To avoid misleading to think, re-edit the question.
Firebase Database DataSnapshot getValue(TimeSlot.class) always return null, but getValue toString still show correct attributes values, Did any one have such experience?
Update the question:
This problem happened when I enable proguard
When I add -keep data mode class in proguard file, this issue is fixed.
Add this rule to proguard-rules.pro file
-keepclassmembers class com.example.app.models.** {
*;
}
Change com.example.app.models to your TimeSlot class package
Reference Set up Firebase Realtime Database for Android
Related
I am using Firestore for my Android project and I am using the following code to convert the fetched document to a custom data class
val userData = user.toObject(UserData::class.java)!!
Now this line works perfectly when no code obfuscation is happening, however, with obfuscation, this line does not fail but rather does not copy the user document data to the userData. so I think the issue might be with Firestore and code obfuscation.
Does anyone else have had this issue before?
toObject() method uses reflection to fill up your UserData model from the user document. Now that your UserData class is getting obfuscated, Firestore is not able to map the values in document to the model class.
To fix this, you need to disable code obfuscation for all the data models that you are using in Firebase.
The easiest fix is to add a #Keep annotation to your data class.
#Keep
data class UserData(...)
If you have a lot of such models, you can disable obuscation for an entire file or package by adding more rules to your proguard-rules.pro.
For example, this statement will keep all the classes intact inside model package while code shrinking and obfuscation:
-keep class com.example.app.data.models.** { *; }
Check out the documentation for more such rules.
For the following Proguard rule(take Kotlin Serialization)
-if #kotlinx.serialization.Serializable class **
-keepclassmembers class <1> {
static <1>$Companion Companion;
}
Here what is the meaning of -if in context with the above rule? I tried looking into official proguard documentation but couldn't find easy to any info around that
I wrote those ProGuard rules. :) The pull request discussion about these changes may provide relevant background.
I understand your confusion, the ProGuard rules documentation is quite sparse.
-if class_specification
Specifies classes and class members that must be present to activate the subsequent keep option (-keep,
-keepclassmembers,...). The condition and the subsequent keep option can share wildcards and references to wildcards. For example, you can
keep classes on the condition that classes with related names exist in
your project, with frameworks like Dagger and Butterknife.
As written in the comments of the rules you copied this from:
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-if #kotlinx.serialization.Serializable class **
...
So, -if #kotlinx.serialization.Serializable class ** should be read as: for all classes which have the #Serializable annotation applied (i.e., "serializable classes"). The <1> in -keepmembers subsequently refers to the ** wildcard, i.e., the fully-qualified class name.
I am using default Firebase Analytics implementation described here:
https://firebase.google.com/docs/analytics/get-started?platform=android
But when I check results in Firebase, name of fragments are "g,d,e,b". How can I fix this without hardcoding fragment names?
To keep the fragment names when using ProGuards, you should use -keepnames.
Lets assume you have a fragment with class identifier
com.example.app.fragments.frag1
To exclude that frag, you should add
-keepnames com.example.app.fragments.frag1 {}
To exclude all fragments including those that are in subfolders, use
-keepnames com.example.app.fragments.** {}
-keepnames is short for -keep,allowshrinking. If you use -keep only, you lose all ProGuards optimizations.
If you want properties to maintain their name, use
-keepnames com.example.app.fragments.** {*;}
For more information, you can check this.
Based on answer from #Abkarino, I came up with follwing solution:
-keep class com.packagename.fragments** { *; }
Where "com.packagename.fragments" is path to root of all fragments in project.
I'm currently using an Android library that uses a lot of reflection.
As soon as I enable proguard, and run it... it crashes.
Why? It uses a lot of reflection and the methods are only invoked via reflection, so they are detected by proguard as unused and removed during the shrinking process, so a a NoSuchMethodError is thrown.
Why this happens? That is easy to figure out they are removed during the shrinking process as proguard considers they are unused and therefore removes that pieces of code (all the methods)
So, how can I configure proguard to avoid shrinking or obfuscating an entire package? (the library)
Note: I don't want to use the -dontshrink option, as it's all or nothing and I just want to avoid a specific package.
More info:
The runtime error is the following:
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.my.app.debug, PID: 3771
java.lang.NoSuchMethodError: observeValueForKeyPath [class java.lang.String, class java.lang.Object, class com.my.lib.util.Dictionary, class java.lang.Object]
at com.my.lib.util.Observable$ObservationManager$Observer.<init>(SourceFile:47)
at com.my.lib.util.Observable$ObservationManager$Observer.<init>(SourceFile:26)
at com.my.lib.util.Observable$ObservationManager.addObserver(SourceFile:159)
...
Take note that the problem is one an inner inner class...
My current configuration has something like:
-keep,includedescriptorclasses class com.my.** { *; }
-keepclassmembers class com.my.lib** { *; }
-keep,includedescriptorclasses class com.my.lib.util.Observable$* { *; }
-keep,includedescriptorclasses class com.my.lib.util.Observable$*$* { *; }
But this apparently only avoids obfuscating the methods not removed during the shrinking process... I need to avoid removing methods during shrinking.
According to the documentation -keep should work even when shrinking, while -keepclassmembers only works "if [the] classes are preserved as well".
-keep class com.library.** { *; }
For the sake of people in the future with similar problems, I'll explain what really was happening:
The -keep class my.app.package was really avoiding methods to be removed by shrinking and obfuscated (#F43nd1r's answer made me realize that by really pointing that the docs said that it avoid also shrinking), so the problem was elsewhere
After decompiling the lib's code and passing some time reading it, I found that it received as a parameter an instance of another class (not from that lib) and a string with a method name that it used for reflection. That was the problem, I needed to also avoid obfuscating that class.
I use the option -dontshrink to prevent shrinking.
Source: link
As above.
My ProGuard config is
-keepclassmembers public class myApp.interfaces.**
-keepclasseswithmembernames public class myApp.interfaces.**
-keepattributes Signature
-keepparameternames
Really new to this and no real idea what I'm doing.
What I'm trying to achieve is to make Proguard not change the method and variable names of all Classes inside myApp.interfaces.*. If they want to rearrange some algo stuff to optimise it or whatever, it's fine. As long as the names are not changed.
This must be done because of the Serializable issue between server and client.
Simply use:
-keep class myApp.interfaces.** { *; }
It will not touch the class or its members. If you get errors / warnings, Rebuild the project.