Question

I'm currently working on an Android project, in which I'm doing some calculation in C, using Android NDK.

My application works fine as long as I do not run proguard, but when I do, a method "reportProgress", is stripped away by proguard. The method is part of a private inner class that extends AsyncTask

private class CalculateTask extends AsyncTask

I call my native code with a reference to the CalculateTask instance. The native code then call a member in this class, using the following code in JNI

jclass taskClass = (*env)->GetObjectClass(env, task);
jmethodID reportProgressMid = (*env)->GetMethodID(env, taskClass, "reportProgress", "(Ljava/lang/String;I)Z");

where task is the reference to the instance of CalculateTask. I'm having a hard time telling proguard not to strip away the

public boolean reportProgress(String, int)

method, which is only called via JNI.

Until now I have taken the following approaches, none of which did the trick:

Keeping the entire class:

-keep class MYPACKAGENAME.CalculateScreen$CalculateTask

Only keeping the mentioned method, by doing:

-keep class MYPACKAGENAME.CalculateScreen$CalculateTask {
    public boolean reportProgress(java.lang.String,int);
}

Or this:

-keepclassmembers class MYPACKAGENAME.CalculateScreen$CalculateTask {
    public boolean reportProgress(java.lang.String,int);
}

Using annotations (reusing a Google AdMob annotation):

-keep class MYPACKAGENAME.CalculateScreen$CalculateTask {
    @com.google.android.gms.common.annotation.KeepName <methods>;
}

Or this:

-keepclassmembers class MYPACKAGENAME.CalculateScreen$CalculateTask {
    @com.google.android.gms.common.annotation.KeepName <methods>;
}

My proguard configuration is based on the "optimize" distributed with Android SDK, named proguard-android-optimize.txt.

Please note that proguard is run via Gradle, and I have made sure that the proguard task is cleaned and rerun.

Was it helpful?

Solution

Your second and third configuration should work for this case:

-keepclassmembers class MYPACKAGENAME.CalculateScreen$CalculateTask {
    public boolean reportProgress(java.lang.String,int);
}

You should check the class name and method name for typos. You should also check if the method really is public.

You can verify if the method is preserved in bin/proguard/seeds.txt.

You can also check the compiled input class and the processed output class with javap.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top