Java Android 中的 Proguard 和反射
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4447145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Proguard and reflection in Android
提问by jax
I have just used proguard, but classes I am trying to instantiate via reflection are not working.
我刚刚使用了 proguard,但是我试图通过反射实例化的类不起作用。
I have an interface
我有一个界面
Algorithm
I pass classes like this
我通过这样的课程
AlgorithmFactory.SomeClassThatExtendsAlgorithmImpl.class
The class is instantiated like this
该类是这样实例化的
public ArrayList<Algorithm> getAlgorithms(Context cnx) {
ArrayList<Algorithm> list = new ArrayList<Algorithm>();
for(Class<? extends Algorithm> alg: algorithms) {
try {
Constructor<? extends Algorithm> c = alg.getConstructor(Context.class);
list.add(c.newInstance(cnx));
} catch (IllegalArgumentException e) {
Log.e(TAG, "IllegalArgumentException", e);
throw new IllegalStateException("There was a problem creating the Algorithm class");
} catch (InvocationTargetException e) {
Log.e(TAG, "InvocationTargetException", e);
throw new IllegalStateException("There was a problem creating the Algorithm class");
} catch (InstantiationException e) {
Log.e(TAG, "InstantiationException", e);
throw new IllegalStateException("There was a problem creating the Algorithm class");
} catch (IllegalAccessException e) {
Log.e(TAG, "IllegalAccessException", e);
throw new IllegalStateException("There was a problem creating the Algorithm class");
} catch (SecurityException e) {
Log.e(TAG, "SecurityException", e);
throw new IllegalStateException("There was a problem creating the Algorithm class");
} catch (NoSuchMethodException e) {
Log.e(TAG, "NoSuchMethodException", e);
throw new IllegalStateException("There was a problem creating the Algorithm class");
}
}
return list;
}
Here is my proguard.cnf
这是我的 proguard.cnf
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-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
-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 * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
public static *** w(...);
public static *** e(...);
}
采纳答案by jax
SOLVED
解决了
For others that are having this problem you need to add the following to proguard.cnf
对于遇到此问题的其他人,您需要将以下内容添加到 proguard.cnf
-keep public class * extends com.yoursite.android.yourappname.YourClassName
-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
public <init>(android.content.Context);
}
The first keep tells proguard to not obfuscate class names that extend YourClassName
第一个 keep 告诉 proguard 不要混淆扩展 YourClassName 的类名
The second one says to keep the constructor name (<init>
means constructor) un-obfuscated that has a single argument of Context
and extends YourClassName
第二个说保持构造函数名称(<init>
意思是构造函数)不被混淆,它只有一个参数Context
和扩展YourClassName
In addition, for android developers that are using the onClick attribute in you XML layouts fileyou will also need to add the name of the function in your proguard.cnf file.
此外,对于在 XML 布局文件中使用onClick 属性的Android 开发人员,您还需要在 proguard.cnf 文件中添加函数的名称。
-keepclassmembers class * {
public void myClickHandler(android.view.View);
}
This says keep all methods named myClickHandler
with a single argument View
in all classes. You could further constrain this by using the extends keyword like above.
这表示在所有类中保留以myClickHandler
单个参数命名的所有方法View
。您可以使用上面的 extends 关键字进一步限制这一点。
hope this helps.
希望这可以帮助。
回答by Amir Raminfar
For the on click fix you don't have to list each method name. You can do:
对于点击修复,您不必列出每个方法名称。你可以做:
-keepclassmembers class * {
public void *(android.view.View);
}
which find all methods that have a View as parameter.
查找所有以 View 作为参数的方法。
回答by Drown Coder
Because Compilation process will remove the method which is not used ,so the constructor method will be remove even if you use reflection to call during the compilation process.
因为编译过程会移除没有使用的方法,所以即使在编译过程中使用反射调用,构造函数方法也会被移除。
You could see the method which is be removed during compilation process in the the usage.txt in your project.
您可以在项目的usage.txt 中看到编译过程中删除的方法。
So you should keep the constructor method in proguard file.
因此,您应该将构造函数方法保留在 proguard 文件中。
-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
public <init>(android.content.Context);
}