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

 更新时间:2017年12月03日 09:30:17   作者:亦枫  
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实现手势密码功能

    Android实现手势密码功能

    这篇文章主要为大家详细介绍了Android实现手势密码功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • Android UI中TextView的使用方法

    Android UI中TextView的使用方法

    这篇文章主要介绍了Android UI中TextView的使用方法的相关资料,希望通过本文大家能掌握TextView的使用方法,需要的朋友可以参考下
    2017-09-09
  • Android实现网易严选标签栏滑动效果

    Android实现网易严选标签栏滑动效果

    这篇文章主要为大家详细介绍了Android实现网易严选标签栏滑动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • Android 自定义View手写签名并保存图片功能

    Android 自定义View手写签名并保存图片功能

    这篇文章主要介绍了Android 自定义View手写签名并保存图片功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2020-03-03
  • HorizontalScrollView水平滚动控件使用方法详解

    HorizontalScrollView水平滚动控件使用方法详解

    这篇文章主要为大家详细介绍了HorizontalScrollView水平滚动控件的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Flutter 控制屏幕旋转的实现

    Flutter 控制屏幕旋转的实现

    这篇文章主要介绍了Flutter 控制屏幕旋转的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 分享五种Android常用布局方式

    分享五种Android常用布局方式

    Android布局是应用界面开发的重要一环,在Android中,共有五种布局方式,分别是:FrameLayout(框架布 局),LinearLayout (线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局),小编通过本文逐一给大家详解
    2015-11-11
  • Android使用EventBus多次接收消息

    Android使用EventBus多次接收消息

    这篇文章主要为大家详细介绍了Android使用EventBus多次接收消息,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • Android属性动画特点详解

    Android属性动画特点详解

    这篇文章主要为大家详细介绍了Android属性动画特点,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Android 夜间模式的实现代码示例

    Android 夜间模式的实现代码示例

    本篇文章主要介绍了Android 夜间模式的实现代码示例,实现能够根据不同的设定,呈现不同风格的界面给用户,有兴趣的可以了解一下。
    2017-03-03

最新评论