編輯:關於Android編程
今天閒,所以想把項目加入混淆,可以減小apk體積,也可以優化項目。
本來以前也加入過,但是因為總是報錯所以不了了之。
androidstudio 混淆
首先需要在項目的build.gradle文件中加入如下代碼。
androidstudio都有一個默認混淆的文件,沒有也可以自己建一個。
保證有文件,文件名一樣就好了,名字其實可以修改。
其實開始也啥都不知道,就再網上慢慢搜,一遍一遍的試。
在這裡說明幾個語法
前面加“#”代表注釋,混淆語句前面都有“-
保持某個類不混淆 -keep class com.uyac.test.MainActivity
保持某個包下面的類不混淆 -keep class com.uyac.test **
保持某個包下面的類還有類中代碼不混淆 -keep class com.uyac.test**{ *; }
保持繼承activity的類 -keep class * extends android.app.Activity (同理Fragment、Service、BroadCast都可以以此混淆)
例如-keep public class * extends android.support.v4.app.Fragment
保持資源類
-keepclassmembers class **.R$* {
public static; }
....
這樣之後,就要去混淆文件中去加混淆代碼了。(混淆代碼在文章末尾貼出),我直接說遇到的問題。
打包時遇到了這樣的錯誤
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)
這是因為我混淆文件裡面有混淆-libraryjarslibs/umeng-analytics-v5.2.4.jar
因為libs下沒有這個文件!我的umeng-analytics 版本是v5.6.4 所以編譯沒通過。
改成-libraryjarslibs/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 #申明第三方庫,以免出現調用錯誤 -libraryjars libs/alipaySDK-20150602.jar -libraryjars libs/aliyun-oss-sdk-android-2.2.0.jar -libraryjars libs/AMap_2DMap_V2.8.1_20160202.jar -libraryjars libs/AMap_Location_V2.4.1_20160414.jar -libraryjars libs/android-async-http-1.4.8.jar -libraryjars libs/com.umeng.message.lib_v2.5.0.jar -libraryjars libs/commons-codec-1.7.jar -libraryjars libs/eventbus-2.1.0.jar -libraryjars libs/gson-2.6.2.jar -libraryjars libs/libammsdk.jar -libraryjars libs/okhttp-3.2.0.jar -libraryjars libs/okio-1.6.0.jar -libraryjars libs/SimplifySpan.jar -libraryjars libs/umeng-analytics-v5.6.4.jar -libraryjars libs/universal-image-loader-1.9.5.jar -libraryjars libs/UPPayAssistEx.jar -libraryjars libs/UPPayPluginExStd.jar #保護注解 -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(android.content.Context); public (android.content.Context, android.util.AttributeSet); public (android.content.Context, android.util.AttributeSet, int); public void set*(...); } #保持 native 方法不被混淆 -keepclasseswithmembernames class * { native ; } # Keep names - Native method names. Keep all native class/method names. -keepclasseswithmembers,allowshrinking class * { native ; } #保持自定義控件類不被混淆 -keepclasseswithmembers class * { public (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 ; !private ; !private ; 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 ; } #不混淆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
Fragment 與 Activity之間傳遞數據有兩種方法,一種是使用setArgument,一種是使用接口回調。下面先學習第一種方法。 (1)使用setArgum
重新定義分割線Drawable的Bounds首先,需要清楚一個事實:出現以上情況的矛盾點,是官方ListView的分割線屬性不支持左右留白。所以最佳的解決方案,就是使得官
一、技術准備今天我們來看一下如何修改Android中編譯時的資源Id的值,在講解這內容之前,我們需要先了解一下Android中的資源編譯之後的結構和編譯過程,這裡就不多說
京東客戶端的輪播文字效果: 本次要實現的只是後面滾動的文字(前面的用ImageView或者TextView實現即可),看一下實現的效果 實