Android 中的 Proguard 和 Reflection

发布于 2024-10-07 20:12:50 字数 2982 浏览 7 评论 0原文

我刚刚使用了 proguard,但是我尝试通过反射实例化的类不起作用。

我有一个接口

Algorithm

我传递这样的类

AlgorithmFactory.SomeClassThatExtendsAlgorithmImpl.class

该类是这样实例化的

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;
}

这是我的 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(...);
}

I have just used proguard, but classes I am trying to instantiate via reflection are not working.

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

-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(...);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜声 2024-10-14 20:12:50

已解决

对于其他遇到此问题的人,您需要将以下内容添加到 proguard.cnf

-keep public class * extends com.yoursite.android.yourappname.YourClassName

-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
 public <init>(android.content.Context);
}

第一个 keep 告诉 proguard 不要混淆扩展 YourClassName 的类名

第二个表示保留构造函数名称 (表示构造函数)未混淆,具有 Context 的单个参数并扩展 YourClassName

此外,对于在 XML 中使用 onClick 属性的 Android 开发人员布局文件,您还需要在 proguard.cnf 文件中添加函数名称。

-keepclassmembers class * {
 public void myClickHandler(android.view.View);
}

这表示在所有类中保留所有名为 myClickHandler 的方法并带有单个参数 View。您可以通过使用上面的 extends 关键字来进一步限制这一点。

希望这有帮助。

SOLVED

For others that are having this problem you need to add the following to 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

The second one says to keep the constructor name (<init> means constructor) un-obfuscated that has a single argument of Context and extends YourClassName

In addition, for android developers that are using the onClick attribute in you XML layouts file you will also need to add the name of the function in your proguard.cnf file.

-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.

hope this helps.

决绝 2024-10-14 20:12:50

对于单击修复,您不必列出每个方法名称。您可以执行以下操作:

-keepclassmembers class * {
   public void *(android.view.View);
}

查找所有以 View 作为参数的方法。

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.

皓月长歌 2024-10-14 20:12:50

因为编译过程中会移除没有使用到的方法,所以即使在编译过程中使用反射调用,构造方法也会被移除。

您可以在项目的usage.txt中看到编译过程中被删除的方法。

所以你应该将构造函数方法保留在 proguard 文件中。

-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
 public <init>(android.content.Context);
}

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.

So you should keep the constructor method in proguard file.

-keepclassmembers class * extends com.yoursite.android.yourappname.YourClassName{
 public <init>(android.content.Context);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文