I have developed an android application that uses Enums in many modules. Now i am trying to protect my application from reverse engineering, for this purpose i have enabled proguard in my application but the issue is after enabling proguard my application crashes wherever i have used Enums.
I have created the following class to define all enums
package app.mypackagename.utils;
import android.content.Context;
public class EnumUtils {
public static enum AppDomain {
LIVE, STAGING, MOCK
}
public static enum UserRole {
CUSTOMER, ADMIN;
}
public static enum Module {
REGISTRATION, PRODUCT
}
}
Enum "UserRole" is being used inside a model class "User"
package app.mypackagename.flavors.models;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import app.mypackagename.utils.EnumUtils;
public class User {
#SerializedName("sulLevelcode")
public String sulLevelcode;
public EnumUtils.UserRole userRole = null;
}
On successful login i am checking the user role using following code
Gson gson = new Gson();
Type listType = new TypeToken<User>() {
}.getType();
onlineUser = ((User) gson.fromJson(taskItem.getRawResponse(),
listType));
onlineUser.userID = userId;
if (onlineUser.sulLevelcode.equalsIgnoreCase(Constants.LEVEL_CODE_CUSTOMER)) {
onlineUser.userRole = EnumUtils.UserRole.CUSTOMER;
}
But applications always crashes on accessing Enum value.
Below is the crash trace
java.lang.AssertionError: java.lang.NoSuchFieldException: CUSTOMER
at b.b.c.b.a.ja$a.<init>(:808)
at b.b.c.b.a.V.a(:834)
at b.b.c.p.a(:423)
at b.b.c.b.a.p.a(:115)
at b.b.c.b.a.p.a(:164)
at b.b.c.b.a.p.a(:100)
at b.b.c.p.a(:423)
at b.b.c.p.a(:886)
at b.b.c.p.a(:852)
at b.b.c.p.a(:801)
at app.mypackagename.activities.k.a(:355)
at app.mypackagename.f.c.a(:442)
at app.mypackagename.f.c.a(:43)
at app.mypackagename.f.b.a(:288)
at app.mypackagename.f.b.a(:271)
at b.c.a.b.m.c(:107)
at b.c.a.b.m.b(:141)
at b.c.a.b.m.a(:128)
at b.c.b.A.a(:456)
at b.c.a.b.m.c(:107)
at b.c.a.b.m.b(:141)
at b.c.a.b.m.a(:128)
at b.c.b.r.run(:246)
at b.c.a.y$d.run(:60)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6577)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:986)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
Caused by: java.lang.NoSuchFieldException: CUSTOMER
at java.lang.Class.getField(Class.java:1549)
at b.b.c.b.a.ja$a.<init>(:797)
at b.b.c.b.a.V.a(:834)
at b.b.c.p.a(:423)
at b.b.c.b.a.p.a(:115)
at b.b.c.b.a.p.a(:164)
at b.b.c.b.a.p.a(:100)
at b.b.c.p.a(:423)
at b.b.c.p.a(:886)
at b.b.c.p.a(:852)
at b.b.c.p.a(:801)
at app.mypackagename.activities.k.a(:355)
at app.mypackagename.f.c.a(:442)
at app.mypackagename.f.c.a(:43)
at app.mypackagename.f.b.a(:288)
at app.mypackagename.f.b.a(:271)
at b.c.a.b.m.c(:107)
at b.c.a.b.m.b(:141)
at b.c.a.b.m.a(:128)
at b.c.b.A.a(:456)
at b.c.a.b.m.c(:107)
at b.c.a.b.m.b(:141)
at b.c.a.b.m.a(:128)
at b.c.b.r.run(:246)
at b.c.a.y$d.run(:60)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6577)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:986)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)
Below is my proguard rules file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-dontwarn com.alcorlink.**
-dontwarn com.google.android.**
-dontwarn androidx.media.**
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class app.app.mypackagename.utils.EnumUtils { *; }
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON #Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class app.mypackagename.flavors.models.User.** { <fields>; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in #JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
#com.google.gson.annotations.SerializedName <fields>;
}
##---------------End: proguard configuration for Gson ----------
I have tried almost every solution available on Stack Overflow but i am unable to solve this issue.
Some from the ways i tried
--keep class app.mypackagename.utils.EnumUtils{ *; }
-keep class app.mypackagename.flavors.models.User.** { *; }
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers enum * { *; }
-keepclassmembers enum app.mypackagename.** { *; }
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep public enum app.mypackagename.utils.EnumUtils** {
**[] $VALUES;
public *;
}
-keepattributes AppDomain
-keepattributes UserRole
Can somebody please help me out with this. Any help will be appreciated.
I had the same issue, but adding this line to my proguard-rules.pro worked -
-keep class app.mypackagename.constants.* { <fields>; }.
where "app.mypackagename.constants" is the package where all my enums are located.
Related
Use case
I'd like to add programmatically an externally provided annotation named: #Trace
to all public methods in the spring-boot project
that are in a class annotated with #Controller
only within a particular package (com.example.apectitddemo.controller)
only if the method doesn't have a different custom annotation already applied, f.e. #Disable
Thanks to the above criteria, each newly added method to the project that meets them all will be #Trace annotated dynamically without any additional developer action, which is the main goal here.
My approach
I used Aspectj's ITD (inter type declaration) for this but it fulfills only 1st requirement and have no idea how to customize it for 2nd, 3rd and 4th.
Tried several ways commented out in the below code snipped.
TracingAspect.aj:
package com.example.apectitddemo.aspect;
public aspect TracingAspect {
declare #method : public * *(..) : #Trace;
//[INFO] 'public void com.example.apectitddemo.controller.ControllerPing.ping()' (ControllerPing.java) is annotated with #Trace method annotation from 'com.example.apectitddemo.aspect.TracingAspect' (TracingAspect.aj)
// declare #method : public * ((#Controller *)).*(..) : #Trace;
// declare #method : public * ((#Controller *)).*(..) && !#Disabled : #Trace;
// declare #method : public com.example.apectitddemo.controller.* :#Trace;
// declare #method : public * com.example.apectitddemo.controller+ : #Trace;
// declare #method : public * *(com.example.apectitddemo.controller.*) : #Trace;
// declare #method : public * controller..* : #Trace;
// declare #method : public * *(..) : #Trace;
}
BTW is it possible to use pure java here (TracingAspect.java) and not as .aj file?
ControllerPing.java (sample method which should be annotated by an aspect)
package com.example.apectitddemo.controller
#Controller
public class ControllerPing {
//#Trace annotation should be added here by ITD
public void ping() {
log.info("ok");
}
#Disable
public void pingDisabled() {
log.info("ok");
}
}
Misc
I was searching the internet but haven't found much documentation and even couldn't encounter any other code samples except below. The above solution is based on this finding:
how to write an aspectj itd to add an annotation to a method?
Other pages found, related:
https://www.eclipse.org/aspectj/doc/released/adk15notebook/ataspectj-itds.html
http://kto.web.elte.hu/hu/oktatas/aop_en.pdf
samples are empty :/ https://www.eclipse.org/aspectj/doc/released/examples/
Maybe there is another better way to complete the requirements?
This is a native AspectJ example. You can run it completely without Spring or from within a Spring application - up to you:
Annotations:
package de.scrum_master.stackoverflow.q73270343;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target({ METHOD })
public #interface Trace {}
package de.scrum_master.stackoverflow.q73270343;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target({ METHOD })
public #interface Disable {}
Non-controller class (negative test):
package de.scrum_master.stackoverflow.q73270343;
public class NoControllerPing {
// #Trace annotation should NOT be added here by ITD
public void ping() {
System.out.println("No controller ping");
}
#Disable
public void pingDisabled() {
System.out.println("No controller pingDisabled");
}
}
Controller class and driver application:
package de.scrum_master.stackoverflow.q73270343;
import org.springframework.stereotype.Controller;
#Controller
public class ControllerPing {
// #Trace annotation should be added here by ITD
public void ping() {
System.out.println("Controller ping");
}
#Disable
public void pingDisabled() {
System.out.println("Controller pingDisabled");
}
public static void main(String[] args) {
new ControllerPing().ping();
new ControllerPing().pingDisabled();
new NoControllerPing().ping();
new NoControllerPing().pingDisabled();
}
}
Native syntax AspectJ aspect:
package de.scrum_master.stackoverflow.q73270343;
public aspect TracingAspect {
declare #method : !#Disable public !static * (#org.springframework.stereotype.Controller *..*).*(..) : #Trace;
before() : #annotation(Trace) && execution(* *(..)) {
System.out.println(thisJoinPoint);
}
}
Console log:
execution(void de.scrum_master.stackoverflow.q73270343.ControllerPing.ping())
Controller ping
Controller pingDisabled
No controller ping
No controller pingDisabled
See AspectJ manual.
BTW is it possible to use pure java here (TracingAspect.java) and not as .aj file?
No, it is not. Quote from the AspectJ manual:
Inter-type declarations are challenging to support using an annotation style. For code style aspects compiled with the ajc compiler, the entire type system can be made aware of inter-type declarations (new supertypes, new methods, new fields) and the completeness and correctness of it can be guaranteed. Achieving this with an annotation style is hard because the source code may simply be compiled with javac where the type system cannot be influenced and what is compiled must be 'pure java'.
You only have #DeclareParents, #DeclareMixin, #DeclarePrecedence, #DeclareWarning, #DeclareError at your disposal. See also the AspectJ 5 quick reference, page 4.
What is the keep option to use for OSGi declarative service to obfuscate with Proguard
Referring to the example below, I need to keep the DS relevant functions without Proguard removes it, because it cant find the reference
#Component
public class RandomApp {
private RandomGenApi randomGenApi;
#Reference
public void setRandomGenService(RandomGenApi randomGenApi) {
this.randomGenApi = randomGenApi;
}
#Activate
void startRandomApp() {
System.out.println("Startig RandomApp...");
}
I could achieve this by defining the OSGi services as the entry points.
Here is the keep options to be defined
#Keep annotations.
-keepattributes *Annotation*
#Keep all Component classes
-keep #org.osgi.service.component.annotations.Component class *
#Kepp all Component classes member functions with OSGi specific annotations
-keepclassmembers #org.osgi.service.component.annotations.Component class * {
#Keep all methods with annotatios Reference.
#org.osgi.service.component.annotations.Reference *;
#Keep all methods with annotatios Activate.
#org.osgi.service.component.annotations.Activate *;
}
java.lang.RuntimeException: A Component requires the 'com.brightcove.player.event.Emits' annotation. If you wish to not listen or emit, create the corresponding annotation with an empty events list.
Has any one else face the same issue??
any help will be appreciable.
It sounds like you do not have the annotation
#Emits(events = {})
before your class declaration. If you show us the relevant fragment it might be obvious to someone what the problem is. A component that emits no events and listens for no events would look like,
/**
* Provides a Component object that is not very useful.
*/
#Emits(events = {})
#ListensFor(events = {})
public class NotVeryUsefulComponent extends AbstractComponent {
}
Please update the proguard with the following lines
-keep public class com.brightcove.player.** { public *;}
-keepclassmembers public class com.brightcove.player.** { public *;}
-keepclasseswithmembers public class com.brightcove.player.** { public *;}
-keep class com.google.android.exoplayer.** { *;}
If you are not using the exoplayer, omit the last line
Your proguard configuration is stripping out the annotations. As an example, please see the proguard-project.txt in our samples repo:
https://github.com/BrightcoveOS/android-player-samples/blob/master/proguard-project.txt
I'm trying to use proguard with my gradle project, however, there is a problem with one of my library classes:
The error:
Warning:com.example.MediaView: can't find referenced field 'android.content.Context mContext' in program class com.example.MediaView
In my proguard.txt there are entries required for android apps:
-keepclasseswithmembernames class * {
public <init>(android.content.Context);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keep class com.example.MediaView
Also the com.example.MediaView comes from a library, and it extends android.widget.FrameLayout
Any idea how to get rid of this warning? (beside the -dontwarn toggle)
Thanks in advance!
Because of the Android 64k max method limit, I'm trying to reduce the number of methods provided by the Parse Android SDK. Parse-1.5.0.jar has some 4,500+ methods. Any suggestions?
Removing the SDK and using the REST APIs is a possibility, but may be somewhat time consuming.
Try using ProGuard and leave out the idea of using REST APIs... Honestly I never heard about such a workaround for such a problem 0_o
Just tell ProGuard to shrink your code, skipping additional features like obuscation if you don't want to slow down the deploy. The proguard-project.txt file will be more or less like this:
-dontoptimize
-dontobfuscate
-allowaccessmodification
-dontpreverify
# The remainder of this file is identical to the non-optimized version
# of the Proguard configuration file (except that the other file has
# flags to turn off optimization).
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native <methods>;
}
# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-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 **.R$* {
public static <fields>;
}
# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**