Hướng dẫn config proguard cho library module
Lý do tại sao phải sử dụng proguard cho các project đã có quá nhiều bài viết đã chia sẻ rồi nên mình xin phép sẽ không nhắc lại nữa. Trong bài viết này mình sẽ hướng dẫn các bạn cấu hình proguard cho module library để mã hóa code khi export ra file aar Xác định các thành phần sẽ chia sẻ Khi ...
Lý do tại sao phải sử dụng proguard cho các project đã có quá nhiều bài viết đã chia sẻ rồi nên mình xin phép sẽ không nhắc lại nữa.
Trong bài viết này mình sẽ hướng dẫn các bạn cấu hình proguard cho module library để mã hóa code khi export ra file aar
Xác định các thành phần sẽ chia sẻ
Khi bạn phát triển module library dĩ nhiên bạn sẽ cần bảo đảm tính chất bao đóng(OOP) cho các đối tương, phương thức, thuộc tính. Nên khi export module thành aar bạn cũng chỉ cần cung cấp cho người dùng những gì bạn đặt modifier là public hoặc protected
Cấu hình file proguard
bạn có thể tìm hiểu chi tiết về các cấu hình của proguard tại đây
https://www.guardsquare.com/en/products/proguard/manual/refcard
Dưới đây là những cấu hình mình hay sử dụng khi proguad library module
-optimizationpasses 5 -dontusemixedcaseclassnames -repackageclasses ' -allowaccessmodification -dontskipnonpubliclibraryclasses -dontskipnonpubliclibraryclassmembers -dontpreverify -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable -keepparameternames -renamesourcefileattribute SourceFile -keepclassmembers,allowoptimization enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -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(); }
Đối với kotlin bạn có thể thêm
-dontwarn kotlin.** -dontwarn kotlin.reflect.jvm.internal.**
Bây giờ chúng ta sẽ tiến hành cấu hình cho những class public/protected của mình(mặc định nếu bạn không cấu hình thì những class kể cả public thì bên ngoài cũng không thể truy cập được)
Trong module của mình có 2 class Test và A
class Test { @Keep companion object { /** * Say hello to every body * @param name *@author BacNV * */ @JvmStatic fun sayHello(name: String): String { return A.hello() } @JvmStatic fun getInstance(context: Context): Test { return Test() } } /** * Say hi to every body *@author BacNV * */ fun sayHi(): String { goodMorning() return A().hi() } fun goodAfternoon(): String { return "Good afternoon" } private fun goodMorning() { Log.e(javaClass.name, "Good morning") } }
Note:
- đối với kotlin những method là static thì bạn phải thêm annotation @JvmStatic để các class java có thể gọi nó như 1 method static bình thường của java
- nếu bạn muốn giữ các method static khi build proguard bạn cần thêm annotation @Keep
class A{ companion object { fun hello() = "AAAAAAAAAAAAA" } fun hi() = "bbbbbbbbbbbbbbbbb" }
trong proguard mình sẽ cấu hình như sau
-keep class com.framgia.mylibrary.Test{ static *** Companion; public static *** sayHello(...); public *** sayHi(); }
ở đây mình sẽ chỉ cấu hình để keep lại class Test và trong class test mình sẽ khai báo các phương thức hoặc thuộc tính mình muốn keep Note: đối với kotlin bạn bắt buộc phải thêm static *** Companion; thì mới có thể truy xuất vào các method static được nhé
Enable proguard
mặc đinh proguard sẽ không được bật nên nếu proguard chưa được bật cho dù bạn đã cấu hình cho proguard như nào thì khi build ra aar thì code của bạn cũng vẫn hiển thị dưới dạng nguyên bản.
Để bật proguard các bạn vào build.gradle của module sau đó thêm vào root android:
buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }
Thực thi
sau khi build ra aar và đưa vào trong project chúng ta sẽ nhìn thấy như sau
public final class Test { public static final Test.Companion Companion = new Test.Companion((DefaultConstructorMarker)null); @NotNull public final String sayHi() { this.a(); return (new a()).a(); } private final void a() { Log.e(this.getClass().getName(), "Good morning"); } @JvmStatic @NotNull public static final String sayHello(@NotNull String name) { return Companion.sayHello(name); } @Metadata( mv = {1, 1, 11}, bv = {1, 0, 2}, k = 1, d1 = {"u0000u0014 u0002u0018u0002 u0002u0010u0000 u0002u0002 u0002u0010u000e u0002u0002u0087u0003u0018u00002u00020u0001Bu0007u0002¢u0006u0002u0010u0002Ju0010u0010u0003u001au00020u00042u0006u0010u0005u001au00020u0004Hu0007¨u0006u0006"}, d2 = {"Lcom/framgia/mylibrary/Test$Companion;", "", "()V", "sayHello", "", "name", "mylibrary_release"} ) @Keep public static final class Companion { @JvmStatic @NotNull public final String sayHello(@NotNull String name) { Intrinsics.checkParameterIsNotNull(name, "name"); return a.a.a(); } private Companion() { } // $FF: synthetic method public Companion(DefaultConstructorMarker $constructor_marker) { this(); } } }
bạn có thể thấy những class/method mà chúng ta không keep lại nó đã bị ẩn đi và không thể nhìn thấy được
Kết luận
Như vậy mình đã hướng dẫn các bạn có thể sử dụng proguard để bảo vệ source code của mình, hi vọng các bạn có thể sử dụng nó linh hoạt trong các project của mình.