在Android开发中,代码混淆(ProGuard或R8)是通过重命名和优化代码来提高应用的安全性。然而,某些类和成员不能被混淆,以确保应用的正常运行。这些类通常包括反射调用、JNI、序列化和框架特定的类。以下是一些不能混淆的类和方法:
1. 反射使用的类和方法
如果代码使用反射来访问类或方法,这些类和方法不能被混淆,因为反射是通过字符串名称进行查找的,混淆会导致名称变化,使反射查找失败。
示例
public class ReflectionExample {
public void exampleMethod() {
// 反射调用方法
Method method = SomeClass.class.getMethod("methodName");
method.invoke(someInstance);
}
}
ProGuard配置
-keepclassmembers class * {
public *;
}
2. 序列化类
如果类实现了 Serializable
接口,序列化和反序列化过程中使用的类名和字段名不能被混淆,否则可能导致序列化失败。
示例
public class User implements Serializable {
private String name;
private int age;
}
ProGuard配置
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException;
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException;
java.lang.Object writeReplace() throws java.io.ObjectStreamException;
java.lang.Object readResolve() throws java.io.ObjectStreamException;
}
3. JNI(Java Native Interface)使用的类和方法
JNI通过字符串查找Java方法,如果这些方法被混淆,JNI调用会失败。
示例
public class JniExample {
public native void nativeMethod();
}
ProGuard配置
-keepclasseswithmembernames class * {
native <methods>;
}
4. 使用特定注解的类和方法
某些框架和库(如Gson、Retrofit、Dagger、ButterKnife等)依赖注解进行依赖注入、JSON序列化和反序列化等操作,这些类和方法不能被混淆。
Gson示例
public class User {
@SerializedName("user_name")
private String name;
}
ProGuard配置
-keep class com.example.app.models.** { *; }
-keep class com.google.gson.annotations.** { *; }
5. Android四大组件和与系统交互的类
Android的四大组件(Activity、Service、BroadcastReceiver、ContentProvider)以及使用Intent、Bundle等与系统交互的类不能被混淆。
在Android应用中,四大组件(Activity、Service、BroadcastReceiver、ContentProvider)可以被混淆,但需要注意的是,其名称不能被混淆,因为它们的名称通常在AndroidManifest.xml文件中被引用,并且这些名称在运行时需要保持不变。所以我们一般说四大组件不能被混淆。
示例
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
ProGuard配置
-keep class * extends android.app.Activity
-keep class * extends android.app.Service
-keep class * extends android.content.BroadcastReceiver
-keep class * extends android.content.ContentProvider
-keep public class * extends android.app.Application
-keep public class * extends android.app.Instrumentation
-keep class * implements android.os.Parcelable
6. 库和框架相关的类
一些第三方库和框架(如Retrofit、ButterKnife、Dagger、EventBus等)要求特定的类和方法不能被混淆,以确保它们的正确运行。
示例(Retrofit)
-keep class retrofit2.** { *; }
-keep class okhttp3.** { *; }
-keep class okio.** { *; }
-keepattributes Signature
-keepattributes Exceptions
示例(ButterKnife)
-keep class butterknife.** { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
7. 自定义视图
自定义视图类通常在XML布局中引用,类名不能被混淆。
示例
public class MyCustomView extends View {
// 自定义视图代码
}
ProGuard配置
-keep class com.example.app.views.MyCustomView { *; }
总结
在代码混淆过程中,需要确保以下几类代码不被混淆:
- 反射使用的类和方法。
- 序列化类。
- JNI使用的类和方法。
- 使用特定注解的类和方法。
- Android四大组件和与系统交互的类。
- 库和框架相关的类。
- 自定义视图。
通过适当的ProGuard配置,可以确保这些关键类和方法不被混淆,从而保证应用的正常运行。