android - how to keep enum from proguard - android

In my proguard, I have the following to keep public enums from being obfuscated.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
My question is, does this also keep the public enum Currency in a class like this?
public class Foo {
public enum **Currency** {PENNY, NICKLE, DIME, QUARTER};
...
}
If not, what do I have to add separately?
Adding the following doesn't seem to help.
-keepattributes InnerClasses
Any advice? Thanks

You could try
-keep public enum com.stuff.TheEnclosingClass$** {
**[] $VALUES;
public *;
}
As shown on this answer Proguard won't keep a class member's enums
Just don't forget to put
-keepattributes InnerClasses

Can you try to tell proguard to keep the specific class:
-keep class com.xxx.Foo { *; }

The option -keepclassmembers only keeps the class members; in this case the methods values() and valueOf(String) of all enum classes. The wild card * also matches internal classes.
If you for some reason want to preserve the inner class with its original name, you can specify:
-keep class somepackage.Foo$Currency
That should only be necessary if your application accesses the class through reflection.

If you want to safe enum names and all fields, methods for it:
-keep enum * { *; }

Related

Android apk not connecting to Azure server after using proguard

I have been looking to a solution to this problem, i have tried many proguard configurations without success.
The app runs perfectly until I make the release version with proguard.
I am getting the error:
"java.lang.IllegalArgumentException:The class representing the mobile serviceTable must have a single id property defined" while assigning the class
I belive that is caused by the class of the table that i am trying to reach, having its variable 'id' name changed.
I have the folowing:
public class User {
public String id;
public String nickname;
public String phone;
}
and the connection is made with:
mClient.getTable(User.class).where().field("nickname")
.eq(nick).execute(new TableQueryCallback<User>() {....
the proguard config file is:
-keep class com.microsoft.azure.storage.table.** { *; }
-dontwarn com.fasterxml.jackson.core**
-keep class com.microsoft.windowsazure.mobileservices.** { *; }
-dontwarn android.os.**
-dontwarn com.microsoft.windowsazure.mobileservices.RequestAsyncTask
##---------------from here is the part that i have modified a lot of times -
-keepattributes Signature
-keepattributes *Annotation*
-keep public class com.company.app.User.** { *; }
-keepclassmembers public class com.company.app.User.** { *; }
I have tried many modifications for hours without success.
I followed this and this among many others.
Can you please help me?
Thanks
EDIT: solved. Just remove the .** after User in the proguard file. Leave it like this:
-keep public class com.company.app.User { *; }
-keepclassmembers public class com.company.app.User { *; }
solved. Just remove the .** after User in the proguard file. Leave it like this:
-keep public class com.company.app.User { *; }
-keepclassmembers public class com.company.app.User { *; }

Proguard Obfuscation Enum Issue

I have following Enum class in my Java package
public enum UIType {
NATIVE,WEB;
}
I have applied following proguard config to keep this enum class
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep public enum android.ui.UIType {
public static **[] values();
public static ** valueOf(java.lang.String);
}
But when I offuscate my jar file,proguard keeps the UIType enum class but removes both NATIVE,WEB values.
In my obfuscated jar my Enum class looks as follows.
public enum UIType {
}
As seen above NATIVE,WEB values are removed by proguard :(.It is causing issue in my application since it is not finding those values.
Can somebody please guide me here what I am doing wrong.
Thanks
As I understand, you ask it to keep the methods values() and valueOf(), but not the values themselves.
Try
-keep public class com.ggg.xxx.Yyy { *; }

Getting java.lang ExceptionInInitializerError when initializing ACRA

I integrated ACRA to my application to get crash reports from my app in beta stadium so I'm able to fix bugs, find errors in code, etc. If I run this on the emulator everything works fine and ACRA is up and running, but if I export a signed package of my application with Android Tools I get an ExceptionInInitializeError and the application is force closed on the device. If I catch this Error and proceed without ACRA the app itself runs like a charm...
has anybody here got the same issue with ACRA? could it be that it has something to do with ProGuard? I followed the ProGuard how to on ACRA homepage but perhaps I'm missing something on this?
here's what my proguard.cfg looks like:
-injars 'C:\Workspaces\motodevWs\gp2012\bin\classes'
-injars 'C:\Workspaces\motodevWs\gp2012\libs'
-outjars 'C:\Workspaces\motodevWs\gp2012\bin\classes-processed.jar'
-libraryjars 'C:\android\android-sdk\platforms\android-7\android.jar'
-libraryjars 'C:\android\android-sdk\add-ons\addon_google_apis_google_inc_7 \libs\maps.jar'
-optimizations !code/simplification/arithmetic
-allowaccessmodification
-repackageclasses ''
-keepattributes *Annotation*,SourceFile,LineNumberTable,*Annotation*
-renamesourcefileattribute SourceFile
-dontpreverify
-dontwarn java.awt.**,javax.security.**,java.beans.**,com.sun.**
-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.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 * {
public <init>(android.content.Context,android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context,android.util.AttributeSet,int);
}
-keepclassmembers class * extends android.os.Parcelable {
static android.os.Parcelable$Creator CREATOR;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
# keep this class so that logging will show 'ACRA' and not a obfuscated name like 'a'.
# Note: if you are removing log messages elsewhere in this file then this isn't necessary
-keep class org.acra.ACRA {
<fields>;
<methods>;
}
# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode {
<fields>;
<methods>;
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter {
public void addCustomData(java.lang.String,java.lang.String);
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter {
public org.acra.ErrorReporter$ReportsSenderWorker handleSilentException(java.lang.Throwable);
}
PROBLEM SOLVED!
After some effort on research and rethinking my problem I found the solution to the problem and it was indeed in my proguard.cfg file where I missed something!
somehow I managed not to keep enums, now I added
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
to my proguard.cfg and everything is working perfectly!!
So, to close this question with the answer I found myself, here is what I did to resolve this particular problem :) (taken from my question post):
After some effort on research and rethinking my problem I found the solution to the problem and it was indeed in my proguard.cfg file where I missed something!
somehow I managed not to keep enums, now I added
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
to my proguard.cfg and everything is working perfectly!!
THere is now a wiki concerning using ACRA with ProGuard
https://github.com/ACRA/acra/wiki/Proguard

How to tell ProGuard to keep everything in a particular package?

My application has many activities and uses native library too. With the default ProGuard configuration which Eclipse generates ProGuard removes many things - OnClick methods, static members, callback methods which my native library uses... Is it there a simple way to instruct ProGuard to NOT remove anything from my package? Removing things saves only about 2.5% of the application size, but breaks my application completely. Configuring, testing and maintaining it class by class in ProGuard configuration would be a pain.
EDIT This answer is 10 years old - it may not apply to newer proguard versions.
I think you need to add these flags at the very least (modify for you individual package names):
-keep class javax.** { *; }
-keep class org.** { *; }
-keep class twitter4j.** { *; }
Also, add these flags:
-dontshrink
-dontoptimize
-dontpreverify
Here's my whole config file: of my Proguard.cfg:
-dontshrink
-dontoptimize
-dontpreverify
-verbose
-dontwarn javax.management.**
-dontwarn java.lang.management.**
-dontwarn org.apache.log4j.**
-dontwarn org.apache.commons.logging.**
-dontwarn org.slf4j.**
-dontwarn org.json.**
-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 javax.** { *; }
-keep class org.** { *; }
-keep class twitter4j.** { *; }
-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 *;
}
As final result I found that just keeping all class members is not enough for the correct work of my application, nor necessary. I addded to the settings file this:
-keepclasseswithmembers class * {
void onClick*(...);
}
-keepclasseswithmembers class * {
*** *Callback(...);
}
The case with onClick* is for all methods which I address in android:onClick atribute in .xml layout files (I begin the names of all such methods with 'onClick').
The case with *Callback is for all callback methods which I call from my native code (through JNI). I place a suffix 'Callback' to the name of every such method.
Also I added few rows for some special cases with variables which I use from native code, like:
-keep class com.myapp.mypackage.SomeMyClass {
*** position;
}
(for a varible with name 'position' in a class with name 'SomeMyClass' from package com.myapp.mypackage)
All this is because these onClick, callback etc. must not only be present but also kept with their original names. The other things ProGuard can optimize freely.
The case with the native methods is important also, but for it there was a declaration in the generated from Eclipse file:
-keepclasseswithmembernames class * {
native <methods>;
}
I know this is an old question but I hope that the following information might help other people.
You can prevent ProGuard from removing anything in a certain package as follows;
-keep,allowoptimization,allowobfuscation class com.example.mypackage.** { *; }
Using the modifiers allowoptimization and allowobfuscation will make sure that ProGuard still obfuscates and optimizes the code. Shrinking will of course be disabled as intended.
You can easily verify how these -keep rules affect the code without the need to (re-)build using the ProGuard Playground.

ProGuard and Gson on Android (ClassCastException)

I am having a hell of a time with Gson and ProGuard. I have a simple object and when I parse tojson, save to sqllite and read back from the database in order to load the json back to my object, I get a java.lang.classcastexception. If I dont use ProGuard, everthing works fine.
I have verified that the json string being sent to and gotten from the database is the same. The exception is not thrown when it converts from json, but rather when I try to access the object.
Here is my simple object:
public class ScanLog extends ArrayList<SingleFrame>
{
private static final long serialVersionUID = 1L;
public ScanLog()
{
}
}
public final class SingleFrame
{
public int Position;
public int Time;
public Map<Integer,String> MainDataMap;
public Map<Integer,String> DataMap;
public SingleFrame(int position, int time,
Map<Integer,String> mainDataMap, Map<Integer,String> dataMap)
{
this.Position = position;
this.Time = time;
this.MainDataMap = mainDataMap;
this.DataMap = dataMap;
}
}
All other aspects of my app are fine, but something with proguard is causing this to happen....Ive tried all kinds of -keep commands in the proguard.cfg but I am not sure what Im doing is right.
EDIT - ADDING PROGUARD.CFG
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-dontshrink
-dontoptimize
-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 all classes that might be used in XML layouts
-keep public class * extends android.view.View
-keep public class * extends android.app.Fragment
-keep public class * extends android.support.v4.Fragment
#keep all classes
-keep public class *{
public protected *;
}
#keep all public and protected methods that could be used by java reflection
-keepclassmembernames class * {
public protected <methods>;
}
-keepclasseswithmembernames class * {
native <methods>;
}
-keep public class org.scanner.scanlog.SingleFrame
-keepclassmembers class org.scanner.scanlog.ScanLog {
private <fields>;
public <fields>;
}
-keepclassmembers class org.scanner.scanlog.SingleFrame {
private <fields>;
public <fields>;
}
-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 *;
}
-dontwarn **CompatHoneycomb
-dontwarn org.htmlcleaner.*
#-keep class android.support.v4.** { *; }
EDIT - Okay I got ACRA set up successfully in my app, pretty awesome feature!
Here is the stack trace:
java.lang.ClassCastException: java.lang.Object
at org.scanner.activity.ReaderMainActivity.AdvanceScanLog(SourceFile:1499)
at org.scanner.activity.r.onProgressChanged(SourceFile:271)
at android.widget.SeekBar.onProgressRefresh(SeekBar.java:89)
at android.widget.ProgressBar.doRefreshProgress(ProgressBar.java:507)
at android.widget.ProgressBar.refreshProgress(ProgressBar.java:516)
at android.widget.ProgressBar.setProgress(ProgressBar.java:565)
at android.widget.AbsSeekBar.trackTouchEvent(AbsSeekBar.java:337)
at android.widget.AbsSeekBar.onTouchEvent(AbsSeekBar.java:292)
at android.view.View.dispatchTouchEvent(View.java:3932)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:906)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1784)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1157)
at android.app.Activity.dispatchTouchEvent(Activity.java:2181)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1759)
at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2336)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1976)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:4263)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
For the latest version of the recommended proguard configuraiton file, please see the gson supplied android proguard example at:
https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg
These settings in the config worked for me in one of my apps:
# Add the gson class
-keep public class com.google.gson
# Add any classes the interact with gson
-keep class com.someapp.android.models.ChatModel { *; }
-keep class com.someapp.android.models.FeedModel { *; }
# Add the path to the jar
-libraryjars /Users/someuser/Documents/workspace/someapp/lib/gson-1.7.1.jar
Hopefully this helps you out.
Applying the changes found in the Android example in the Gson project worked for me
The lines needed were:
-keepattributes Signature
-keep class sun.misc.Unsafe { *; }
# and keeping the classes that will be serialized/deserialized
I know the original question was resolved by taking a different approach, but I was having a very similar issue using flexjson and Proguard on Android, and I've solved it, in case anyone runs into it themselves.
When converting back from JSON to my value object which included some ArrayLists, I would get the same ClassCastException. I got it to work by basically having obfuscation enabled but turning all parts of obfuscation off (-keep everything, -keepclassmembers everything and -keepattributes everything) and then working backwards by enabling things a bit at a time.
The result; keeping the entire flexjson library:
-keep class flexjson**
--keepclassmembers class flexjson** {
*;
}
and keeping the Signature and Annotation attribute:
-keepattributes Signature, *Annotation*
I was able to use the flexjson library without incident after that in a proguarded, release version of my app.
I was getting errors for Model classes with proguard If you look at
GSON Proguard you will find a line
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { *; }
replace com.google.gson.examples.android.model. with your model package likewise in my case i replaced it with -keep class com.consumer.myProject.model.** { *; }
rest I copied as such
So, I ended up ditching the Gson library and instead of converting my object to json using gson, I created a custom class in my app to serialize and deserialize the object and store the data that way.
I am overall more happy, even though this has cost me over 12 hours of trying to figure it out. Apparently, PROGUARD and gson must not like each other too much?
As A HUGELY added benefit to not having to use GSON, I noticed that by taking out the GSON library, my app size is cut in half. My app was 577kb and is now only 260kb after removing the gson lib.
It does look like your are keeping everything from your class (fields, methods and the class itself). But to make sure you can add -printseeds outputfile.txt to the proguard.cfg file to verify that proguard really keeps everything you need once obfuscation is done.
BTW, you might think about adding something like ACRA or Android Remote stacktrace that allows you to inspect stacktraces on a built app.
Just to add to all of the other answers, if you guys reached here, it means that you want to obfuscate your code AND use Gson.
If, at the end, you chose to -keep class your instances, it means that these Gson classes WILL NOT BE OBFUSCATED and this solution (or even Gson in general, is not an optimal solution for you).
In this case I would advise to Serialize the classes yourself and store them See #Jessy's answer.

Categories

Resources