android软件的配置书,开发一个优秀的Android应用你必须要加入的代码及配置

1 . 开发一个Android App我们一般需要继承Application来初始化一些配置,如下所示:

a. Application中有一个registerActivityLifecycleCallbacks()方法,可以在回调中把整个应用打开的Activity保存在集合中、销毁的Activity重集合中删除。个人觉得这种方式比BaseActivity的方式或者每打开一个Activity把当前的引用加入到集合中的方式优雅多了,推荐大家用这种方式。关闭应用也非常方便,遍历保存Activity的集合,�执行finish()就好。

/**

* 注册ActivityListener

*/

private void registerActivityListener() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

@Override

public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

if (null == mActivitys) {

return;

}

mActivitys.add(activity);

}

@Override

public void onActivityStarted(Activity activity) {}

@Override

public void onActivityResumed(Activity activity) {}

@Override

public void onActivityPaused(Activity activity) {}

@Override

public void onActivityStopped(Activity activity) {}

@Override

public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

@Override

public void onActivityDestroyed(Activity activity) {

if (null == activity && mActivitys.isEmpty()) {

return;

}

if (mActivitys.contains(activity)) {

mActivitys.remove(activity);

}

}

});

}

}

b. 严苛模式StrictMode:建议大家在Debug版本打开严苛模式。 例如:严苛模式下可以检测到你应用中没有关闭的流,可以减少OOM,如下所示,可以看到在在控制台严苛模式模式下的Log输出。

cdc24240f3ca

image.png

ThreadPolicy线程策略检测

自定义的耗时调用 使用detectCustomSlowCalls()开启

磁盘读取操作 使用detectDiskReads()开启

磁盘写入操作 使用detectDiskWrites()开启

网络操作 使用detectNetwork()开启

VmPolicy虚拟机策略检测

Activity泄露 使用detectActivityLeaks()开启

未关闭的Closable对象泄露 使用detectLeakedClosableObjects()开启

泄露的Sqlite对象 使用detectLeakedSqlLiteObjects()开启

检测实例数量 使用setClassInstanceLimit()开启

/**严苛模式主要检测两大问题,一个是线程策略,即TreadPolicy,另一个是VM策略,即VmPolicy。*/

if (AppConfig.IS_DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());

}

c .在onCreate中,检测当前进程名称是否为应用包名,否则return (像百度地图等sdk需要在单独的进程中执行,会多次执行Application的onCreate()方法,所以为了只初始化一次应用配置,作此判断),代码如下:

/**检测当前进程名称是否为应用包名,否则return (像百度地图等sdk需要在单独的进程中执行,会多次执行Application的onCreate()方法,所以为了只初始化一次应用配置,作此判断)*/

if (!CommonUtil.getCurProcessName(this).equals(getPackageName())) {

return;

}

d . �Crash全局异常捕获,用到了一个第三方库,使用方法如下:

compile 'cat.ereza:customactivityoncrash:1.5.0'

CustomActivityOnCrash.install(this);

应用发生异常时customactivityoncrash库�会打开一个如下图所示的Activity页面,可以查看错误。

cdc24240f3ca

image.png

e .其他配置初始化

private void init() {

/**注册ActivityListener*/

registerActivityListener();

/**crash异常捕获*/

if (AppConfig.IS_DEBUG) {

CustomActivityOnCrash.install(this);

}

/**初始化base url*/

if (AppConfig.IS_DEBUG) {

final String base_url = SPUtils.getString(SPUtils.DEFAULT_FILE_NAME, SharePrefsConstant.SP_BASE_URL, "");

if (TextUtils.isEmpty(base_url)) return;

AppConfig.updateAllUrl(base_url);

}

/**初始化LeakCanary */

if (AppConfig.IS_DEBUG) {

if (LeakCanary.isInAnalyzerProcess(this)) {

return;

}

LeakCanary.install(this);

}

}

2 .�完整MyApplication代码,如下所示:

public class MyApplication extends Application {

private static MyApplication application;

/**

* 维护Activity的List

*/

private static List mActivitys = Collections.synchronizedList(new LinkedList());

@Override

public void onCreate() {

/**严苛模式主要检测两大问题,一个是线程策略,即TreadPolicy,另一个是VM策略,即VmPolicy。*/

if (AppConfig.IS_DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build());

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build());

}

super.onCreate();

application = this;

/**检测当前进程名称是否为应用包名,否则return (像百度地图等sdk需要在单独的进程中执行,会多次执行Application的onCreate()方法,所以为了只初始化一次应用配置,作此判断)*/

if (!CommonUtil.getCurProcessName(this).equals(getPackageName())) {

return;

}

/**初始化一些应用配置*/

init();

}

private void init() {

/**注册ActivityListener*/

registerActivityListener();

/**crash异常捕获*/

if (AppConfig.IS_DEBUG) {

CustomActivityOnCrash.install(this);

}

/**初始化base url*/

if (AppConfig.IS_DEBUG) {

final String base_url = SPUtils.getString(SPUtils.DEFAULT_FILE_NAME, SharePrefsConstant.SP_BASE_URL, "");

if (TextUtils.isEmpty(base_url)) return;

AppConfig.updateAllUrl(base_url);

}

/**初始化LeakCanary */

if (AppConfig.IS_DEBUG) {

if (LeakCanary.isInAnalyzerProcess(this)) {

return;

}

LeakCanary.install(this);

}

}

public static MyApplication getApplication() {

return application;

}

public static void finishAllActivity() {

if (mActivitys == null || mActivitys.isEmpty()) {

return;

}

for (Activity activity : mActivitys) {

activity.finish();

}

}

/**

* 获取当前Activity(栈中最后一个压入得)

*/

public static Activity getCurrentActivity() {

if (mActivitys == null || mActivitys.isEmpty()) {

return null;

}

Activity activity = mActivitys.get(mActivitys.size() - 1);

return activity;

}

/**

* 注册ActivityListener

*/

private void registerActivityListener() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {

@Override

public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

if (null == mActivitys) {

return;

}

mActivitys.add(activity);

}

@Override

public void onActivityStarted(Activity activity) {}

@Override

public void onActivityResumed(Activity activity) {}

@Override

public void onActivityPaused(Activity activity) {}

@Override

public void onActivityStopped(Activity activity) {}

@Override

public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

@Override

public void onActivityDestroyed(Activity activity) {

if (null == activity && mActivitys.isEmpty()) {

return;

}

if (mActivitys.contains(activity)) {

mActivitys.remove(activity);

}

}

});

}

}

}

3 . 应用的入口SplashActivity的onCreate方法中要加入如下代码,解决首次安装应用,点击应用图标打开应用,点击home健回到桌面,再次点击应用图标,进入应用时多次初始化SplashActivity的问题

/**在应用的入口activity加入以下代码,解决首次安装应用,点击应用图标打开应用,点击home健回到桌面,再次点击应用图标,进入应用时多次初始化SplashActivity的问题*/

if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {

finish();

return;

}

if (!isTaskRoot()) {

finish();

return;

}

4 . �app下的build.gradle配置,代码如下

apply plugin: 'com.android.application'

apply plugin: 'com.antfortune.freeline'

android {

//国内镜像地址来下载 $ ./gradlew initFreeline -Pmirror

freeline {

hack true

productFlavor 'zyp'

}

compileSdkVersion rootProject.ext.compileSdkVersion

buildToolsVersion rootProject.ext.buildToolsVersion

defaultConfig {

applicationId "com.zyp"

minSdkVersion rootProject.ext.minSdkVersion

targetSdkVersion rootProject.ext.targetSdkVersion

versionCode rootProject.ext.versionCode

versionName rootProject.ext.versionName

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

vectorDrawables.useSupportLibrary = true

}

signingConfigs {

debug {

storeFile file("debug.keystore")

}

release {

storeFile file("release.keystore")

// storeFile file("release.jks")

keyAlias 'androiddebugkey'

storePassword 'android'

keyPassword 'android'

}

}

buildTypes {

debug {

applicationIdSuffix ".debug"

manifestPlaceholders = [app_label: "@string/app_name_debug"]

manifestPlaceholders = [UMENG_CHANNEL_VALUE: "zyp"]

manifestPlaceholders = [BAIDU_API_KEY_VALUE: "CC939499621bc8191c63799999b1f987", UMENG_APPKEY_VALUE: "4ef289045270156bd6999998"]

buildConfigField "String", "BASE_URL", "\"https://api.test\""

buildConfigField "String[]", "BASE_TEST_URL", "{\"https://api.test\", \"https://api.test1\", \"https://api.test2\", \"https://api.test3\", \"https://api.test4\"}"

buildConfigField "boolean", "IS_LOG", "true"

buildConfigField "boolean", "IS_DEBUG", "true"

debuggable true

zipAlignEnabled false

shrinkResources false

minifyEnabled false

signingConfig signingConfigs.debug

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}

release {

manifestPlaceholders = [app_label: "@string/app_name"]

manifestPlaceholders = [UMENG_CHANNEL_VALUE: "zyp"]

manifestPlaceholders = [BAIDU_API_KEY_VALUE: "CC939499621bc8191c63799999b1f987", UMENG_APPKEY_VALUE: "4ef289045270156bd6999998"]

buildConfigField "String", "BASE_URL", "\"https://api.release\""

buildConfigField "String[]", "BASE_TEST_URL", "{\"https://api.release1\", \"https://api.release2\"}"

buildConfigField "boolean", "IS_LOG", "false"

buildConfigField "boolean", "IS_DEBUG", "false"

debuggable false

zipAlignEnabled true

shrinkResources true

minifyEnabled true

signingConfig signingConfigs.release

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}

}

applicationVariants.all { variant ->

variant.outputs.each { output ->

def outputFile = output.outputFile

def fileName

if (outputFile != null && outputFile.name.endsWith('.apk')) {

// 输出apk名称为zyp_v1.0.0_wandoujia.apk

if (variant.buildType.name.equals('release')) {

fileName = "zyp_v${defaultConfig.versionName}_${variant.productFlavors[0].name}_release.apk"

} else if (variant.buildType.name.equals('debug')) {

fileName = "zyp_v${defaultConfig.versionName}_${variant.productFlavors[0].name}_debug.apk"

}

output.outputFile = new File(outputFile.parent, fileName)

}

}

}

// 友盟多渠道打包

productFlavors {

zyp {}

// _360yingyong {}

// yingyongbao {}

// baidushouzhu {}

// xiaomi {}

// wandoujia {}

// anzhi {}

// jifeng {}

// liantongwo {}

// yidongmm {}

// huawei {}

// lianxiang {}

// meizu {}

// oppo {}

// leshi {}

// mumayi {}

// nduowang {}

// wangyi {}

// sinaweibo {}

// sougoushouzhu {}

// google {}

// samsung {}

// vivo{}

}

productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]

}

dexOptions {

preDexLibraries = false

jumboMode = false

javaMaxHeapSize "4g"

}

lintOptions {

checkReleaseBuilds false

abortOnError false

}

packagingOptions {

exclude 'META-INF/LICENSE.txt'

exclude 'LICENSE.txt'

exclude 'META-INF/NOTICE.txt'

exclude 'META-INF/DEPENDENCIES.txt'

exclude 'META-INF/LICENSE.txt'

exclude 'META-INF/NOTICE'

exclude 'META-INF/LICENSE'

exclude 'META-INF/DEPENDENCIES'

exclude 'META-INF/notice.txt'

exclude 'META-INF/license.txt'

exclude 'META-INF/dependencies.txt'

exclude 'META-INF/LGPL2.1'

exclude 'META-INF/rxjava.properties'

}

compileOptions {

sourceCompatibility JavaVersion.VERSION_1_7

targetCompatibility JavaVersion.VERSION_1_7

}

sourceSets.main {

// jniLibs.srcDirs = ['libs/jniLibs']

}

}

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

androidTestCompile("com.android.support.test.espresso:espresso-core:${espressoCore}", {

exclude group: 'com.android.support', module: 'support-annotations'

})

testCompile "junit:junit:${junit}"

compile "com.android.support:appcompat-v7:${appcompatV7}"

compile "com.android.support.constraint:constraint-layout:${constraintLayout}"

compile "com.android.support:design:${design}"

compile "com.android.support:support-vector-drawable:${supportVectorDrawable}"

compile "cat.ereza:customactivityoncrash:${customactivityoncrash}"

debugCompile "com.squareup.leakcanary:leakcanary-android:${leakcanaryVersion}"

releaseCompile "com.squareup.leakcanary:leakcanary-android-no-op:${leakcanaryVersion}"

testCompile "com.squareup.leakcanary:leakcanary-android-no-op:${leakcanaryVersion}"

}

5 . 应用根目录下得build.gradle文件配置,代码如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

ext {

compileSdkVersion = 25

buildToolsVersion = "25.0.3"

minSdkVersion = 15

targetSdkVersion = 22

versionCode = 1

versionName = "1.0.0"

espressoCore = "2.2.2"

junit = "4.12"

constraintLayout = "1.0.2"

customactivityoncrash = "1.5.0"

leakcanaryVersion = "1.5.1"

appcompatV7 = "25.3.1"

design = "25.3.1"

supportVectorDrawable = "25.3.1"

}

buildscript {

repositories {

jcenter()

mavenCentral()

maven { url 'https://jitpack.io' }

}

dependencies {

classpath 'com.android.tools.build:gradle:2.3.0'

classpath 'com.antfortune.freeline:gradle:0.8.7'

// NOTE: Do not place your application dependencies here; they belong

// in the individual module build.gradle files

}

}

allprojects {

repositories {

jcenter()

}

}

6 . 应用的混淆配置文件,代码如下:

-keepclassmembers class fqcn.of.javascript.interface.for.webview {

public *;

}

#webView js调用不混淆,否则取不到数据

-keepclassmembers class com.zyp.ui.WebActivity$* {

;

}

#shrink,测试后发现会将一些无效代码给移除,即没有被显示调用的代码,该选项 表示 不启用 shrink。

#-dontshrink

#指定重新打包,所有包重命名,这个选项会进一步模糊包名,将包里的类混淆成n个再重新打包到一个个的package中

#-flattenpackagehierarchy

#优化时允许访问并修改有修饰符的类和类的成员

-allowaccessmodification

#不跳过(混淆) jars中的 非public classes 默认选项

-dontskipnonpubliclibraryclassmembers

#忽略警告

-ignorewarnings

#指定代码的压缩级别

-optimizationpasses 5

#不使用大小写混合类名

-dontusemixedcaseclassnames

#不去忽略非公共的库类

-dontskipnonpubliclibraryclasses

#不启用优化 不优化输入的类文件

-dontoptimize

#不预校验

-dontpreverify

#混淆时是否记录日志

-verbose

#混淆时所采用的算法

-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#保护注解

-renamesourcefileattribute SourceFile

#保持源文件和行号的信息,用于混淆后定位错误位置

-keepattributes SourceFile,LineNumberTable

#保持含有Annotation字符串的 attributes

-keepattributes *Annotation*

#过滤泛型

-keepattributes Signature

-keepattributes Exceptions,InnerClasses

-dontwarn org.apache.**

-dontwarn android.support.**

#基础配置

# 保持哪些类不被混淆

# 系统组件

-keep public class * extends android.app.Fragment

-keep public class * extends android.app.Activity

-keep public class * extends android.app.Application

-keep public class * extends android.app.Service

-keep public class * extends android.content.BroadcastReceiver

-keep public class * extends android.content.ContentProvider

-keep public class * extends android.app.backup.BackupAgentHelper

-keep public class * extends android.preference.Preference

-keep public class com.android.vending.licensing.ILicensingService

#如果有引用v4包可以添加下面这行

-keep public class * extends android.support.v4.app.Fragment

#自定义View

-keep public class * extends android.view.View

# V4,V7

-keep class android.support.constraint.**{ *; }

-keep class android.support.v4.**{ *; }

-keep class android.support.v7.**{ *; }

-keep class android.webkit.**{*;}

-keep interface android.support.v4.app.** { *; }

#保持 本化方法及其类声明

-keepclasseswithmembers class * {

native ;

}

#保持view的子类成员: getter setter

-keepclassmembers public class * extends android.view.View {

void set*(***);

*** get*();

}

#保持Activity的子类成员:参数为一个View类型的方法 如setContentView(View v)

-keepclassmembers class * extends android.app.Activity {

public void *(android.view.View);

}

#保持枚举类的成员:values方法和valueOf (每个enum 类都默认有这两个方法)

-keepclassmembers enum * {

public static **[] values();

public static ** valueOf(java.lang.String);

}

#保持Parcelable的实现类和它的成员:类型为android.os.Parcelable$Creator 名字任意的 属性

-keep class * implements android.os.Parcelable {

public static final android.os.Parcelable$Creator *;

}

#保持 任意包名.R类的类成员属性。 即保护R文件中的属性名不变

-keepclassmembers class **.R$* {

public static ;

}

# 记录生成的日志数据,在 proguard 目录下

-dump class_files.txt

-printseeds seeds.txt

-printusage unused.txt

-printmapping mapping.txt

-keepclasseswithmembernames class * {

native ;

}

-keepclasseswithmembers class * {

public (android.content.Context, android.util.AttributeSet);

}

-keepclasseswithmembers class * {

public (android.content.Context, android.util.AttributeSet, int);

}

-keepclassmembers class * extends android.app.Activity {

public void *(android.view.View);

}

-keepclassmembers enum * {

public static **[] values();

public static ** valueOf(java.lang.String);

}

-keep class * implements android.os.Parcelable {

public static final android.os.Parcelable$Creator *;

}

-keepnames class * implements android.os.Parcelable {

public static final ** CREATOR;

}

-dontwarn java.util.**

-keep class java.util.** {*; }

-dontwarn org.apache.http.**

-keep class org.apache.http.** {*; }

-keepclassmembers class * implements java.io.Serializable {

static final long serialVersionUID;

private static final java.io.ObjectStreamField[] serialPersistentFields;

private void writeObject(java.io.ObjectOutputStream);

private void readObject(java.io.ObjectInputStream);

java.lang.Object writeReplace();

java.lang.Object readResolve();

}

-keep public class * implements java.io.Serializable {*;}

-keepclassmembers class **.R$* {

public static ;

}

# ======================= 以上是混淆的基础配置================================

# ======================= 以下是混淆的第三方包的配置================================

# ======================= Gson 混淆================================

-keepattributes *Annotation*

-keep class sun.misc.Unsafe { *; }

-keep class com.idea.fifaalarmclock.entity.***

-keep class com.google.gson.stream.** { *; }

# ======================= Umeng 混淆================================

-keepclassmembers class * {

public (org.json.JSONObject);

}

#这是由于SDK中的部分代码使用反射来调用构造函数, 如果被混淆掉, 在运行时会提示"NoSuchMethod"错误。

#另外,由于SDK需要引用导入工程的资源文件,通过了反射机制得到资源引用文件R.java,但是在开发者通过proguard等混淆/优化工具处理apk时,proguard可能会将R.java删除,如果遇到这个问题,请在proguard配置文件中添加keep命令如:

-keep public class com.zyp.R$*{

public static final int *;

}

-keep class com.umeng.**

-keep public class com.idea.fifaalarmclock.app.R$*{

public static final int *;

}

-keep public class com.umeng.fb.ui.ThreadView {

}

-dontwarn com.umeng.**

-dontwarn org.apache.commons.**

-keep public class * extends com.umeng.**

-keep class com.umeng.** {*; }

# ======================= pinying4j 混淆================================

-dontwarn com.hp.hpl.sparta.**

-keep class com.hp.hpl.sparta.**{*;}

-dontwarn net.sourceforge.pinyin4j.**

-keep class net.sourceforge.pinyin4j.**{*;}

-dontwarn demo.**

-keep class demo.**{*;}

# ======================= volley 混淆================================

-dontwarn com.android.volley.**

-keep class com.android.volley.**{*;}

# ======================= fastjson 混淆================================

-dontwarn com.alibaba.fastjson.**

-keep class com.alibaba.fastjson.** { *; }

# ======================= alipay 混淆================================

-keep class com.alipay.android.app.IAlixPay{*;}

-keep class com.alipay.android.app.IAlixPay$Stub{*;}

-keep class com.alipay.android.app.IRemoteServiceCallback{*;}

-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}

-keep class com.alipay.sdk.app.PayTask{ public *;}

-keep class com.alipay.sdk.app.AuthTask{ public *;}

-keep class com.alipay.mobilesecuritysdk.*

-keep class com.ut.*

# ======================= weixin 混淆================================

-keep class com.tencent.mm.** { *; }

# ======================= okio ================================

-dontwarn okio.**

-keep class okio.**{*;}

-keep interface okio.**{*;}

# ======================= activation.jar ================================

-dontwarn javax.activation.**

-keep class javax.activation.**{*;}

-dontwarn com.sun.activation.registries.**

-keep class com.sun.activation.registries.**{*;}

# ======================= additionnal.jar ================================

-dontwarn myjava.awt.datatransfer.**

-keep class myjava.awt.datatransfer.**{*;}

-dontwarn org.apache.harmony.**

-keep class org.apache.harmony.**{*;}

# ======================= RxAndroid,RxJava ================================

-dontwarn sun.misc.**

-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {

long producerIndex;

long consumerIndex;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {

rx.internal.util.atomic.LinkedQueueNode producerNode;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {

rx.internal.util.atomic.LinkedQueueNode consumerNode;

}

#======================= httpmime =======================

-keep class org.apache.http.entity.mime.** {*;}

#======================= zxing =======================

-keep class com.google.zxing.** { *; }

#======================= simplelatlng =======================

-keep class com.javadocmd.simplelatlng.** {*;}

# =======================universal-image-loader ================================

-keep class com.nostra13.universalimageloader.** {*;}

# ======================= 百度地图 ================================

-keep class com.baidu.** {*;}

-keep class vi.com.** {*;}

-dontwarn com.baidu.**

# ======================= 高德地图 ================================

# 3D 地图

-keep class com.amap.api.maps.**{*;}

-keep class com.autonavi.amap.mapcore.*{*;}

-keep class com.amap.api.trace.**{*;}

# 定位

-keep class com.amap.api.location.**{*;}

-keep class com.amap.api.fence.**{*;}

-keep class com.autonavi.aps.amapapi.model.**{*;}

#搜索

-keep class com.amap.api.services.**{*;}

#2D地图

-keep class com.amap.api.maps2d.**{*;}

-keep class com.amap.api.mapcore2d.**{*;}

#导航

-keep class com.amap.api.navi.**{*;}

-keep class com.autonavi.**{*;}

#讯飞

-keep class com.iflytek.**{*;}

# ======================= app javabean 混淆================================

-keep class com.zyp.bean.**{*;}

##---------------Begin:retrofit+rxjava----------------------

-dontwarn javax.annotation.**

-dontwarn javax.inject.**

# OkHttp3

-dontwarn com.squareup.okhttp.**

-keep class com.squareup.okhttp.** { *;}

-keep interface okhttp3.**{*;}

-dontwarn okhttp3.logging.**

-keep class okhttp3.internal.**{*;}

-dontwarn okhttp3.**

-keep class okhttp3.** { *;}

-dontwarn okio.**

# Retrofit

-dontwarn retrofit2.**

-keep class retrofit2.** { *; }

-keepattributes Signature

-keepattributes Exceptions

# RxJava RxAndroid

-dontwarn sun.misc.**

-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {

long producerIndex;

long consumerIndex;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {

rx.internal.util.atomic.LinkedQueueNode producerNode;

}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {

rx.internal.util.atomic.LinkedQueueNode consumerNode;

}

-dontnote android.webkit.**

-dontnote java.util.**

##---------------Inmobi----------------------

-keepattributes SourceFile,LineNumberTable -keep class com.inmobi.** { *; }

-keep public class com.google.android.gms.**

-dontwarn com.google.android.gms.**

-dontwarn com.squareup.picasso.**

-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient{

public *;

}

# skip the Picasso library classes

-keep class com.squareup.picasso.** {*;}

-dontwarn com.squareup.picasso.**

-dontwarn com.squareup.okhttp.**

# skip Moat classes

-keep class com.moat.** {*;}

-dontwarn com.moat.**

7 . 此Demo的功能,可以在应用内切换Base_Url,退出登录时还原默认的Base_Url ,导出应用的私有数据到SD卡上,个人觉得这几个功能,是我们开发app时很需要的功能,如下所示:

cdc24240f3ca

image.png

8 . 混淆前后文件目录变化如下图所示,其中mapping.txt文件为混淆的映射文件,每个版本要注意保存起来(Umeng上需要导入这个文件的)。

cdc24240f3ca

image.png

9 . 对系统Log类的封装Logger类,可以在控制台打印出如下图所示的功能,主要实现代码如下:

StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[4];

StringBuilder sb = new StringBuilder();

sb.append("(")

.append(stackTrace.getFileName())

.append(":")

.append(stackTrace.getLineNumber())

.append(")")

.append("#")

.append(stackTrace.getMethodName())

.append(":")

.append(CommonUtil.unicode2GBK(sb1.toString()));//服务器返回的汉字可能是unicode编码,所以在此转成GBK

cdc24240f3ca

image.png

10 . 最后还有一个小Tips要送大家,大家其实发现了我应用中使用的全是AppConfig.IS_DEBUG而不是BuildConfig.DEBUG,这是为什么呢?主要是为了避免导错BuildConfig的包名,如下图所示:

cdc24240f3ca

image.png

看看随便进入一个android.support.design的BuildConfig,BuildConfig.DEBUG其实是为false的,其实我们希望BuildConfig.DEBUG为true,�但是事与愿违,而且这个错误还不容易发现。

cdc24240f3ca

image.png

为什么用AppConfig.IS_DEBUG就不会出现这样的问题呢,因为这是在我们自己的app下定义的,在那定义的?如下图所示,其实是在build.gradle中定义的,build.gradle可以定义很多类型的变量,可以很方便的达到我们需要的效果:

cdc24240f3ca

image.png

而在AppConfig我又封装了一层,避免了其他library中的build.gradle也定义了IS_DEBUG字段,所以只要AppConfig中的导包正确,就不会出现错误了,所以使用build.gradle中定义的字段时候,请务必再封装一层,代码如下图所示:

import com.zyp.BuildConfig;

public class AppConfig {

/**在build.gradle中配置的变量*/

public static String BASE_URL = BuildConfig.BASE_URL;

/** 默认的base url */

public final static String DEFAULT_BASE_URL = BuildConfig.BASE_URL;

public final static String APPLICATION_ID = BuildConfig.APPLICATION_ID;

public final static int VERSION_CODE = BuildConfig.VERSION_CODE;

public final static boolean IS_LOG = BuildConfig.IS_LOG;

public final static boolean IS_DEBUG = BuildConfig.IS_DEBUG;

public final static String[] BASE_TEST_URL = BuildConfig.BASE_TEST_URL;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值