热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android中可以作为Log开关的一些操作及安全性详解

Android的调试好伙伴Log在调试时非常有用,基本可以看Log而无需单点调试,尤其对实时大数据量的设备调试尤其有效,下面这篇文章就来给大家详细介绍关于Android中可以作为Log开关的一些操作及安全性的相关资料,需要的朋友可以参考下。

前言

本文主要给大家介绍了关于Android中能够作为Log开关的一些操作及安全性的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。

自定义常量

开发阶段利用 Log 日志方便代码调试是再常见不过的事情。出于安全考虑,这种做法仅限于 Debug 模式,Release 模式下打包发布时一定要关掉。所以在我们的项目中,一定会有一个工具类或者方法来控制 Log 日志的使用,比如:

public class LogUtils {
 
 public static final Boolean DEBUG_MODE = true;
 
 public static void d(String message) {
  if (DEBUG_MODE) {
   Log.d("TAG", message);  
  }
 }
 
}

常见的做法便是像上面这样,自定义一个布尔类型的常量作为开关来控制是否打印日志。但是这种做法有一个弊端,那就是每次发布 Release 包时都需要手动修改这个常量的值为 false,然后下一次开发阶段再手动修改为 true。

虽然是很简单的手动修改操作,但是也很容易忘记。那么有没有一种办法实现自动化管理呢?答案当然是有的,使用 BuildConfig 类。

BuildConfig

类似 R 资源文件,BuildConfig 也是在编译阶段,Gradle 插件自动生成的一个 class 文件。该文件包含一些帮助开发人员辨别当前 build 类型的常量信息。当然你也可以通过 Gradle 提供的定制功能向该文件里面添加其他辅助内容。这里我们看一下默认情况下,BuildConfig 文件都包含有哪些内容:

public final class BuildConfig {
 public static final boolean DEBUG = Boolean.parseBoolean("true");
 public static final String APPLICATION_ID = "com.yifeng.sample";
 public static final String BUILD_TYPE = "debug";
 public static final String FLAVOR = "";
 public static final int VERSION_CODE = 1;
 public static final String VERSION_NAME = "1.0";
}

能够看出,都是一些大家很熟悉的信息。其中包括一个 DEBUG 常量,其值便可用于判断当前 build 类型。debug 模式下为 true,release 模式下为 false。所以,使用 BuildConfig.DEBUG 可以替代前面我们自定义的常量,实现自动管理 Log 日志的打印:

public static void d(String message) {
 if (BuildConfig.DEBUG) {
  Log.d("TAG", message);
 }
}

看上去貌似已经很完美了,但其实还是有瑕疵的。BuildConfig 类文件的生成依据于 Module,也就是说每一个 Module 编译时都会产生自己的这个文件。如果你的主 app module 使用其他依赖 module 中 BuildConfig 文件里面的 DEBUG 值,就需要多加注意。

默认情况下,Library 的构建永远是以 Release 模式执行的,所以其 BuildConfig.DEBUG 值一定是 false!即使主 Module 使用 Debug 模式构建,也是如此。

那么,有没有办法修改 Library Module 的默认构建方式呢?答案也是肯定的。打开对应 Library 的 build.gradle 文件,添加这样一行配置代码:

android {
 // 这里省略其他内容
 publishNonDefault true
}

即表示不使用默认构建方式,编译时也会自动生成其他 build 类型的 BuildConfig 类文件。你可以在相应 Library 路径下查看配置该命令前后 BuildConfig 文件的生成情况,目录地址为:

libraryName/build/generated/source/buildConfig/ + debug/release

然后在我们的主 Module 依赖的时候同时引入 debug 和 release 两种配置,这里以 extras/PullToRefresh 作为 Library 为例,看下依赖代码:

dependencies {
 releaseCompile project(path: ':extras:PullToRefresh', configuration: 'release')
 debugCompile project(path: ':extras:PullToRefresh', configuration: 'debug')
}

如此这般,便可以解决前面提到的依赖 Module 问题。当然,如果你的项目比较简单,只是单一 Module,也就不存在这个问题。

但是如果项目中的依赖 Module 比较多的话,这种处理方式还是略显麻烦。你需要在用到的地方针对每个 Module 逐一处理。其实还有一种更好的解决方案,那就是使用 Manifest 清单文件中 application 标签里的 debuggable 属性。

ApplicationInfo

application 标签里有个 android:debuggable 属性,表示当前应用是否可以被调试(一般不建议手动设置这个属性)。这个属性也会随着 build 类型自动改变。所以,利用这个特性也能判定应用是否处于 Debug 模式,比如:

public static boolean isDebug(Context context) {
 return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
}

控制 Log 日志打印的开关,除了上面讲到的这些方式,其实还有别的方式。比如利用 Gradle 的灵活性在 build.gradle 文件中自定义一个 Boolean 变量,根据 build 类型动态赋值,也能达到我们的目的。

Android自定义Log开关

有时Log太多会影响速度,需要根据需要开关Log,而Android IDE环境没有这个功能,起码Eclipse没有,那么我们可以写一个类将Log封装,通过调用这个类设置boolean变量,控制Log是否有效。

public class MLog
{
public static final boolean DEBUG = true;//开关控制
public static void i(String tag,String msg)
{
if(DEBUG)
{
Log.i(tag,msg);
}
public static void e(String tag,String msg)
{
if(DEBUG)
{
Log.e(tag,msg);
}
//其它级别的同上...
}

使用的时候直接调用MLog替换Log即可。

更安全的 Log 用法

前面所有这些做法都只是使 release 包不去显示 Log 日志,从而提高安全性。但是,有没有想过,如果 apk 被反编译的话,这些 Log 相关的代码还是能够别识别出来,别人只需要稍作修改,重新打包,依旧能够使 Log 重现。

当然,使用常量作为 LogUtils 中的判断条件的话,根据 proguard 的优化规则,在 Release 包中是不包含条件体中的 Log.d 等操作代码的。关于这一点,可以自己反编译 apk 尝试看下。

然而,在其他调用 LogUtils 工具类的地方依旧暴露了我们的意图。所以,定义一个 LogUtils 类虽然提高了使用 Log 的效率,依旧解决不了 Log 安全的问题。相比而言,我们做了这么多努力只是稍微提高了一些安全的门槛而已。

所以,最好的办法就是,Release 包中不包含任何用于调试的 Log 代码(如果使用 LogUtils 的话,也包括 该类的调用)。也就是说,不使用 LogUtils 工具类封装,在任何需要的地方,不嫌麻烦的逐一添加判断条件:(可以使用 Live Template 提高效率)

if (BuildConfig.DEBUG) {
 Log.d("TAG", message);  
}

这样,打包时,开启 proguard 后,Release 包会自动删除上面的代码,彻底根绝 Log 引发的安全问题。关于这一部分的细节操作,可以参考这两篇文章:

  • Android Apk 文件反编译和重新打包的过程分析
  • 如何安全地打印日志

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。


推荐阅读
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 创建项目:Visual Studio Online 入门指南
    本文介绍如何使用微软的 Visual Studio Online(VSO)创建和管理开发项目。作为一款基于云计算的开发平台,VSO 提供了丰富的工具和服务,简化了项目的配置和部署流程。 ... [详细]
  • 在创建新的Android项目时,您可能会遇到aapt错误,提示无法打开libstdc++.so.6共享对象文件。本文将探讨该问题的原因及解决方案。 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 深入理解ExtJS:从入门到精通
    本文详细介绍了ExtJS的功能及其在大型企业前端开发中的应用。通过实例和详细的文件结构解析,帮助初学者快速掌握ExtJS的核心概念,并提供实用技巧和最佳实践。 ... [详细]
  • 本文详细介绍了如何在Python3环境中配置Appium1.4.6,并指导如何连接模拟器进行自动化测试。通过本文,您将了解从环境搭建到模拟器连接的完整流程。 ... [详细]
  • 初探Java编程:从入门到实践
    本文旨在为初学者提供Java编程的基础知识,涵盖程序、算法、流程图的概念,以及JDK环境的配置和Eclipse的使用方法。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
  • 本文详细介绍了如何准备和安装 Eclipse 开发环境及其相关插件,包括 JDK、Tomcat、Struts 等组件的安装步骤及配置方法。 ... [详细]
  • Struts与Spring框架的集成指南
    本文详细介绍了如何将Struts和Spring两个流行的Java Web开发框架进行整合,涵盖从环境配置到代码实现的具体步骤。 ... [详细]
author-avatar
卧龙先生八斗才
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有