Android中proguard的作用

 這兩天在手機設置裡面需要添加一個設置項,可是在所有代碼都添加好之後,點擊該設置項時,一直報錯,log為:

08-08 10:51:50.622 E/AndroidRuntime( 3169): FATAL EXCEPTION: main
08-08 10:51:50.622 E/AndroidRuntime( 3169): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.settings/com.android.settings.SubSettings}: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.android.settings.AppPreferInstallLocation: make sure class name exists, is public, and has an empty constructor that is public
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.ActivityThread.access$600(ActivityThread.java:123)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.os.Looper.loop(Looper.java:137)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.ActivityThread.main(ActivityThread.java:4424)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at java.lang.reflect.Method.invokeNative(Native Method)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at java.lang.reflect.Method.invoke(Method.java:511)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at dalvik.system.NativeStart.main(Native Method)
08-08 10:51:50.622 E/AndroidRuntime( 3169): Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.android.settings.AppPreferInstallLocation: make sure class name exists, is public, and has an empty constructor that is public
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.Fragment.instantiate(Fragment.java:581)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.preference.PreferenceActivity.switchToHeaderInner(PreferenceActivity.java:1117)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.preference.PreferenceActivity.switchToHeader(PreferenceActivity.java:1133)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.preference.PreferenceActivity.onCreate(PreferenceActivity.java:532)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at com.android.settings.Settings.onCreate(Settings.java:97)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.Activity.performCreate(Activity.java:4465)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     … 11 more
08-08 10:51:50.622 E/AndroidRuntime( 3169): Caused by: java.lang.ClassNotFoundException: com.android.settings.AppPreferInstallLocation
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     at android.app.Fragment.instantiate(Fragment.java:571)
08-08 10:51:50.622 E/AndroidRuntime( 3169):     … 18 more
08-08 10:51:50.632 W/ActivityManager( 1736):   Force finishing activity com.android.settings/.SubSettings
08-08 10:51:50.632 W/ActivityManager( 1736):   Force finishing activity com.android.settings/.Settings

    從log上可以看出,程序一直沒有找到要啟動的activity的class,可是在代碼中我明明已經添加瞭,而且對比設置中其他選項的做法,沒有什麼區別。可是結果還是一樣,一直報錯。後來實在沒有辦法,模仿其他選項的做法完全一樣的寫一個,隻是class 名不一樣而已,可還是不行。

    這個問題折騰瞭我2天,期間找好幾個在設置中添加過選項的同事來看也沒找到原因。本來一個很小的功能,頂多平常1-2個小時就搞定的東西,搞瞭我2天,當時比較崩潰,該想的辦法都想瞭,可是就是不如所願。後來實在不行,我就看瞭一下Settings package中的代碼結構,發現在Settins目錄下面有一個proguard.flags文件,平時一般隻關註Android.mk和AndroidManifest.xml兩個文件,其他文件都忽略,因此也不知道他們都有什麼作用。當我打開這個文件時,豁然開朗,問題就在這裡。原來我添加的class沒有被包含在這裡面,這導致啟動activity時找不動這個class。問題解決瞭,經驗教訓是proguard要慎用啊!

———-下面是網上找到的一些proguard的資料,貼出來分享:
ProGuard是一個免費的java類文件壓縮,優化,混淆器.它探測並刪除沒有使用的類,字段,方法和屬性.它刪除沒有用的說明並使用字節碼得到最大優化.它使用無意義的名字來重命名類,字段和方法.

ProGuard的使用是為瞭:

1.創建緊湊的代碼文檔是為瞭更快的網絡傳輸,快速裝載和更小的內存占用.
2.創建的程序和程序庫很難使用反向工程.
3.所以它能刪除來自源文件中的沒有調用的代碼
4.充分利用java6的快速加載的優點來提前檢測和返回java6中存在的類文件.

 

作者:goyoung

發佈留言