ProGuardのいくつかの踏み込みについてまとめます


前言
開発において、混同はかなり重要な一環であり、どのappもコード混同、資源圧縮、不要な資源の除去を開くべきである.AndroidのSDKは、このプロセスを実現するためにProGuardを提供しています.ProGuardは、64 kリファレンスの制限をトランスフォームで解決するための有用なツールとなる、カプセル化されたアプリケーションで使用されていないクラス、フィールド、メソッド、および属性を検出および除去します.ProGuardはまた、バイトコードを最適化し、未使用のコード命令を削除し、残りのクラス、フィールド、メソッドを短い名前で混同することもできます.混同されたコードを使用すると、APKがリバースエンジニアリングされにくくなります.これは、ライセンス検証などのセキュリティ感度機能を適用する際に特に役立ちます.
ProGuardの概要
ProGuardには4つの機能があります.
  • 圧縮(Shrink):コード内の不要なクラス、フィールド、メソッド、およびプロパティを検出して除去する
  • .
  • 最適化(Optimize):バイトコードを最適化し、不要な命令
  • を除去する
  • 混同(Obfuscate):a、b、c、dのような名前を使用して、クラス、フィールドおよびメソッドの名前を
  • に変更する.
  • プリフェッチ(Preveirfy):Javaプラットフォーム上で処理後のコードをプリフェッチ混同するこの4つのステップから構成され、各ステップもオプションであり、構成スクリプトによってどのステップを実行するかを決定することができる.

  • 混同コマンド
  • -keep{Modifier}{class_specification}クラスとメンバーの削除または名前の変更を防止する
  • .
  • -keepclassmembers{modifier}{class_specification}メンバーの削除または名前の変更を防止する
  • -keepclasseswithmembers{class_specification}このメンバーを持つクラスとメンバーの削除または名前の変更を防止する
  • -keepnames{class_specification}メンバーの名前変更を防止する
  • -keepclasseswithmembernames{class_specification}このメンバーを持つクラスとメンバーの名前の変更を防ぐ
  • -keepclasseswithmembers
  • optimizationpasses圧縮レベル
  • を指定
  • dontoptimize入力されたクラスファイルを最適化しない
  • dontusemixedcaseclassnamesパッケージ名大文字小文字を混合しない
  • dontskipnonpubliclibraryclasses非共通ライブラリのクラスメンバー
  • をスキップしない
  • dontpreverify混同時プリチェック
  • しない
  • dontwarn警告があれば
  • を終了しません
  • verbose混同時記録ログ
  • optimizations混同時に採用されるアルゴリズム
  • 要素が混同に関与しないルール
    次のようになります.
    [    ] [ ] {
        [  ]
    }

    「クラス」は、クラスに関連する制限条件を表し、その制限条件に合致するクラスに最終的に配置されます.コンテンツは次のように使用できます.
  • 具体的なクラス
  • アクセス修飾子(public、protected、private)
  • ワイルドカード*は、任意の長さの文字に一致しますが、パケット名区切り記号(.)は含まれません.
  • ワイルドカード**は、任意の長さの文字に一致し、パケット名区切り記号(.)を含む.
  • extends、すなわちクラスのベースクラスを指定できる
  • implement,マッチングあるインタフェースを実現したクラス
  • $内部クラス
  • 「メンバー」は、クラスメンバーに関連する制限条件を表し、その制限条件に合致するクラスメンバーに最終的に配置されます.コンテンツは次のように使用できます.
  • はすべてのコンストラクタ
  • に一致する.
  • すべてのドメインに一致する
  • すべての方法
  • に一致する
  • ワイルドカード*は、任意の長さの文字に一致しますが、パケット名区切り記号(.)は含まれません.
  • ワイルドカード**は、任意の長さの文字に一致し、パケット名区切り記号(.)を含む.
  • ワイルドカード*は、任意のパラメータタイプ
  • に一致します.
  • ...、任意の長さの任意のタイプのパラメータに一致します.例えばvoid test(…)は任意のvoid test(String a)やvoid test(int a,String b)と一致する.
  • アクセス修飾子(public、protected、private)
  • 共通のカスタム混同規則
  • -keep public class com.proguard.example.Test { *; } クラスを混同しない
  • -keep class com.bumptech.glide.* { ; } パケットの下にあるすべてのクラスを混同しない
  • -keep public class * extends com.proguard.example.Test { *; } クラスを混同しないサブクラス
  • -keep public class .model. {*;} すべてのクラス名がmodelを含むクラスとそのメンバーを混同しない
  • -keep public class * extends android.os.Iinterfaceあるインタフェースを混同しない実装
  • -keepclassmembers class com.proguard.example.Test {public ();} クラスを混同しない構造方法
  • -keepclassmembers class * {void *(**On*Event);} コールバック関数を持つOnXXEventを混同しない方法
  • 構成の混同
    android {
        buildTypes {
            release {
                minifyEnabled true
                shrinkResources true
                //Zipalign  
                zipAlignEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }

    一般的に混同時間が長いのでreleaseモードでのみオンになります.shrinkResourcesは、リソース圧縮を開きます.
    汎用混同コード
    #      
    -optimizationpasses 5
    
    #            
    -dontskipnonpubliclibraryclassmembers
    
    #                    ,             
    -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
    
    #             
    -useuniqueclassmembernames
    
    #                     
    -allowaccessmodification
    
    #        
    -dontusemixedcaseclassnames
    
    #          
    -dontskipnonpubliclibraryclasses
    
     #         
    -verbose
    
    #          Android      preverify,         
    -dontpreverify
    
    #         “SourceFile”   
    -renamesourcefileattribute SourceFile
    
    #    
    -keepattributes SourceFile,LineNumberTable,Deprecated
    
    #    
    -ignorewarning
    
    
    #      ,gradle build          
    -dump class_files.txt            #apk    class     
    -printseeds seeds.txt            #        
    -printusage unused.txt           #         
    -printmapping mapping.txt        #       
    
    #    
    -keepattributes *Annotation*,InnerClasses,Deprecated
    
    #                 
    -keepattributes Signature
    
    -keepattributes EnclosingMethod
    
    #   native       
    -keepclasseswithmembernames class * {
        native ;
    }
    
    #           
    -dontwarn android.support.**
    
    #       Serializable       
    -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();
    }
    
    
    #          
    -dontnote junit.framework.**
    -dontnote junit.runner.**
    -dontwarn android.test.**
    -dontwarn android.support.test.**
    -dontwarn org.junit.**
    
    #Fragment    AndroidManifest.xml   ,       
    -keep public class * extends android.support.v4.app.Fragment
    -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 * extends android.view.View
    -keep public class com.android.vending.licensing.ILicensingService
    -keep class android.support.** {*;}
    -keep public class * extends android.os.IInterface
    
    -keep public class * extends android.view.View{
        *** get*();
        void set*(***);
        public (android.content.Context);
        public (android.content.Context, android.util.AttributeSet);
        public (android.content.Context, android.util.AttributeSet, int);
    }
    
    
    #          
    -keep class **.R$* {
     *;
    }
    
    #         onXXEvent ,    
    -keepclassmembers class * {
        void *(**On*Event);
    }
    
    #             
    -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 * { #      enum      
     public static **[] values();
     public static ** valueOf(java.lang.String);
    }
    
    #    Parcelable     
    -keep class * implements android.os.Parcelable {
     public static final android.os.Parcelable$Creator *;
    }
    

    混同チェック
    混同されたパッケージは、混同によって導入されるバグを回避するためにチェックする必要があります.一方,コードレベルからチェックする必要がある.上記の構成を使用して混同パッケージを作成すると、/build/outputs/mapping/release/ディレクトリの下に次のファイルが出力されます.
  • dump.txtは、APKファイル内のすべてのクラスの内部構造
  • を記述する.
  • mapping.txtは、前後のクラス、メソッド、クラスメンバー等を混同対照表
  • を提供する.
  • seeds.txtは、混同されていないクラスおよびメンバー
  • をリストする.
  • usage.txtは、除去するコード
  • をリストする.
    私たちはseedsに基づいてtxtファイルは、混同されていないクラスとメンバーに、所望の保持がすべて含まれているかどうかを確認し、usageに従う.txtファイルは、誤って削除されたコードがあるかどうかを確認します.一方、テストの面からチェックする必要があります.混同したパッケージを全面的にテストし、バグが発生しているかどうかを確認します.
    Proguardマニュアルproguard圧縮コードとリソースのAndroid開発者への混同マニュアルの紹介