Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to exempt a library module from pro-guard in android gradle

Release version of my Android app crashes with the following exception

java.lang.NoSuchMethodError: no static or non-static method "Lcom/mm/android/dhproxy/client/DHProxyClient;.InitWithName(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)I"

This error is not found in debug version and hence is because of the proguard I guess.

The above mentioned class is in one of the modules which also use JNI libraries. My proguard-rules for the app module file is below

-keepattributes InnerClasses
-dontoptimize
-keep class com.mm.android.dhproxy.client.DHProxyClient
-keepclasseswithmembernames class * {
    native <methods>;
}
-keep class mypackage.MyCallbackClass {
    void myCallbackMethod(java.lang.String);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-printmapping build/outputs/mapping/release/mapping.txt

The build.gradle file for the concerned module is below

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    compileOptions.encoding = 'ISO-8859-1'

    defaultConfig {

        minSdkVersion 14
        targetSdkVersion 23
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile files('libs/IPlaySDK.jar')
    compile files('libs/ToUProxy.jar')
}

even after adding the line -keep class com.mm.android.dhproxy.client.DHProxyClient I can see that the usage.txt file conatins the following entries

com.mm.android.dhproxy.client.DHProxyClient:
    29:35:public boolean initWithName(java.lang.String,int,java.lang.String,java.lang.String)
    64:69:public int delPort(int)
    136:141:public int queryRate(int,com.mm.android.dhproxy.client.DHProxyRateParam)
    158:163:public int p2pSetOption(int,int)
    180:185:public int p2pGetOption(int)
    192:197:public int exit()
    private native int InitWithName(java.lang.String,int,java.lang.String,java.lang.String)
    private native int DelPort(int,int)
    private native int P2PSetOption(int,int,int)
    private native int P2PGetOption(int,int)
    private native int QueryRate(int,com.mm.android.dhproxy.client.DHProxyRateParam,int)
    private native int Exit(int)
com.mm.android.dhproxy.client.DHProxyRateParam

Thanks in advance.

like image 368
dmSherazi Avatar asked Aug 15 '16 08:08

dmSherazi


2 Answers

The solution is to look up for the methods and classess that needs to be exempted and add them to the proguard rules as follows ( Here I needed to keep the files in classes com.mm.** and com.company.** where ** acts as wild char

-keep class com.mm.** {*;}
-keep class com.company.** {*;}
-keepclassmembers  class com.mm.** {*;}
-keepclassmembers  class com.company.** {*;}
like image 168
dmSherazi Avatar answered Nov 11 '22 01:11

dmSherazi


If you are using external/separate source libraries with your main project/application, you should not use a proguard on the library modules. Instead, you replace the following,

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
    }
    debug {
        minifyEnabled false
    }
}

with the following (in the build.gradle of the library/libraries):

buildTypes {
    release {
        consumerProguardFiles 'proguard-project.txt'
    }
}

where proguard-project.txt is the file that contains the proguard rules for your library project. When building the application (either in debug or release mode), the compiler will take care of all the rules (in the library and in the application).

Source: This stackoverflow answer

like image 38
Zaxter Avatar answered Nov 10 '22 23:11

Zaxter