今天闲,所以想把项目加入混淆,可以减小apk体积,也可以优化项目。
本来以前也加入过,但是因为总是报错所以不了了之。
androidstudio 混淆
首先需要在项目的build.gradle文件中加入如下代码。
androidstudio都有一个默认混淆的文件,没有也可以自己建一个。
保证有文件,文件名一样就好了,名字其实可以修改。
其实开始也啥都不知道,就再网上慢慢搜,一遍一遍的试。
在这里说明几个语法 以下图为例:
前面加“#”代表注释,混淆语句前面都有“-
保持某个类不混淆 -keepclass com.uyac.test.MainActivity
保持某个包下面的类不混淆 -keep class com.uyac.test **
保持某个包下面的类还有类中代码不混淆 -keep class com.uyac.test**{ *; }
保持继承activity的类 -keep class * extends android.app.Activity (同理Fragment、Service、BroadCast都可以以此混淆)
例如 -keeppublic class * extends android.support.v4.app.Fragment
保持资源类
-keepclassmembersclass **.R$* {
public static <fields>;
}
....
这样之后,就要去混淆文件中去加混淆代码了。(混淆代码在文章末尾贴出),我直接说遇到的问题。
打包时遇到了这样的错误
Error:Execution failed for task ':ElegantLife2.1.0:transformClassesAndResourcesWithProguardForRelease'.
> java.io.IOException: Can't read [D:\project_as_1\ElegantLife3.0.0_as2\MyUyac\ElegantLife2.1.0\libs\umeng-analytics-v5.2.4.jar] (No such file or directory)
这是因为我混淆文件里面有混淆 -libraryjars libs/umeng-analytics-v5.2.4.jar
因为libs下没有这个文件!我的umeng-analytics 版本是v5.6.4 所以编译没通过。
改成-libraryjars libs/umeng-analytics-v5.6.4.jar就没问题了
然后我再次打包,打包是可以成功的,只是打开app在欢迎页就崩了。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.uyac.elegantlife.tt, PID: 14659
java.lang.NullPointerException: Attempt to invoke virtual method 'int com.uyac.elegantlife.c.bm$a.e()' on a null object reference
at com.uyac.elegantlife.a.z.getView(SourceFile:176)
at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:220)0
at android.widget.AbsListView.obtainView(AbsListView.java:2347)
at android.widget.ListView.makeAndAddView(ListView.java:1864)
at android.widget.ListView.fillDown(ListView.java:698)
at android.widget.ListView.fillFromTop(ListView.java:759)
at android.widget.ListView.layoutChildren(ListView.java:1659)
at android.widget.AbsListView.onLayout(AbsListView.java:2151)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1077)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.support.v4.view.ViewPager.onLayout(SourceFile:1767)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.support.v4.view.ViewPager.onLayout(SourceFile:1767)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1077)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579)
at android.widget.FrameLayout.onLayout(FrameLayout.java:514)
at android.view.View.layout(View.java:15714)
at android.view.ViewGroup.layout(ViewGroup.java:5046)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2091)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.
报错如上,(即使打包之后,只要代码中有输出log,也是可以看到的,错误信息也有,可以用于打包后调试,有更好的方法欢迎讨论)
这种问题就不好解决了,看样子是一个类部类,而正好欢迎界面过后要启动的界面适配器里面有类部类,所以我就keep了我的适配器包。然后不报错了。
但是还没有结束
第三方登录,和分享功能不能用!!!因为用的友盟分享和第三方登录。
#友盟混淆
-keep class com.umeng.**
-keep class com.umeng.**{*;}
这样看来,混淆其实也很简单,最主要是找到问题,解决问题。
最后献上混淆源码
#指定代码的压缩级别
-optimizationpasses 5
#包明不混合大小写
-dontusemixedcaseclassnames
#不去忽略非公共的库类
-dontskipnonpubliclibraryclasses
#优化 不优化输入的类文件
-dontoptimize
#不做预校验
-dontpreverify
#混淆时是否记录日志
-verbose
# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#忽略警告
-ignorewarning
#apk 包内所有 class 的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从 apk 中删除的代码
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt
# 保持哪些类不被混淆 google默认 不混淆 Activity 、Service ... 类的子类
#混淆了可能编译不通过
-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
#保护注解
-keepattributes *Annotation*
#如果有引用v4包可以添加下面这行
-keep public class * extends android.support.v4.app.Fragment
#如果引用了v4或者v7包
-dontwarn android.support.**
-keep public class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
}
# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,allowshrinking class * {
native <methods>;
}
#保持自定义控件类不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
#保持自定义控件类不被混淆
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持 Serializable 不被混淆
-keepnames class * implements java.io.Serializable
#保持 Serializable 不被混淆并且enum 类也不被混淆
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
#不混淆资源类
-keepclassmembers class **.R$* {
public static <fields>;
}
#不混淆H5交互
-keepattributes *JavascriptInterface*
#ClassName是类名,H5_Object是与javascript相交互的object,建议以内部类形式书写
-keepclassmembers class **.ClassName$H5_Object{
*;
}
#如果使用有Gson,则添加以下配置
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
#keep model
-keep class com.uyac.elegantlife.entity.**{*;}
#keep 适配器
-keep class com.uyac.elegantlife.adapter.**{*;}
#高德定位混淆
-keep class com.amap.api.location.**{*;}
-keep class com.amap.api.fence.**{*;}
-keep class com.autonavi.aps.amapapi.model.**{*;}
#高德2D地图混淆
-keep class com.amap.api.maps2d.**{*;}
-keep class com.amap.api.mapcore2d.**{*;}
#友盟混淆
-dontwarn com.umeng.**
-keep class com.umeng*.** {*; }
#三星应用市场需要添加:sdk-v1.0.0.jar,look-v1.0.1.jar
#-libraryjars libs/sdk-v1.0.0.jar
#-libraryjars libs/look-v1.0.1.jar