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 文件反编译和重新打包的过程分析
  • 如何安全地打印日志

总结

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

(0)

相关推荐

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

    前言 本文主要给大家介绍了关于Android中能够作为Log开关的一些操作及安全性的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 自定义常量 开发阶段利用 Log 日志方便代码调试是再常见不过的事情.出于安全考虑,这种做法仅限于 Debug 模式,Release 模式下打包发布时一定要关掉.所以在我们的项目中,一定会有一个工具类或者方法来控制 Log 日志的使用,比如: public class LogUtils { public static final Bool

  • Android编程之基于Log演示一个activity生命周期实例详解

    本文实例讲述了Android编程之基于Log演示一个activity生命周期.分享给大家供大家参考,具体如下: 利用Android的Log 演示一个activity的生命周期 代码: //DemoActivity.java package uni.activity; /* @author octobershiner 2011 7 22 SE.HIT */ import android.app.Activity; import android.os.Bundle; import android.u

  • Android中使用am命令实现在命令行启动程序详解

    在Android中,除了从界面上启动程序之外,还可以从命令行启动程序,使用的是命令行工具am. 复制代码 代码如下: usage: am [subcommand] [options] start an Activity: am start [-D]         -D: enable debugging send a broadcast Intent: am broadcast start an Instrumentation: am instrument [flags]         -r

  • Android中系统自带锁WalkLock与KeyguardLock用法实例详解

    本文实例讲述了Android中系统自带锁WalkLock与KeyguardLock用法.分享给大家供大家参考,具体如下: WalkLock - 顾名思义 唤醒锁 点亮屏幕用的 KeyguardLock - 顾名思义 键盘锁 解锁键盘用的 详细介绍: 1: WalkLock 唤醒锁 - WalkLock真的能点亮屏幕吗? 答案是肯定的. 可是有时候为什么不点亮屏幕,这个就是参数设置的问题了. 复制代码 代码如下: PowerManager.newWakeLock(PowerManager.FULL

  • Android中GIF动图的播放控制和监听详解

    前言 最近接手的项目里涉及到了 GIF 动图的播放与监听,在上一版本中对于 GIF 的处理是由 H5 来实现的,因为考虑到用户体验,因此现在的需求是将这块儿原生化,途中差点误入歧途!下面来看看详细的介绍吧. Android 中 GIF 动图处理与监听 刚开始第一个想到的便是 glide , 但是自认为 glide 不能够控制 GIF 以及去监听它,所以网上去搜寻别的方法.看到有一个方案是将图片分帧,一张张的去用逐帧动画来实现. 我开始怀疑给这个解决方案的人了,都什么时代了还做这种费力不讨好,大量

  • Android中使用socket通信实现消息推送的方法详解

    原理 最近用socket写了一个消息推送的demo,在这里和大家分享一下. 主要实现了:一台手机向另外一台手机发送消息,这两台手机可以随时自由发送文本消息进行通信,类似我们常用的QQ. 效果图: 原理:手机通过socket发送消息到服务器,服务器每接收到一条消息之后,都会把这条消息放进一个messageList里面,服务器会不停地检测messageList是否含有消息,如果有的话就会根据messageList里面item的数据,推送到相应的另一端手机上面. 下面简单画了一个图来说明这个原理: 演

  • 基于Android中Webview使用自定义的javascript进行回调的问题详解

    先说为什么需要讨论这个问题. 现在很多的手机应用,都可能会直接嵌入一个web页面.这样做的好处:一个是功能更新方便,维护起来容易,只需要维护服务器的页面即可,不需要更新客户端:另一个是功能通用,不仅android可以用,ios也可以用,symbian也可以直接用. 那为什么现在很多手机应用并不做成web方式的呢?原因很多.一个是现阶段web方式展现能力相对较弱,如果对于应用的美观程度要求比较高,就无法使用web方式:一个是web方式速度相对较慢,用户体验会受一些影响:一个是现阶段流量还是相对宝贵

  • Android中一种效果奇好的混音方法详解

    初识音频 从初中物理上我们就学到,声音是一种波.计算机只能处理离散的信号,通过收集足够多的离散的信号,来不断逼近波形,这个过程我们叫做采样.怎么样才能更好的还原声音信息呢?这里很自然引出两个概念了. 采样频率(Sample Rate):每秒采集声音的数量,它用赫兹(Hz)来表示. 采样率越高越靠近原声音的波形,常见的采样率有以下几种: 8khz:电话等使用,对于记录人声已经足够使用. 22.05khz:广播使用频率. 44.1kb:音频CD. 48khz:DVD.数字电视中使用. 96khz-1

  • Android封装对原生Log进行封装的操作

    我就废话不多说了,大家还是直接看代码吧~ package com.zjx.taobaounion.utils; import android.util.Log; public class LogUtils { private static int currentLev = 4; // 当前log等级 上线之后控制这个等级 就可以减少Log的输出 private static final int DEBUG_LEV = 4; // debug 等级 private static final int

  • 在Android中查看当前Activity是否销毁的操作

    进入到Android-sdk中platform-tools目录 在命令行中执行以下命令 adb shell dumpsys activity>activity.txt 可以将当前的四大组件 (Activity,Service,BroadCase,ContentProvider) 的存在情况打印到当前目录的activity.txt文件中 然后进入打印文件搜索: ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities) 补充知识:打开另一个A

随机推荐