>

从而做一些在 澳门博发娱乐官网Debug,项目有一

- 编辑:澳门博发娱乐官网 -

从而做一些在 澳门博发娱乐官网Debug,项目有一

面前全体这一个做法都只是使 release 包不去显得 Log 日志,进而加强安全性。但是,有未有想过,假使 apk 被反编写翻译的话,这几个 Log 相关的代码还能够别识别出来,别人只要求稍作修改,重新包装,仍然能够使 Log 重现。

3. 消除方案

听他们讲地点分析的原由,方今大家有八个思路:
(1) 始终调用最后运维的 Module 的 BuildConfig,因为它未有被别的另外Module 信赖,所以 BuildConfig.DEBUG 值会标准。
(2) 让被依赖的 Module 提供除 Release 版以外的任何版本。

3.1 技术方案一:使用其余的 BuildConfig.java
借使 Lib Module 中可见 import 到外围真正运营 App 的 BuildConfig 就 ok 了,如下:

package cn.trinea.android.lib.util;

/**
 * Utils for App
 * <ul>
 * <li>{@link #syncIsDebug(Context)} Should be called in module Application</li>
 * </ul>
 * Created by Trinea on 2017/3/9.
 */
public class AppUtils {

    private static Boolean isDebug = null;

    public static boolean isDebug() {
        return isDebug == null ? false : isDebug.booleanValue();
    }

    /**
     * Sync lib debug with app's debug value. Should be called in module Application
     *
     * @param context
     */
    public static void syncIsDebug(Context context) {
        if (isDebug == null) {
            try {
                String packageName = context.getPackageName();
                Class buildConfig = Class.forName(packageName + ".BuildConfig");
                Field DEBUG = buildConfig.getField("DEBUG");
                DEBUG.setAccessible(true);
                isDebug = DEBUG.getBoolean(null);
            } catch (Throwable t) {
                // Do nothing
            }
        }
    }
}

因此反射得到真正实行的 Module 的 BuildConfig,在本身的 Application 内调用:

AppUtils.syncIsDebug(getApplicationContext());

这么看起来达到指标了。

但稳重想想会开掘这种施工方案依旧有毛病,因为 BuildConfig.java 的 packageName 是 Module 的 Package Name,即 AndroidManifest.xml 中的 package 属性,而 context.getPackageName() 得到的是应用的 applicationId,这一个 applicationId 通过 build.gradle 是能够修改的。所以当 build.gradle 中的 applicationId 与 AndroidManifest.xml 中的 package 属性分裂等时,上边的反射查找类路线便会出错。

PS:这种方案还大概有个变种正是通过 android.app.ActivityThread.currentPackageName 获得包名,从而节省传递 Context 起始化的步调,但依旧有 applicationId 被改换后类查找不到类似的难点。

Gradle中自定义BuildConfig字段

若是上述暗中同意生成的字段不大概满意开发须求,那就要求在内部参预自定义的字段,如果我们须求投入应用的编写翻译的时日timeStamp, 那大家则要求在gradle中插手该自定义字段:

defaultConfig {
        applicationId "com.qualcomm.qti.faceauth"
        minSdkVersion 24
        buildConfigField("String", "timeStamp", System.currentTimeMills() + "L");
}

通过增添该条属性,那么则会在BuildConfig中自动生成如下字段:

public final class BuildConfig {
  public static final boolean DEBUG = false;
  public static final String APPLICATION_ID = "com.storm.9gag";
  public static final String BUILD_TYPE = "release";
  public static final String FLAVOR = "wandoujia";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  //newly automatically added timeStamp attribute
  public static final String timeStamp = 23800883L;
}

那在代码中央政府机关接能够调用:

String timeStr = BuildConfig.timeStamp;

就能够获取到当下岁月戳的字符串,用于专门的学问逻辑代码的支配等。

当大家对主module举办营造时, 会先构建library module, 但是library的塑造恒久是采取release形式营造的. 使用命令打debug包./gradlew :app:assembleDebug, log输出如下:

从log输出能够领略library module打包情势是运用release方式打包的, 因而BuildConfig.DEBUG的值自然是false了. 假设主module的buildType是release, 那么注重的library module就更别讲了, buildType肯定是release../gradlew :app:assembleRelease
打release包, log输出如下:

虽说是很简单的手动修改操作,不过也很轻松忘记。那么有未有一种方式落实自动化管理吗?答案当然是部分,使用 BuildConfig 类。

Android 开辟中平时会经过 BuildConfig.DEBUG 决断是否是 Debug 方式,进而做一些在 Debug 形式才展开的奇怪操作,比方打印日志。那样好处是不要在揭露前去主动修改,因为那一个值在 Debug 情势下为 true,Release 形式下为 false。

BuildConfig的用法

在Android开荒中,大家运用android.util.Log来打字与印刷日志,方便我们的成本调节和测量检验。可是这么些代码不想在揭破后进行,我们并不想在软件发表后调节和测量检验日志被另外开荒者见到,现在自家的点子是安装贰个全局变量,标识软件为Debug方式仍旧Release情势。来看下代码:

public class Log {
    private static final boolean DEBUG = true;

    public static void i(String tag, String msg) {
        if (DEBUG)
            android.util.Log.i(tag, msg);
    }

    public static void e(String tag, String msg) {
        if (DEBUG)
            android.util.Log.e(tag, msg);
    }

    public static void d(String tag, String msg) {
        if (DEBUG)
            android.util.Log.d(tag, msg);
    }

    public static void v(String tag, String msg) {
        if (DEBUG)
            android.util.Log.v(tag, msg);
    }

    public static void w(String tag, String msg) {
        if (DEBUG)
            android.util.Log.w(tag, msg);
    }
}

如此打包宣布在此以前如若改下DEBUG=false就行了,可是每趟在发表以前都要手动去改那一个变量,不是很有益于,而且不拔除开采者忘记改的情事。那么有未有更加好更方便的做法吧?
ADT(r17)发表之后,谷歌为大家提供了一种新的调节和测量检验机制,即BuildConfig.DEBUG。

ADT 17.0.0的New build features第二条之类描述:

Added a feature that allows you to run some code only in debug mode. Builds now generate a class called BuildConfig containing a DEBUG constant that is automatically set according to your build type. You can check the (BuildConfig.DEBUG) constant in your code to run debug-only functions.

增产了一个特点,允许开发者只在Debug方式下运转部分代码。Builds会生成贰个叫做BuildConfig的类,该类包含一个名叫DEBUG的常量,其常量值会依据开荒者的Build类型自动设定。如此,便足以运用BuildConfig.DEBUG来贯彻只在Debug格局下运维的代码。

故此只须要将如下代码实行更换就能够,而该值会自动依照前段时间项指标编写翻译格局(debug/release)进行翻新:

private static final boolean DEBUG = BuildConifg.DEBUG;

而在编写翻译完结后,大家得以看看在如下路线中会自动生成该BuildConfig.java文件:

app/build/source/BuildConfig/Build Varients/package name/BuildConfig

本来除了DEBUG字段之外,还带有如下内容:

public final class BuildConfig {
  public static final boolean DEBUG = false;
  public static final String APPLICATION_ID = "com.storm.9gag";
  public static final String BUILD_TYPE = "release";
  public static final String FLAVOR = "wandoujia";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
}

android {
publishNonDefault true
}

在library的build.gradle文件中增添上边代码:

能够看出,都以一对我们很熟识的音讯。在那之中囊括叁个 DEBUG 常量,其值便可用于判定当前 build 类型。debug 方式下为 true,release 格局下为 false。所以,使用 BuildConfig.DEBUG 能够代替前边大家自定义的常量,达成全自动处理 Log 日志的打字与印刷:

2. 原因

BuildConfig.java 是编写翻译时自动生成的,况且各个 Module 都会生成一份,以该 Module 的 packageName 为 BuildConfig.java 的 packageName。所以只要您的使用有八个 Module 就能够有三个 BuildConfig.java 生成,而地方的 Lib Module import 的是上下一心的 BuildConfig.java,编写翻译时被信赖的 Module 暗中同意会提供 Release 版给别的Module 或工程应用,那就导致该 BuildConfig.DEBUG 会始终为 false。

>Note that this publishing configuration name references the full variant name. *Release* and *debug* are only applicable when there are no flavors. If you wanted to change the default published variant while using flavors, you would write:

>```
android {
    defaultPublishConfig "flavor1Debug"
}

这么一来, library module中的BuildConfig.DEBUG的值永久都以false. 如《Android: 使用BuildConfig.DEBUG优化你的Log输出 & 开启混淆(proguard)的优化布局》一文中所说把DevUtil工具类放到公共库中以便代码重用
, DevUtil是不可能平常干活的, 因为依赖库总是以release方式打包, 导致BuildConfig.DEBUG的值总是false, 进而导致log永远不可能输出. 那么消除DevUtil工具类的log输出难点, 就改为了化解正视库的打包难点.
实际那一个包裹难点很已经有人提议来了, 大约时贰零壹贰年七月的时候
有关那个标题标issue地址: https://code.google.com/p/android/issues/detail?id=52962
二. 建设方案issue上有比比较多hack, 上边就介绍个中一种相比精简的hack, 如图:

libraryName/build/generated/source/buildConfig/ + debug/release
1. 问题

假如运用独有贰个 Module 未有毛病,Debug 形式下 BuildConfig.DEBUG 会始终为 true。要是前些天有七个 Module,分别为 App 和 Lib,且 App 依赖Lib,在 Lib 内有工具类 LogUtils,代码如下:

package cn.trinea.android.lib.util;

import android.util.Log;
import cn.trinea.android.lib.util.BuildConfig;

public class LogUtils {

    public static void d(String log) {
        if (BuildConfig.DEBUG) {
            Log.d("trinea-debug", log);
        }
    }
    ……
}

当大家在 App Module 内调用 LogUtils 时大家会发觉向来无法打字与印刷日志,因为地点的 BuildConfig.DEBUG 会始终为 false。为何吧?

二. 解决方案
issue上有非常多hack, 上边就介绍个中一种相比较轻易的hack, 如图:

a. 测验意况: AndroidStudio2.2 + Gradle Plugin 2.2.0 + Gradle 2.14.1
b. 在AndroidStudio中开创三个品种, 项目有三个主module和三个library module, 目录结构如下:

这么,便得以消除日前提到的信赖 Module 难点。当然,若是您的种类相比较轻便,只是单纯 Module,也就一纸空文那几个标题。

3.2 技术方案二:被信任的 Module 提供其余版本

让被信任的 Module 提供除 Release 版以外的任何版本,这种方案供给将具备被信赖 library 中加上:

android {
    publishNonDefault true
}

代表该 Module 打包时会同期包装别的版本,包蕴 Debug 版。何况供给在 App Module 上将其借助的 library 如下每一种加多:

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

意味着信赖分歧版本的依靠 Module。
不过这种艺术具备 Module 配置都急需修改,侵入性太强。

......
:library:packageReleaseRenderscript UP-TO-DATE
:library:packageReleaseResources UP-TO-DATE
:library:processReleaseJavaRes UP-TO-DATE
:library:transformResourcesWithMergeJavaResForRelease UP-TO-DATE
:library:transformClassesAndResourcesWithSyncLibJarsForRelease UP-TO-DATE
:library:mergeReleaseJniLibFolders UP-TO-DATE
:library:transformNative_libsWithMergeJniLibsForRelease UP-TO-DATE
:library:transformNative_libsWithSyncJniLibsForRelease UP-TO-DATE
:library:bundleRelease UP-TO-DATE
......
:app:packageRelease
:app:assembleRelease

BUILD SUCCESSFUL

Total time: 20.195 secs

如此那般library库中的BuildConfig.DEBUG就能依照buildType生成分化的值.
论及到DevUtil工具类的地点, 能够整合《Android: 使用BuildConfig.DEBUG优化你的Log输出 & 开启混淆(proguard)的优化配置》阅读

if (BuildConfig.DEBUG) { Log.d("TAG", message); }
3.3 最终施工方案:使用 ApplicationInfo.FLAG_DEBUGGABLE

既然如此 BuildConfig 的不二等秘书诀行不通,我们反编写翻译 Debug 包和 Release 包相比较看看有未有别的的差别,会开采她们 AndroidManifest.xml 中 application 节点的 android:debuggable 值是例外的。Debug 包值为 true,Release 包值为 false,那是编写翻译自动修改的。所以大家着想通过 ApplicationInfo 的那个性子去看清是或不是是 Debug 版本,如下:

package cn.trinea.android.lib.util;

/**
 * Utils for App
 * <ul>
 * <li>{@link #syncIsDebug(Context)} Should be called in module Application</li>
 * </ul>
 * Created by Trinea on 2017/3/9.
 */
public class AppUtils {

    private static Boolean isDebug = null;

    public static boolean isDebug() {
        return isDebug == null ? false : isDebug.booleanValue();
    }

    /**
     * Sync lib debug with app's debug value. Should be called in module Application
     *
     * @param context
     */
    public static void syncIsDebug(Context context) {
        if (isDebug == null) {
            isDebug = context.getApplicationInfo() != null &&
                    (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        }
    }
}

在团结的 Application 内调用进行初始化,

AppUtils.syncIsDebug(getApplicationContext());

这么之后调用 AppUtils.isDebug() 就可以判别是不是是 Debug 版本,比如在地点的 LogUtils 中。同不经常间适用于 Module 是 Lib 和 applicationId 被修改的图景,比 BuildConfig.DEBUG 可信的多。

这么些方案有个注意事项正是温馨 App Module 中无法主动设置 android:debuggable,不然无论 Debug 照旧 Release 版会始终是安装的值。当然笔者就一贯不自行安装的画龙点睛。

原著地址:http://www.trinea.cn/android/android-whether-debug-mode-why-buildconfig-debug-always-false/

//省略其余配置
......
......


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:24.2.1'

    //依赖library
    debugCompile project(path: ':library', configuration: 'allDebug')
    releaseCompile project(path: ':library', configuration: 'allRelease')

    //省略其余依赖
    .....
    .....
}
在 [《Android: 使用BuildConfig.DEBUG优化你的Log输出 & 开启混淆(proguard)的优化配置》]
(http://www.jianshu.com/p/658eb18838df) 这篇中推荐把
DevUtil放到公共库中去, 以方便重用, 但是这里有个巨坑: **主
module对library module的依赖都是release依赖**

澳门博发娱乐官网 1image.png

  1. 在library的build.gradle文件中增多上面代码:

一. 坑

本文由胜博发-编程发布,转载请注明来源:从而做一些在 澳门博发娱乐官网Debug,项目有一