全部產品
Search
文件中心

Mobile Platform as a Service:混淆 Android 檔案

更新時間:Jul 13, 2024

mPaaS Android 用戶端開發的應用程式是通過 Java 代碼編寫而成,而 Java 代碼易被反編碼,因此為了保護 Java 原始碼,需要使用 ProGuard 混淆 Android 檔案。

ProGuard 是一個壓縮、最佳化和混淆 Java 位元組碼檔案的工具。

  • 壓縮 指檢測以及刪除沒有用到的類、欄位、方法以及屬性。

  • 最佳化 指分析以及最佳化方法的位元組碼。

  • 混淆 指使用無意義的短變數,對類、變數、方法進行重新命名。

使用 ProGuard 可以讓代碼更精簡,更高效,也更難被逆向或破解。

前置條件

您已經配置 mPaaS 工程。

關於此任務

採用組件化方案的 mPaaS 工程,每一個 bundle 的編譯產物都是一個已經混淆的 dex 檔案,所以配置混淆檔案是以 bundle 工程為單位而進行的。Portal 工程通常沒有代碼,不需要開啟混淆。

程式碼範例

  • Gradle 配置

    android {
      compileSdkVersion 23
      buildToolsVersion "19.1.0"
    
      defaultConfig {
          applicationId "com.youedata.xionganmaster.launcher"
          minSdkVersion 15
          targetSdkVersion 23
          versionCode 1
          versionName "1.0"
      }
      buildTypes {
          release {
              // 混淆開關,是否混淆
              minifyEnabled true
              // 混淆檔案清單,混淆規則配置
              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
          }
      }
      lintOptions {
            checkReleaseBuilds false
            // Or, if you prefer, you can continue to check for errors in release builds,
            // but continue the build even when errors are found:
            abortOnError false
      }
    }
  • 混淆檔案樣本

    下列混淆是一個基本樣本(如果要添加額外的第三方庫,需要加入其它混淆,通常設定檔可在第三方庫的官網中找到):

      # Add project specific ProGuard rules here.
      # By default, the flags in this file are appended to flags specified
      # in ${sdk.dir}/tools/proguard/proguard-android.txt
      # You can edit the include path and order by changing the proguardFiles
      # directive in build.gradle.
    
      # For more details, see [Shrink your code and resources](http://developer.android.com/guide/developing/tools/proguard.html)。
    
      # Add any project specific keep options here:
    
      # If your project uses WebView with JS, uncomment the following
      # and specify the fully qualified class name to the JavaScript interface
      # class:
      # -keepclassmembers class fqcn.of.javascript.interface.for.webview {
      # public *;
      # }
      -optimizationpasses 5
      -dontusemixedcaseclassnames
      -dontskipnonpubliclibraryclasses
      -dontpreverify
      -verbose
      -ignorewarnings
      -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
    
      -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 com.android.vending.licensing.ILicensingService
      -keep public class com.alipay.mobile.phonecashier.*
      -keepnames public class *
      -keepattributes SourceFile,LineNumberTable
      -keepattributes *Annotation*
    
      #-keep public class * extends com.alipay.mobile.framework.LauncherApplicationAgent {
      #    *;
      #}
    
      #-keep public class * extends com.alipay.mobile.framework.LauncherActivityAgent {
      #    *;
      #}
    
      -keepclasseswithmembernames class * {
          native <methods>;
      }
    
      -keepclasseswithmembernames class * {
          public <init>(android.content.Context, android.util.AttributeSet);
      }
    
      -keepclasseswithmembernames class * {
          public <init>(android.content.Context, android.util.AttributeSet, int);
      }
    
      -keepclassmembers enum * {
          public static **[] values();
          public static ** valueOf(java.lang.String);
      }
    
      -keep class * extends java.lang.annotation.Annotation { *; }
      -keep interface * extends java.lang.annotation.Annotation { *; }
    
      -keep class * implements android.os.Parcelable {
        public static final android.os.Parcelable$Creator *;
      }
    
      -keep public class * extends android.view.View{
          !private <fields>;
          !private <methods>;
      }
    
      -keep class android.util.**{
           public <fields>;
           public <methods>;
       }
    
      -keep public class  com.squareup.javapoet.**{
          !private <fields>;
            !private <methods>;
      }
      -keep public class   javax.annotation.**{
              !private <fields>;
              !private <methods>;
        }
      -keep public class   javax.inject.**{
           !private <fields>;
           !private <methods>;
       }
      -keep interface **{
        !private <fields>;
        !private <methods>;
      }
      # for dagger
        -keep class * extends dagger.internal.Binding
        -keep class * extends dagger.internal.ModuleAdapter
    
        -keep class **$$ModuleAdapter
        -keep class **$$InjectAdapter
        -keep class **$$StaticInjection
    
        -keep class dagger.** { *; }
    
        -keep class javax.inject.**{ *; }
        -keep class * extends dagger.internal.Binding
        -keep class * extends dagger.internal.ModuleAdapter
        -keep class * extends dagger.internal.StaticInjection
    
      # for butterknife
        -keep class butterknife.* { *; }
        -keep class butterknife.** { *; }
        -dontwarn butterknife.internal.**
        -keep class **$$ViewBinder { *; }
    
        -keepclasseswithmembernames class * {
            @butterknife.* <fields>;
        }
    
        -keepclasseswithmembernames class * {
            @butterknife.* <methods>;
        }
    說明

    如果在您的 bundle 工程中定義了架構類LauncherApplicationAgentLauncherActivityAgent,請注意進行防混淆設定

  • 避免混淆萬用群組件

    如果在metainfo.xml中註冊了萬用群組件,編譯時間會檢查這些組件是否存在,請避免這些組件被混淆,否則會編譯失敗。例如註冊了以下組件:

       <metainfo>
       <service>
           <className>com.mpaas.cq.bundleb.MyServiceImpl</className>
           <interfaceName>com.mpaas.cq.bundleb.api.MyService</interfaceName>
           <isLazy>true</isLazy>
       </service>
    </metainfo>

    請在混淆配置中添加:

      -keep class com.mpaas.cq.bundleb.MyServiceImpl
      -keep class com.mpaas.cq.bundleb.api.MyService