Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NullPointerException when using XML file in res/raw with Proguard

I am using a simple XML serializer in my app and seem to have successfully excluded it from Proguard obfuscation by using the following lines in proguard.cfg, thanks to this SO question:

-keep public class org.simpleframework.**{ *; } 
-keep class org.simpleframework.xml.**{ *; } 
-keep class org.simpleframework.xml.core.**{ *; } 
-keep class org.simpleframework.xml.util.**{ *; } 

I am able to sign and export the apk, but when I try to run my app, it crashes with a NullPointerException when trying to access an XML file in the res/raw directory (R.raw.home_screen_menu).

I am excluding R.java with this:

-keepclassmembers class **.R$* {
    public static <fields>;
}

I've been playing around with this config file all day, but without any luck. Has anyone come across this problem or something like it? The latest thing I've tried is using the "adaptresource" options like these shown below:

-adaptresourcefilenames    **.xml
-adaptresourcefilecontents **.xml

For reference, here are the contents of my proguard.cfg:

#Use 5 step of optimization 
-optimizationpasses 5

#When not preverifing in a case-insensitive filing system, such as Windows. This tool will unpack your processed jars,(if using windows you should then use):
-dontusemixedcaseclassnames

#Specifies not to ignore non-public library classes. As of version 4.5, this is the default setting
-dontskipnonpubliclibraryclasses

#Preverification is irrelevant for the dex compiler and the Dalvik VM, so we can switch it off with the -dontpreverify option.
-dontpreverify

#Specifies to write out some more information during processing. If the program terminates with an exception, this option will print out the entire stack trace, instead of just the exception message.
-verbose

#The -optimizations option disables some arithmetic simplifications that Dalvik 1.0 and 1.5 can't handle. Note that the Dalvik VM also can't handle aggressive overloading (of static fields).
#To understand or change this check http://proguard.sourceforge.net/index.html#/manual/optimizations.html
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-dump ../bin/class_files.txt
-printseeds ../bin/seeds.txt
-printusage ../bin/unused.txt
-printmapping ../bin/mapping.txt 

-dontskipnonpubliclibraryclassmembers

#Ignore warnings for roboguice.activity.RoboAccountAuthenticatorActivity
-dontwarn roboguice.activity.RoboAccountAuthenticatorActivity

-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 * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keep class com.google.inject.Binder

# Keep annotations
-keepattributes *Annotation*
-keepattributes Signature

#To remove debug logs:
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
    public static *** w(...);
}

# Roboguice
-keepclassmembers class * {
    @com.google.inject.Inject <init>(...);
}

# SimpleXML
-keep public class org.simpleframework.**{ *; } 
-keep class org.simpleframework.xml.**{ *; } 
-keep class org.simpleframework.xml.core.**{ *; } 
-keep class org.simpleframework.xml.util.**{ *; } 
-dontwarn javax.xml.stream.**
-dontwarn javax.xml.namespace.**

-keep public class roboguice.**

# There's no way to keep all @Observes methods, so use the On*Event convention to identify event handlers
-keepclassmembers class * { 
    void *(**On*Event); 
}

-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

-keepclasseswithmembers class * {
    native <methods>;
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

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

-keepclassmembers class * implements android.os.Parcelable {
    static android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}
like image 492
Ben Jakuben Avatar asked Oct 19 '25 14:10

Ben Jakuben


2 Answers

I have exactly the same problem. Finally I solve it thanks to this question and answer. I left here the final configuration:

build.gradle:

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

dependencies {
    compile('org.simpleframework:simple-xml:2.7.1') {
        exclude module: 'stax'
        exclude module: 'stax-api'
        exclude module: 'xpp3'
    }
}

proguard-rules.pro (addition to default proguard config)

-dontwarn javax.xml.**

-keep public class org.simpleframework.**{ *; }
-keep class org.simpleframework.xml.**{ *; }
-keep class org.simpleframework.xml.core.**{ *; }
-keep class org.simpleframework.xml.util.**{ *; }

-keepattributes Signature
-keepattributes *Annotation*

# Ignore our XML Serialization classes
-keep public class your.annotated.pojo.models.*{
  public protected private *;
}

Hope it helps to somebody

like image 162
sabadow Avatar answered Oct 22 '25 06:10

sabadow


Turns out the raw files were left alone and okay. The problem was my class used for serialization with annotations for the Simple XML serializer. I added log statements to my app and found this error at the offending line: "Attribute 'id' does not have a match in class com.xxx.ListViewItems at line 2". This made me realize that the private "id" variable was being obfuscated and not recognized by the Simple XML serializer. Here's the code from ListViewItems.java:

@Attribute(required=false)
private String id;  // This was being obfuscated and thus unrecognizable!

Here's what I added to Proguard to completely skip obfuscating a class (there is probably a better way):

# Ignore our XML Serialization classes
-keep public class com.xxx.ListViewItems {
  public protected private *;
}
like image 25
Ben Jakuben Avatar answered Oct 22 '25 07:10

Ben Jakuben