android - GoogleAnalyticsV2 and Proguard

android - GoogleAnalyticsV2 and Proguard

Ibrahim Yaron Author: Ibrahim Yaron Date: 2022-10-05
android - GoogleAnalyticsV2 and Proguard

All you need to know about android - GoogleAnalyticsV2 and Proguard , in addintion to android - Stripped invalid locals information from 1 method - Proguard , java - Android proguard, keep inner class , Error on using proguard with Android Facebook sdk 3.0 , obfuscation - crash using ORMLite on Android with proguard

  1. android - GoogleAnalyticsV2 and Proguard
  2. Question:

    I use Google Analytics V2 library in my project.

    When I export signed application package from Eclipse I get following output in Console:

    Proguard returned with error code 1. See console
      Warning: com.google.analytics.tracking.android.FutureApis: can't find referenced method 'boolean setReadable(boolean,boolean)' in class java.io.File
      Warning: com.google.analytics.tracking.android.FutureApis: can't find referenced method 'boolean setWritable(boolean,boolean)' in class java.io.File
            You should check if you need to specify additional program jars.
      Warning: there were 2 unresolved references to program class members.
               Your input classes appear to be inconsistent.
               You may need to recompile them and try again.
               Alternatively, you may have to specify the option 
               '-dontskipnonpubliclibraryclassmembers'.
      java.io.IOException: Please correct the above warnings first.
        at proguard.Initializer.execute(Initializer.java:321)
        at proguard.ProGuard.initialize(ProGuard.java:211)
        at proguard.ProGuard.execute(ProGuard.java:86)
        at proguard.ProGuard.main(ProGuard.java:492)
    

    Here's my proguard.cfg

    -optimizationpasses 5
    -dontusemixedcaseclassnames
    -dontskipnonpubliclibraryclasses
    -dontpreverify
    -dontwarn android.support.**
    -verbose
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
    
    -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 com.android.vending.licensing.ILicensingService
    -keep public class * extends android.support.v4.app.Fragment
    -keep public class * extends android.app.Fragment
    
    -keepclasseswithmembernames 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 **.R$* {
      public static <fields>;
    }
    
    -keep class com.flurry.** { *; }
    -dontwarn com.flurry.**
    

    If I add -dontwarn com.google.analytics.tracking.android.FutureApis to config then I get

        at proguard.ProGuard.main(ProGuard.java:492)
       Proguard returned with error code 1. See console
             You should check if you need to specify additional program jars.
       Unexpected error while evaluating instruction:
         Class       = [android/support/v4/view/AccessibilityDelegateCompat$AccessibilityDelegateJellyBeanImpl]
         Method      = [newAccessiblityDelegateBridge(Landroid/support/v4/view/AccessibilityDelegateCompat;)Ljava/lang/Object;]
         Instruction = [18] areturn
         Exception   = [java.lang.IllegalArgumentException] (Can't find any super classes of [android/support/v4/view/AccessibilityDelegateCompatIcs$1] (not even immediate super class [android/view/View$AccessibilityDelegate]))
       Unexpected error while performing partial evaluation:
         Class       = [android/support/v4/view/AccessibilityDelegateCompat$AccessibilityDelegateJellyBeanImpl]
         Method      = [newAccessiblityDelegateBridge(Landroid/support/v4/view/AccessibilityDelegateCompat;)Ljava/lang/Object;]
         Exception   = [java.lang.IllegalArgumentException] (Can't find any super classes of [android/support/v4/view/AccessibilityDelegateCompatIcs$1] (not even immediate super class [android/view/View$AccessibilityDelegate]))
       java.lang.IllegalArgumentException: Can't find any super classes of [android/support/v4/view/AccessibilityDelegateCompatIcs$1] (not even immediate super class [android/view/View$AccessibilityDelegate])
        at proguard.evaluation.value.ReferenceValue.generalize(ReferenceValue.java:287)
        at proguard.evaluation.value.IdentifiedReferenceValue.generalize(IdentifiedReferenceValue.java:65)
        at proguard.evaluation.value.ReferenceValue.generalize(ReferenceValue.java:481)
        at proguard.optimize.info.MethodOptimizationInfo.generalizeReturnValue(MethodOptimizationInfo.java:247)
        at proguard.optimize.evaluation.StoringInvocationUnit.generalizeMethodReturnValue(StoringInvocationUnit.java:195)
        at proguard.optimize.evaluation.StoringInvocationUnit.setMethodReturnValue(StoringInvocationUnit.java:126)
        at proguard.evaluation.BasicInvocationUnit.exitMethod(BasicInvocationUnit.java:134)
        at proguard.evaluation.Processor.visitSimpleInstruction(Processor.java:514)
        at proguard.classfile.instruction.SimpleInstruction.accept(SimpleInstruction.java:218)
        at proguard.optimize.evaluation.PartialEvaluator.evaluateSingleInstructionBlock(PartialEvaluator.java:753)
        at proguard.optimize.evaluation.PartialEvaluator.evaluateInstructionBlock(PartialEvaluator.java:587)
        at proguard.optimize.evaluation.PartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(PartialEvaluator.java:560)
        at proguard.optimize.evaluation.PartialEvaluator.visitCodeAttribute0(PartialEvaluator.java:264)
        at proguard.optimize.evaluation.PartialEvaluator.visitCodeAttribute(PartialEvaluator.java:181)
        at proguard.classfile.attribute.CodeAttribute.accept(CodeAttribute.java:101)
        at proguard.classfile.ProgramMethod.attributesAccept(ProgramMethod.java:79)
        at proguard.classfile.attribute.visitor.AllAttributeVisitor.visitProgramMember(AllAttributeVisitor.java:95)
        at proguard.classfile.util.SimplifiedVisitor.visitProgramMethod(SimplifiedVisitor.java:91)
        at proguard.classfile.ProgramMethod.accept(ProgramMethod.java:71)
        at proguard.classfile.ProgramClass.methodsAccept(ProgramClass.java:504)
        at proguard.classfile.visitor.AllMethodVisitor.visitProgramClass(AllMethodVisitor.java:47)
        at proguard.classfile.ProgramClass.accept(ProgramClass.java:346)
        at proguard.classfile.ClassPool.classesAccept(ClassPool.java:116)
        at proguard.optimize.Optimizer.execute(Optimizer.java:372)
        at proguard.ProGuard.optimize(ProGuard.java:306)
        at proguard.ProGuard.execute(ProGuard.java:115)
        at proguard.ProGuard.main(ProGuard.java:492)
    

    Any hints?


    Solution 1:

    I've also faced this problem. As there's no official solution in the GA documentation yet, I made up this set of rules:

    -keep class com.google.android.gms.analytics.**
    -keep class com.google.analytics.tracking.**
    -dontwarn com.google.android.gms.analytics.**
    -dontwarn com.google.analytics.tracking.**
    

    This skips obfuscation as well, but that should not be a problem for an external libary..

    Solution 2:

    The initial warning indicates that FutureApis invokes File#setReadable(boolean,boolean), which doesn't exist on the target platform that you have specified for your build (apparently android-8 or older). ProGuard can ignore it, but it will be a problem if that code is ever executed on those older platforms. The documentation of Google Analytics specifies that android-7 is sufficient, so presumably ignoring it is fine.

    The unexpected error indicates that V4 support class AccessibilityDelegateCompatIcs$1 extends Android class View$AccessibilityDelegate, which doesn't exist on the target platform that you have specified for your build (android-13 or older). In this case, ProGuard really needs that class to properly process the code. With an incomplete class hierarchy, the output would be a mess.

    You can solve both problems by specifying a more recent build target in project.properties when compiling your release version. The missing classes and methods will be present in the corresponding android.jar, so ProGuard will have all the information it needs. Since these classes are just runtime library classes, used for compilation/optimization/obfuscation, they won't affect the output.

    Solution 3:

    I ran into the same problem - I was able to suppress errors when creating ank for release - but when the application it falls, in those places where the classes to which swearing obfuscator. At the moment I have not solved this problem. What is interesting is that in debage mode when running the application through Eclipse - and it works perfectly.

  3. android - Stripped invalid locals information from 1 method - Proguard
  4. Question:

    I'm getting this warning after gradle build. I think it's related to my Proguard rules and Logs. How can I "strip invalid locals information" ?

    I thought wrapping my Log's to a LogUtil class:

    public class LogUtils {
        public static void debug(final String tag, String message) {
            if (BuildConfig.DEBUG) {
                Log.d(tag, message);
            }
        }
    }
    

    and adding this to proguard rules

    -assumenosideeffects class android.util.Log {
        public static *** d(...);
    }
    

    is a good solution but I have a lot of Log.d in my project so it'll be hard.

    same issue with Timber. I think it's too late to switch

    if (BuildConfig.DEBUG) {
      Timber.plant(new Timber.DebugTree());
    }
    


    Solution 1:

    ok I've fixed the issue with:

    -assumenosideeffects class android.util.Log {
        public static boolean isLoggable(java.lang.String, int);
        public static int v(...);
        public static int i(...);
        public static int w(...);
        public static int d(...);
        public static int e(...);
    }
    

  5. java - Android proguard, keep inner class
  6. Question:

    My android program has a class A, which has two static inner class. They are found to be stripped from .dex after applying proguard.

    public class A{
    
      ...
      static class B{
        ...
      }
    
      static class C{
        ...
      }
    }
    

    I have put the following lines in proguard.flags, but seem no luck.

    -keep class com.xxx.A
    -keep class com.xxx.A$*
    

    Any hint?


    Solution 1:

    Try adding InnerClasses to the keep attributes. e.g:

    -keepattributes Exceptions, InnerClasses, ...
    

    Also, try adding a body to the "keep" call with an asterisk, like so:

    -keep class com.xxx.A$* {
        *;
    }
    

    Solution 2:

    Solution 3:

    This did the trick for me

    -keepattributes InnerClasses
     -keep class com.yourpackage.YourClass**
     -keepclassmembers class com.yourpackage.YourClass** {
        *;
     }
    

    It may be a bit overkill with the wildcards but I wanted to make sure I didn't miss anything. The main thing is you need the InnerClasses attributes the keep on the class and the keepclassmembers on the class.

  7. Error on using proguard with Android Facebook sdk 3.0
  8. Question:

    Warning: I removed a lot of "old text" to keep the question more clean. Just check the history if needed.

    I'm using proguard to both shrink and obfuscate an app that uses the facebook sdk 3.0 (I'm using the sdk-version-3.0.2.b tag). I'm not using a JAR file. Instead, I imported the sdk inside my workspace, as taught by the documentation.

    At a certain point in the execution, the app loads a PlacePickerFragment to let the user choose the place where he is. To code this, I follow exactly the Scrumptious tutorial. When I generate the debug apk without using proguard everything works as expected. But when I generate the signed apk using proguard, it crashes when the PlacePickerFragment loads nearby places with the following trace:

    E/AndroidRuntime(27472): FATAL EXCEPTION: main
    E/AndroidRuntime(27472): com.facebook.FacebookGraphObjectException: can't infer generic type of: interface com.facebook.model.GraphObjectList
    E/AndroidRuntime(27472):    at com.facebook.model.GraphObject$Factory.coerceValueToExpectedType(Unknown Source)
    E/AndroidRuntime(27472):    at com.facebook.model.GraphObject$Factory$GraphObjectProxy.proxyGraphObjectGettersAndSetters(Unknown Source)
    E/AndroidRuntime(27472):    at com.facebook.model.GraphObject$Factory$GraphObjectProxy.invoke(Unknown Source)
    E/AndroidRuntime(27472):    at com.facebook.widget.$Proxy2.getData(Native Method)
    E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader.addResults(Unknown Source)
    E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader.requestCompleted(Unknown Source)
    E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader.access$1(Unknown Source)
    E/AndroidRuntime(27472):    at com.facebook.widget.GraphObjectPagingLoader$2.onCompleted(Unknown Source)
    E/AndroidRuntime(27472):    at com.facebook.Request$4.run(Unknown Source)
    E/AndroidRuntime(27472):    at android.os.Handler.handleCallback(Handler.java:587)
    E/AndroidRuntime(27472):    at android.os.Handler.dispatchMessage(Handler.java:92)
    E/AndroidRuntime(27472):    at android.os.Looper.loop(Looper.java:130)
    E/AndroidRuntime(27472):    at android.app.ActivityThread.main(ActivityThread.java:3687)
    E/AndroidRuntime(27472):    at java.lang.reflect.Method.invokeNative(Native Method)
    E/AndroidRuntime(27472):    at java.lang.reflect.Method.invoke(Method.java:507)
    E/AndroidRuntime(27472):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
    E/AndroidRuntime(27472):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
    E/AndroidRuntime(27472):    at dalvik.system.NativeStart.main(Native Method)
    

    Trying to avoid this error, I kept all facebook classes untouched, but didn't work. My current proguard-project.txt file:

    -keep class com.facebook.** {
       *;
    }
    

    My current projet.properties file (excerpt):

    proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
    

    As you can see, my proguard configuration is a "specialization" of this file.

    If I put -dontobfuscate in proguard-project.txt file, it will work. But what I don't understand is that the keep class com.facebook.** should already prevent classes related to facebook to be obfuscated. Which suggests that the problem is not directly related to the facebook classes.

    The excerpt of code that throws com.facebook.FacebookGraphObjectException is:

    static <U> U coerceValueToExpectedType(Object value, Class<U> expectedType, 
            ParameterizedType expectedTypeAsParameterizedType) {
    
        // [...]
    
        } else if (Iterable.class.equals(expectedType) || Collection.class.equals(expectedType)
            || List.class.equals(expectedType) || GraphObjectList.class.equals(expectedType)) {
            if (expectedTypeAsParameterizedType == null) {
                throw new FacebookGraphObjectException("can't infer generic type of: " + expectedType.toString());
            }
        // [...]
    }
    

    Clearly, expectedTypeAsParameterizedType is null in release build. But in both builds (debug and release) expectedType is a com.facebook.model.GraphObjectList interface. Unfortunately, I don't understand almost nothing about Java reflection concepts.

    How can I fix this problem?


    Solution 1:

    This will solve your problem, i hope:

    And the winner is .....

    -keepattributes Signature
    

    From Proguard Homepage:

    The "Signature" attribute is required to be able to access generic types when compiling in JDK 5.0 and higher.

    Solution 2:

    if you want to proguard Facebook, the config below is working for me

    #modify for Facebook
    -keepattributes Signature
    -keep class com.facebook.model.** { *; }
    
    -keepnames class * implements java.io.Serializable
    -keepclassmembers class * implements java.io.Serializable {
        static final long serialVersionUID;
        private static final java.io.ObjectStreamField[] serialPersistentFields;
        !static !transient <fields>;
        private void writeObject(java.io.ObjectOutputStream);
        private void readObject(java.io.ObjectInputStream);
        java.lang.Object writeReplace();
        java.lang.Object readResolve();
    }
    

    Solution 3:

    This may work (untested)

    -keep class com.facebook.** { *; }
    

  9. obfuscation - crash using ORMLite on Android with proguard
  10. Question:

    We're using ORMLite in our Android app. It's working fine, except when we try to do a build with proguard switched on.

    I've read various similar posts, and so far I've got in my proguard-project.txt

    -keep class com.j256.** {
       *;
    }
    

    as suggested in the following discussion http://sourceforge.net/p/proguard/discussion/182456/thread/6765bb69

    and I've got

    -keepclassmembers class * { 
      public <init>(android.content.Context);
      public <init>(android.app.Activity,int);
    }
    

    as suggested in another stackoverflow question Proguard with OrmLite on Android

    But it still not working. I can get it to run if I add

    -dontobfuscate
    

    but that somewhat missing the point of using proguard in the first place.

    When I run I get an

    IllegalStateException: Could not find OpenHelperClass because none of the generic
    parameters of class class <our.package.name>.LaunchActivity extends
    OrmLiteSqliteOpenHelper.  You should use getHelper(Context, Class) instead.
    

    Where

    public class LaunchActivity extends OrmLiteBaseActivity<DatabaseHelper>
    

    and

    public class DatabaseHelper extends OrmLiteSqliteOpenHelper
    

    I've added

    -keep public class * extends com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper
    
    -keep public class <our.package.name>.LaunchActivity
    

    But still no luck. This question seems to have been asked before (Problems with OrmLite and proguard obfuscation) but I'm hoping somebody will know what the solution is!


    Solution 1:

    The error message mentions generic parameters, so ORMLite is probably using reflection to retrieve generic type information. This information is stored in optional Signature attributes (Java erases generic types), which ProGuard removes by default. You can keep them with

    -keepattributes Signature