android 混淆規則作用,Android代碼混淆詳解

来源:https://www.cnblogs.com/Bytezero/p/18037309
-Advertisement-
Play Games

一、混淆的意義 混淆代碼並不是讓代碼無法被反編譯,而是將代碼中的類、方法、變數等信息進行重命名,把它們改成一些毫無意義的名字,同時也可以移除未被使用的類、方法、變數等。 所以直觀的看,通過混淆可以提高程式的安全性,增加逆向工程的難度,同時也有效縮減了apk的體積。總結如下: 1、將項目中的類、方法、 ...


一、混淆的意義

混淆代碼並不是讓代碼無法被反編譯,而是將代碼中的類、方法、變數等信息進行重命名,把它們改成一些毫無意義的名字,同時也可以移除未被使用的類、方法、變數等。 所以直觀的看,通過混淆可以提高程式的安全性,增加逆向工程的難度,同時也有效縮減了apk的體積。總結如下:

1、將項目中的類、方法、變數等信息進行重命名,變成一些無意義的簡短名字。

2、移除未被使用的類、方法、變數等。

二、混淆的規則和配置

凡是需要在AndroidManifest.xml中去註冊的所有類的類名以及從父類重寫的方法名都自動不會被混淆。 因此,除了Activity之外,這份規則同樣也適用於Service、BroadcastReceiver和ContentProvider。

(1)minifyEnabled

minifyEnabled為true的作用:啟用代碼混淆、壓縮APK;

minifyEnabled會對資源進行壓縮,多餘的代碼在打包的時候就給移除掉了。不僅僅是代碼,沒有被調用的資源同樣也會被移除掉,因此minifyEnabled除了混淆代碼之外,還可以起到壓縮APK包的作用。

開啟混淆後也可添加shrinkResources,表示開啟刪除無用資源。

(2)shrinkResources

shrinkResources為true用來開啟刪除無用資源。

shrinkResources會對就是沒有被引用的文件(經過實測是drawable,layout,實際並不是徹底刪除,而是保留文件名,但是沒有內容),但是因為需要知道是否被引用所以需要配合mififyEnable使用,只有當兩者都為true的時候才會起到真正的刪除無效代碼和無引用資源的目的。

(3)避免被誤刪除

若配置minifyEnable true && shrinkResources true,防止避免誤刪除的文件,可以配置如下: 在res/raw/keep.xml(避免被誤刪除)寫了配置的

對於沒有被引用的文件&沒有在配置文件keep.xml中聲明保存的文件,打包後是沒有內容的,聲明保存的文件有內容(資源文件和layout文件)。 註意:string.xml中沒有被引用的怎麼設置都不會被刪除。

(4)proguard-android.txt和proguard-rules.pro

proguard-android.txt:代表系統預設的混淆規則配置文件,該文件在/tools/proguard下,一般不要更改該配置文件,因為也會作用於其它項目。

proguard-rules.pro:代碼表當前Project的混淆配置文件,在app module下,可以通過修改該文件來添加適用當前項目的混淆規則。

(5)proguard文件夾

代碼混淆生成apk之後,項目下麵會多出來一個proguard文件夾,proguard文件夾中四個文件的作用。

dump.txt : 描述了apk中所有類文件中內部的結構體。

mapping.txt : 列出了原始的類、方法和名稱與混淆代碼間的映射。

seeds.txt : 列出了沒有混淆的類和方法。

usage.txt : 列出congapk中刪除的代碼。

android studio自帶java語言的ProGuard工具,主要用來壓縮、優化、混淆,然後配合Gradle構建工具實現混淆。

在app module中統一配置混淆規則

我們可以直接在app module中build.gradle文件配置所有module需要混淆的規則。這樣,其他module中就無需開啟混淆。
首先在build.gradle 中將混淆的開關打開,即 minifyEnabled 置為 true

 

1 buildTypes {
2         release {
3             minifyEnabled true   //開啟混淆
4             zipAlignEnabled true  //壓縮優化
5             shrinkResources true  //移出無用資源
6             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' //預設的混淆文件以及我們指定的混淆文件
7         }
8 }

如果是model混淆,子模塊混淆文件的指定是通過consumerProguardFiles這個屬性來指定的,並不是proguardFiles 屬性,而且我們無需配置其他的選項,只需要配置consumerProguardFiles屬性就可以。該屬性表示在打包的時候會自動尋找該module下我們指定的混淆文件對代碼進行混淆。配置如下:

1 buildTypes {
2     release {
3     //minifyEnabled true //是否開啟混淆,其實子模塊中這個已經沒有作用了,由主模塊控制
4     consumerProguardFiles 'proguard-rules.pro' //子模塊要用這個命令才能生效
5 }

然後就要去proguard-rules.pro寫入我們的混淆的規則(如文件其名),防止重要的類被混淆移除了。

先特別介紹的是與保持相關元素不參與混淆的規則相關的幾種命令:
-keep    防止類和成員被移除或者被重命名
-keepnames    防止類和成員被重命名
-keepclassmembers    防止成員被移除或者被重命名
-keepclasseswithmembers    防止擁有該成員的類和成員被移除或者被重命名
-keepclasseswithmembernames    防止擁有該成員的類和成員被重命名

混淆規則:

1、有一些固定的混淆規則不需要更改:

#指定代碼的壓縮級別
-optimizationpasses 5

#包明不混合大小寫
-dontusemixedcaseclassnames

#不去忽略非公共的庫類
-dontskipnonpubliclibraryclasses

 #優化  不優化輸入的類文件
-dontoptimize

 #預校驗
-dontpreverify

 #混淆時是否記錄日誌
-verbose

 # 混淆時所採用的演算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#保護註解
-keepattributes *Annotation*

2、理解通配符

-keep class cn.hadcn.test.**
-keep class cn.hadcn.test.*
很多同學都搞不懂下麵兩個的區別,一顆星表示只是保持該包下的類名,而子包下的類名還是會被混淆;兩顆星表示把本包和所含子包下的類名都保持;用以上方法保持類後,你會發現類名雖然未混淆,但裡面的具體方法和變數命名還是變了,這時如果既想保持類名,又想保持裡面的內容不被混淆,我們就需要以下方法了:

-keep class cn.hadcn.test.* {*;}

3、保證指定包名下的所有類及子包中所有的類不被混淆

例子1:com.lib.manager 包下麵的類不混淆
-keep class com.lib.manager.**{*;} 
例子2:v4包下麵的所有類不混淆
-keep class android.support.v4.** { *; }

4、保證指定的類不被混淆

例子1:YiBaWiFiActivity 類不被混淆, YiBaWiFiActivity 完整包名:com.yiba.wifi.sdk.lib.activity.YiBaWiFiActivity
-keep class com.yiba.wifi.sdk.lib.activity.YiBaWiFiActivity{*;}
例子2:v4 包下麵的 ActivityCompat 類不被混淆
-keep class android.support.v4.app.ActivityCompat{*;}

5、不混淆指定類的子類

-keep class * extends pp.lib.User { *; }
User 類的子類不混淆

6、指定介面不混淆

Callback 是一個介面,完整包名為:com.lib.impl.Callback

-keep interface com.lib.impl.Callback{ * ; }

7、指定介面的實現類不混淆

Callback 是一個介面,完整包名為:com.lib.impl.Callback . 所有的實現類都不會混淆。

-keep class * implements com.lib.impl.Callback { *; }

8、指定類的內部類不混淆

PhoneUtil 的源碼如下:

 1 package com.lib.manager;
 2 import android.content.Context;
 3 import android.os.AsyncTask;
 4  
 5 /**
 6  * Created by yiba_zyj on 2017/4/5.
 7  */
 8  
 9 public class PhoneUtil {
10  
11     public final static int APPID = 100 ;
12  
13     public PhoneUtil( Context context ){
14  
15     }
16  
17     class MyTask extends AsyncTask {
18  
19         @Override
20         protected Object doInBackground(Object[] params) {
21             return null;
22         }
23     }
24 }

PhoneUtil 有一個常量、一個構造函數、一個內部類。

混淆規則:

-keep class com.lib.manager.PhoneUtil$* {
  * ;
}

 

9、構造函數不混淆

PhoneUtil 的源碼如所示:

 1 package com.lib;
 2  
 3 /**
 4  * Created by yiba_zyj on 2017/4/7.
 5  */
 6  
 7 public class PhoneUtil {
 8  
 9     public static final String aa = "1222" ;
10  
11     public void run(){
12  
13     }
14  
15 }

混淆規則:PhoneUtil 的無參構造函數不混淆 。PhoneUtil 裡面沒有用到的 屬性和方法將會被移除。

-keep class com.lib.PhoneUtil {
  public <init>();
}
那麼有參的構造函數的混淆規則是怎麼樣的?

混淆規則:PhoneUtil 的 參數為 Context 的構造函數不混淆

-keep class com.lib.PhoneUtil {
public <init>( android.content.Context );
}

10、指定類的屬性和方法不被混淆

原始類 PhoneUtil 代碼如下,完整的包名為:com.lib.manager.PhoneUtil

 1 package com.lib.manager;
 2  
 3 import android.content.Context;
 4 import android.util.DisplayMetrics;
 5 import android.view.WindowManager;
 6  
 7 /**
 8  * Created by yiba_zyj on 2017/4/5.
 9  */
10  
11 public class PhoneUtil {
12  
13      public static final int AppID = 100 ;
14  
15     /**
16      * 獲得屏幕高度
17      * @param context
18      * @return
19      */
20     public static int getScreenWidth(Context context) {
21         WindowManager wm = (WindowManager) context
22                 .getSystemService(Context.WINDOW_SERVICE);
23         DisplayMetrics outMetrics = new DisplayMetrics();
24         wm.getDefaultDisplay().getMetrics(outMetrics);
25         return  outMetrics.widthPixels;
26     }
27  
28     /**
29      * 獲得屏幕寬度
30      * @param context
31      * @return
32      */
33     public static int getScreenHeight(Context context) {
34         WindowManager wm = (WindowManager) context
35                 .getSystemService(Context.WINDOW_SERVICE);
36         DisplayMetrics outMetrics = new DisplayMetrics();
37         wm.getDefaultDisplay().getMetrics(outMetrics);
38         return  outMetrics.heightPixels;
39     }
40  
41 }

PhoneUtil 類中包含1個常量及2個方法.類中的變數不被混淆:
-keep class com.lib.manager.PhoneUtil{
public static final int AppID ;
}
混淆後的效果如下:

1 package com.lib.manager;
2  
3 public class PhoneUtil {
4     public static final int AppID = 100;
5  
6     public PhoneUtil() {
7     }
8 }

可以看到混淆後的類中,AppID 常量被保存下來了,getScreenWidth 、 getScreenHeight 這兩個方法被移除了。 為什麼會有方法被移除? 因為在混淆時,Android 會預設移除沒有使用的的方法和資源,保證apk 合理的被壓縮。保留類中的方法不被混淆
-keep class com.lib.manager.PhoneUtil{
 public static int getScreenWidth(android.content.Context);
 }
混淆後的方法如下:

 1 //
 2 // Source code recreated from a .class file by IntelliJ IDEA
 3 // (powered by Fernflower decompiler)
 4 //
 5  
 6 package com.lib.manager;
 7  
 8 import android.content.Context;
 9 import android.util.DisplayMetrics;
10 import android.view.WindowManager;
11  
12 public class PhoneUtil {
13     public PhoneUtil() {
14     }
15  
16     public static int getScreenWidth(Context var0) {
17         WindowManager var1 = (WindowManager)var0.getSystemService("window");
18         DisplayMetrics var2 = new DisplayMetrics();
19         var1.getDefaultDisplay().getMetrics(var2);
20         return var2.widthPixels;
21     }
22 }

11、不混淆類中所有的 public 方法

# <methods> 匹配所有的方法

-keep class cn.hadcn.test.One {
    public <methods>;
}
表示One類下的所有public方法都不會被混淆

12、不混淆類中所有的 public 欄位

-keep class pp.lib.PhoneUtil{
  public <fields> ;
}
表示 PhoneUtil 類中所有的 public 屬性將保留,其他類型的欄位

13、不混淆構造函數

-keep class pp.lib.PhoneUtil{
   <init>(***) ;
   <init>(*** , *** ) ;
}
不混淆 PhoneUtil 類中所有 一個參數 和 兩個參數的 的構造函數。

13、不混淆 bean 對象裡面的 set 、get 方法

User 對象如下圖所示:

 1 package pp.lib;
 2  
 3 /**
 4  * Created by ${zhaoyanjun} on 2017/4/10.
 5  */
 6  
 7 public class User {
 8  
 9     private String name ;
10     private String age ;
11  
12     public String getName() {
13         return name;
14     }
15  
16     public void setName(String name) {
17         this.name = name;
18     }
19  
20     public String getAge() {
21         return age;
22     }
23  
24     public void setAge(String age) {
25         this.age = age;
26     }
27 }

混淆規則:不混淆 User 類中所有的 set 和 get 方法,*** 代表 通配符

-keep class pp.lib.User{
  void set*( *** ) ;
   *** get*() ;
}

常見不混淆的類和屬性

不混淆四大組件 和 Application

因為四大組件和 Application 需要在 AndroidManifest.xml 中註冊,不能混淆,否則就會報類找不到異常。

-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 

特殊情況:

如果 BroadcastReceiver 是動態註冊的,則是可以加入混淆的。

不混淆任何包含native方法的類的類名以及native方法名
-keepclasseswithmembernames class * {
    native <methods>;
}

不混淆任何一個View中的setXxx()和getXxx()方法,因為屬性動畫需要有相應的setter和getter的方法實現,混淆了就無法工作了。
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

不混淆Activity中參數是View的方法,因為有這樣一種用法,在XML中配置android:onClick=”buttonClick”屬性,當用戶點擊該按鈕時就會調用Activity中的buttonClick(View view)方法,如果這個方法被混淆的話就找不到了。
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

不混淆枚舉中的values()和valueOf()方法

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

不混淆Parcelable實現類中的CREATOR欄位,毫無疑問,CREATOR欄位是絕對不能改變的,包括大小寫都不能變,不然整個Parcelable工作機制都會失敗。
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

不混淆R文件中的所有靜態欄位,我們都知道R文件是通過欄位來記錄每個資源的id的,欄位名要是被混淆了,id也就找不著了。
登錄後複製 
-keepclassmembers class **.R$* {
    public static <fields>;
}
 

其他的常見不被混淆

一般以下情況都會不混淆:

1.使用了自定義控制項那麼要保證它們不參與混淆。

2.使用了枚舉要保證枚舉不被混淆。

3.對第三方庫中的類不進行混淆。

4.運用了反射的類也不進行混淆。

5.使用了 Gson 之類的工具要使 JavaBean 類即實體類不被混淆。

6.在引用第三方庫的時候,一般會標明庫的混淆規則的,建議在使用的時候就把混淆規則添加上去,免得到最後才去找。

7.有用到 WebView 的 JS 調用也需要保證寫的介面方法不混淆,原因和第一條一樣。

8.Parcelable 的子類和 Creator 靜態成員變數不混淆,否則會產生 Android.os.BadParcelableException 異常。

9.供第三放調用的Interface介面不進行混淆。

附一份配置:

  1 # 指定代碼的壓縮級別 0 - 7(指定代碼進行迭代優化的次數,在Android裡面預設是5,這條指令也只有在可以優化時起作用。)
  2 -optimizationpasses 5
  3 # 混淆時不會產生形形色色的類名(混淆時不使用大小寫混合類名)
  4 -dontusemixedcaseclassnames
  5 # 指定不去忽略非公共的庫類(不跳過library中的非public的類)
  6 -dontskipnonpubliclibraryclasses
  7 # 指定不去忽略包可見的庫類的成員
  8 -dontskipnonpubliclibraryclassmembers
  9 #不進行優化,建議使用此選項,
 10 -dontoptimize
 11  # 不進行預校驗,Android不需要,可加快混淆速度。
 12 -dontpreverify
 13 # 屏蔽警告
 14 -ignorewarnings
 15 # 指定混淆是採用的演算法,後面的參數是一個過濾器
 16 # 這個過濾器是谷歌推薦的演算法,一般不做更改
 17 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
 18 # 保護代碼中的Annotation不被混淆
 19 -keepattributes *Annotation*
 20 # 避免混淆泛型, 這在JSON實體映射時非常重要
 21 -keepattributes Signature
 22 # 拋出異常時保留代碼行號
 23 -keepattributes SourceFile,LineNumberTable
 24  #優化時允許訪問並修改有修飾符的類和類的成員,這可以提高優化步驟的結果。
 25 # 比如,當內聯一個公共的getter方法時,這也可能需要外地公共訪問。
 26 # 雖然java二進位規範不需要這個,要不然有的虛擬機處理這些代碼會有問題。當有優化和使用-repackageclasses時才適用。
 27 #指示語:不能用這個指令處理庫中的代碼,因為有的類和類成員沒有設計成public ,而在api中可能變成public
 28 -allowaccessmodification
 29 #當有優化和使用-repackageclasses時才適用。
 30 -repackageclasses ''
 31  # 混淆時記錄日誌(列印混淆的詳細信息)
 32  # 這句話能夠使我們的項目混淆後產生映射文件
 33  # 包含有類名->混淆後類名的映射關係
 34 -verbose
 35 # ----------------------------- 預設保留 -----------------------------
 36 # 保持哪些類不被混淆
 37 #繼承activity,application,service,broadcastReceiver,contentprovider....不進行混淆
 38 -keep public class * extends android.app.Activity
 39 -keep public class * extends android.app.Application
 40 -keep public class * extends android.support.multidex.MultiDexApplication
 41 -keep public class * extends android.app.Service
 42 -keep public class * extends android.content.BroadcastReceiver
 43 -keep public class * extends android.content.ContentProvider
 44 -keep public class * extends android.app.backup.BackupAgentHelper
 45 -keep public class * extends android.preference.Preference
 46 -keep public class * extends android.view.View
 47 -keep class android.support.** {*;}## 保留support下的所有類及其內部類
 48 -keep public class com.google.vending.licensing.ILicensingService
 49 -keep public class com.android.vending.licensing.ILicensingService
 50 #表示不混淆上面聲明的類,最後這兩個類我們基本也用不上,是接入Google原生的一些服務時使用的。
 51 #----------------------------------------------------
 52 # 保留繼承的
 53 -keep public class * extends android.support.v4.**
 54 -keep public class * extends android.support.v7.**
 55 -keep public class * extends android.support.annotation.**
 56 #表示不混淆任何包含native方法的類的類名以及native方法名,這個和我們剛纔驗證的結果是一致
 57 -keepclasseswithmembernames class * {
 58     native <methods>;
 59 }
 60 #這個主要是在layout 中寫的onclick方法android:onclick="onClick",不進行混淆
 61 #表示不混淆Activity中參數是View的方法,因為有這樣一種用法,在XML中配置android:onClick=”buttonClick”屬性,
 62 #當用戶點擊該按鈕時就會調用Activity中的buttonClick(View view)方法,如果這個方法被混淆的話就找不到了
 63 -keepclassmembers class * extends android.app.Activity{
 64     public void *(android.view.View);
 65 }
 66 #表示不混淆枚舉中的values()和valueOf()方法,枚舉我用的非常少,這個就不評論了
 67 -keepclassmembers enum * {
 68     public static **[] values();
 69     public static ** valueOf(java.lang.String);
 70 }
 71 #表示不混淆任何一個View中的setXxx()和getXxx()方法,
 72 #因為屬性動畫需要有相應的setter和getter的方法實現,混淆了就無法工作了。
 73 -keep public class * extends android.view.View{
 74     *** get*();
 75     void set*(***);
 76     public <init>(android.content.Context);
 77     public <init>(android.content.Context, android.util.AttributeSet);
 78     public <init>(android.content.Context, android.util.AttributeSet, int);
 79 }
 80 -keepclasseswithmembers class * {
 81     public <init>(android.content.Context, android.util.AttributeSet);
 82     public <init>(android.content.Context, android.util.AttributeSet, int);
 83 }
 84 #表示不混淆Parcelable實現類中的CREATOR欄位,
 85 #毫無疑問,CREATOR欄位是絕對不能改變的,包括大小寫都不能變,不然整個Parcelable工作機制都會失敗。
 86 -keep class * implements android.os.Parcelable {
 87   public static final android.os.Parcelable$Creator *;
 88 }
 89 # 這指定了繼承Serizalizable的類的如下成員不被移除混淆
 90 -keepclassmembers class * implements java.io.Serializable {
 91     static final long serialVersionUID;
 92     private static final java.io.ObjectStreamField[] serialPersistentFields;
 93     private void writeObject(java.io.ObjectOutputStream);
 94     private void readObject(java.io.ObjectInputStream);
 95     java.lang.Object writeReplace();
 96     java.lang.Object readResolve();
 97 }
 98 # 保留R下麵的資源
 99 -keep class **.R$* {
100  *;
101 }
102 #不混淆資源類下static的
103 -keepclassmembers class **.R$* {
104     public static <fields>;
105 }
106 # 對於帶有回調函數的onXXEvent、**On*Listener的,不能被混淆
107 -keepclassmembers class * {
108     void *(**On*Event);
109     void *(**On*Listener);
110 }
111 # 保留我們自定義控制項(繼承自View)不被混淆
112 -keep public class * extends android.view.View{
113     *** get*();
114     void set*(***);
115     public <init>(android.content.Context);
116     public <init>(android.content.Context, android.util.AttributeSet);
117     public <init>(android.content.Context, android.util.AttributeSet, int);
118 }
119 -keep class com.example.odm.garbagesorthelper.widget.** { *; }
120 #
121 #----------------------------- WebView(項目中沒有可以忽略) -----------------------------
122 #
123 #webView需要進行特殊處理
124 #在app中與HTML5的JavaScript的交互進行特殊處理
125 #我們需要確保這些js要調用的原生方法不能夠被混淆,於是我們需要做如下處理:
126 #
127 #---------------------------------實體類---------------------------
128 #--------(實體Model不能混淆,否則找不到對應的屬性獲取不到值)-----
129 #
130 -keep class com.example.odm.garbagesorthelper.model.entity.** { *; }
131 -dontwarn  com.example.odm.garbagesorthelper.model.entity.**
132 #對含有反射類的處理
133 -keep class com.example.odm.garbagesorthelper.utils.** { *; }
134 #
135 # ----------------------------- 其他的 -----------------------------
136 #
137 # 刪除代碼中Log相關的代碼
138 -assumenosideeffects class android.util.Log {
139     public static boolean isLoggable(java.lang.String, int);
140     public static int v(...);
141     public static int i(...);
142     public static int w(...);
143     public static int d(...);
144     public static int e(...);
145 }
146 # 保持測試相關的代碼
147 -dontnote junit.framework.**
148 -dontnote junit.runner.**
149 -dontwarn android.test.**
150 -dontwarn android.support.test.**
151 -dontwarn org.junit.**
152 #
153 # ----------------------------- 第三方庫、框架、SDK -----------------------------
154 #logger
155 -dontwarn com.orhanobut.logger.**
156 -keep class com.orhanobut.logger.**{*;}
157 -keep interface com.orhanobut.logger.**{*;}
158 # Gson
159 -keep class com.google.gson.stream.** { *; }
160 -keepattributes EnclosingMethod
161 -dontwarn com.google.gson.**
162 -keep class com.google.gson.**{*;}
163 -keep interface com.google.gson.**{*;}
164 #gson
165 #如果用到Gson解析包的,直接添加下麵這幾行就能成功混淆,不然會報錯。
166 ##---------------Begin: proguard configuration for Gson  ----------
167 # Gson uses generic type information stored in a class file when working with fields. Proguard
168 # removes such information by default, so configure it to keep all of it.
169 -keepattributes Signature
170 # For using GSON @Expose annotation
171 -keepattributes *Annotation*
172 # Gson specific classes
173 -dontwarn sun.misc.**
174 #-keep class com.google.gson.stream.** { *; }
175 # Prevent proguard from stripping interface information from TypeAdapterFactory,
176 # JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
177 -keep class * implements com.google.gson.TypeAdapterFactory
178 -keep class * implements com.google.gson.JsonSerializer
179 -keep class * implements com.google.gson.JsonDeserializer
180 # Application classes that will be serialized/deserialized over Gso
181 # OkHttp3
182 -dontwarn okhttp3.logging.**
183 -keep class okhttp3.internal.**{*;}
184 -dontwarn okio.**
185 # Retrofit
186 -dontwarn retrofit2.**
187 -keep class retrofit2.** { *; }
188 #-keepattributes Signature-keepattributes Exceptions
189 # Platform calls Class.forName on types which do not exist on Android to determine platform.
190 -dontnote retrofit2.Platform
191 # Platform used when running on Java 8 VMs. Will not be used at runtime.
192 -dontwarn retrofit2.Platform$Java8
193 # Retain generic type information for use by reflection by converters and adapters.
194 -keepattributes Signature
195 # Retain declared checked exceptions for use by a Proxy instance.
196 -keepattributes Exceptions
197 # RxJava RxAndroid
198 -dontwarn sun.misc.**
199 -keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
200     long producerIndex;
201     long consumerIndex;
202 }
203 -keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
204     rx.internal.util.atomic.LinkedQueueNode producerNode;
205 }
206 -k

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • GreatSQL TPC-H 性能測試報告 - (2024 年 2 月28日) 完整性能測試報告:https://greatsql.cn/docs/8032-25/user-manual/10-optimze/3-3-benchmark-greatsql-tpch-report.html 1、概述 ...
  • 本文分享自華為雲社區《GaussDB(DWS)等待視圖之Hashjoin-nestloop》,作者:Arrow0lf。 1. 業務場景 眾所周知,GaussDB(DWS)中有3種常見的join方式:HashJon/MergeJoin/NestLoop 但在有一些場景中,等待視圖中等待狀態會顯示為:H ...
  • 在資料庫設計中,存儲過程、觸發器、游標、視圖、自定義函數、欄位類型、欄位可空、統計欄位、邏輯刪除以及許可權系統和無限級類別設計都是重要的概念。下麵我將逐一解釋這些概念,並提供相關的設計建議。 存儲過程 (Stored Procedure) 定義:存儲過程是一組為了完成特定功能的SQL語句集,經編譯後存 ...
  • 要實現兩個資料庫之間的實時同步,需要給Oracle設置參數 ALTER DATABASE ADD SUPPLEMENTAL LOG DATA; -- 執行了12小時,等待資料庫中的其它事務都提交以後才執行完成 ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRI ...
  • 北京白鯨開源科技有限公司(以下簡稱“白鯨開源”)今日宣佈,其旗艦產品WhaleStudio套件已與瀚高基礎軟體股份有限公司(以下簡稱“瀚高軟體”)旗下的IvorySQL資料庫管理系統V3.0完成深度相容性認證。此次合作標志著兩家領軍企業在數據管理領域的緊密聯合,為用戶提供更加穩定、高效的數據處理解決 ...
  • 本文分享自華為雲社區《GaussDB(DWS)存儲引擎:從CU入手優化HStore表》,作者: yd_261437590。 1. 前言 適用版本:【8.2.1(及以上)】 HStore同時擁有處理傳統TP場景的事務能力和強大的數據分析能力,但是強大的數據分析能力很可能被小CU問題給破壞,另外,將多個 ...
  • 序言 開年的第一篇文章,今天分享的是SwiftUI,SwiftUI出來好幾年,之前一直沒學習,所以現在才開始;如果大家還留在 iOS 開發,這們語言也是一個趨勢; 目前待業中.... 不得不說已逝的2023年,大家開始都抱著一解封,經濟都會向上轉好,可是現實不是我們想象那樣;目前我也在學習 Swif ...
  • 方案一 :可以用 if來替代 如下 原因:在Android Studio中使用JDK17以上版本,會出現switch語句報錯"Constant expression required"的問題,這是因為在JDK17中switch語句的條件表達式支持使用枚舉類型,而這個特性還沒有被支持。 方案2:換JD ...
一周排行
    -Advertisement-
    Play Games
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...
  • 目錄前言PostgreSql安裝測試額外Nuget安裝Person.cs模擬運行Navicate連postgresql解決方案Garnet為什麼要選擇Garnet而不是RedisRedis不再開源Windows版的Redis是由微軟維護的Windows Redis版本老舊,後續可能不再更新Garne ...
  • C#TMS系統代碼-聯表報表學習 領導被裁了之後很快就有人上任了,幾乎是無縫銜接,很難讓我不想到這早就決定好了。我的職責沒有任何變化。感受下來這個系統封裝程度很高,我只要會調用方法就行。這個系統交付之後不會有太多問題,更多應該是做小需求,有大的開發任務應該也是第二期的事,嗯?怎麼感覺我變成運維了?而 ...
  • 我在隨筆《EAV模型(實體-屬性-值)的設計和低代碼的處理方案(1)》中介紹了一些基本的EAV模型設計知識和基於Winform場景下低代碼(或者說無代碼)的一些實現思路,在本篇隨筆中,我們來分析一下這種針對通用業務,且只需定義就能構建業務模塊存儲和界面的解決方案,其中的數據查詢處理的操作。 ...
  • 對某個遠程伺服器啟用和設置NTP服務(Windows系統) 打開註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer 將 Enabled 的值設置為 1,這將啟用NTP伺服器功 ...
  • title: Django信號與擴展:深入理解與實踐 date: 2024/5/15 22:40:52 updated: 2024/5/15 22:40:52 categories: 後端開發 tags: Django 信號 松耦合 觀察者 擴展 安全 性能 第一部分:Django信號基礎 Djan ...
  • 使用xadmin2遇到的問題&解決 環境配置: 使用的模塊版本: 關聯的包 Django 3.2.15 mysqlclient 2.2.4 xadmin 2.0.1 django-crispy-forms >= 1.6.0 django-import-export >= 0.5.1 django-r ...
  • 今天我打算整點兒不一樣的內容,通過之前學習的TransformerMap和LazyMap鏈,想搞點不一樣的,所以我關註了另外一條鏈DefaultedMap鏈,主要調用鏈為: 調用鏈詳細描述: ObjectInputStream.readObject() DefaultedMap.readObject ...
  • 後端應用級開發者該如何擁抱 AI GC?就是在這樣的一個大的浪潮下,我們的傳統的應用級開發者。我們該如何選擇職業或者是如何去快速轉型,跟上這樣的一個行業的一個浪潮? 0 AI金字塔模型 越往上它的整個難度就是職業機會也好,或者說是整個的這個運作也好,它的難度會越大,然後越往下機會就會越多,所以這是一 ...
  • @Autowired是Spring框架提供的註解,@Resource是Java EE 5規範提供的註解。 @Autowired預設按照類型自動裝配,而@Resource預設按照名稱自動裝配。 @Autowired支持@Qualifier註解來指定裝配哪一個具有相同類型的bean,而@Resourc... ...