Realm Kotlin not in schema - android

I try to use Realm.io to store data in android i have RealmClass
#RealmClass
public open class Alarm : RealmObject() {
#Required
public open var hourOfDay: Int? = null
#Required
public open var minute: Int? = null
#Required
public open var days: BooleanArray? = null
public open var name: String? = null
}
and in onCreate i try to add some test data
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mRealm = Realm.getInstance(activity);
mRealm.beginTransaction()
var a = mRealm.createObject(Alarm::class.java)
a.hourOfDay = 12
a.minute = 1;
a.days = booleanArrayOf(true, true, true, true, true, false, false);
a.name = "Test${System.currentTimeMillis()}"
mRealm.commitTransaction()
}
but i get exception.
> java.lang.IllegalArgumentException: Alarm is not part of the schema for this Realm
at var a = mRealm.createObject(Alarm::class.java)
i have set realm rules
-keep class io.realm.annotations.RealmModule
-keep #io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep #io.realm.internal.Keep class *
-dontwarn javax.**
-dontwarn io.realm.**
in > proguard-rules.pro
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
realmFlavor {
proguardFile 'proguard-rules.pro'
}
}
but this did not bring solution
CONCLUSION
so far its looks like we have to write models in Java, Realm and any ORM libraries Kotlin examples posted on GitHub have models written in pure Java

"java.lang.NoClassDefFoundError: io/realm/annotations/RealmClass"
If you run into the error above, You'll most likely have to add something like this to your build.gradle. The bottom two lines for kapt are key.
//Realm
compile 'io.realm:realm-android:0.87.1'
kapt "io.realm:realm-annotations:0.87.1"
kapt "io.realm:realm-annotations-processor:0.87.1"
Per the comment at the bottom of this issue: https://github.com/realm/realm-java/issues/509

For Kotlin to work with Realm's annotation processor you need the following setup in your build.gradle
compile "io.realm:realm-android-library:0.86.0#aar"
compile "io.realm:realm-annotations:0.86.0"
kapt "io.realm:realm-annotations-processor:0.86.0"

For me, I added #RealmClass to all models and fixed despite that it is not required.
I think it forces to run Realm processor correctly by using annotator.
To check RealmObject models are processed or not, your Gradle console output (you can open it in Android Studio at the right bottom toggle panel) has to show Red-colored model processing log as below.
:app:compileDebugJavaWithJavac
Full recompilation is required because at least one of the classes of removed jar 'kotlin-stdlib-1.0.0.jar' requires it. Analysis took 1.572 secs.
Note: Processing class ModelSomething
Note: Processing class ModelAnotherThing
Note: Creating DefaultRealmModule
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:app:transformClassesWithRealmTransformerForDebug
:app:transformClassesWithInstantRunVerifierForDebug
:app:transformClassesWithJavaResourcesVerifierForDebug
The Note: lines are red colors and you can see Processing class ModelSomething message.
All of your model should be listed as this message.
This issue is filed as a suspicious bug: https://github.com/realm/realm-java/issues/2822

Related

Kotlin 1.6.0 (There are no problems in 1.5.21) + Proguard + Gson (Registering an InstanceCreator with Gson...)

I have enabled Proguard and configured the rules
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
For GSON I used these rules
added my models to exceptions (-keep class my.package.model.** { *; })
Also used other rules for various libraries
I have this error -> Registering an InstanceCreator with Gson for this type may fix this problem.
the error occurred when switching to kotlin 1.6.0 and 1.6.10.
There is no error on version Kotlin 1.5.21!
Error (I have a bug only on Kotlin 1.6.0/1.6.10. There is no error on kotlin 1.5.21) --->
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.project.main, PID: 2943
java.lang.RuntimeException: Unable to invoke no-args constructor for class com.project.main.domain.entity.MyEntityClass. Registering an InstanceCreator with Gson for this type may fix this problem.
at com.google.gson.internal.c$e.a(SourceFile:228)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(SourceFile:212)
at com.google.gson.Gson.h(SourceFile:963)
at com.google.gson.Gson.j(SourceFile:928)
at com.google.gson.Gson.l(SourceFile:877)
at com.project.main.data.cache.converter.MyEntityClassConverter.toMyEntityClass(SourceFile:14)
at com.project.main.data.cache.dao.MyProjectDao_Impl$21.call(SourceFile:947)
at com.project.main.data.cache.dao.MyProjectDao_Impl$21.call(SourceFile:889)
at k1.c$a$a$a$a.invokeSuspend(SourceFile:128)
at uh.a.resumeWith(SourceFile:33)
at uk.z0.run(SourceFile:106)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.lang.UnsupportedOperationException: Abstract class can't be instantiated! Class name: com.project.main.domain.entity.MyEntityClass
at com.google.gson.internal.l.a(SourceFile:120)
at com.google.gson.internal.l$a.c(SourceFile:49)
at com.google.gson.internal.c$e.a(SourceFile:225)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(SourceFile:212) 
at com.google.gson.Gson.h(SourceFile:963) 
at com.google.gson.Gson.j(SourceFile:928) 
at com.google.gson.Gson.l(SourceFile:877) 
at com.project.main.data.cache.converter.MyEntityClassConverter.toMyEntityClass(SourceFile:14) 
at com.project.main.data.cache.dao.MyProjectDao_Impl$21.call(SourceFile:947) 
at com.project.main.data.cache.dao.MyProjectDao_Impl$21.call(SourceFile:889) 
at k1.c$a$a$a$a.invokeSuspend(SourceFile:128) 
at uh.a.resumeWith(SourceFile:33) 
at uk.z0.run(SourceFile:106) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
at java.lang.Thread.run(Thread.java:923) 
I have rules for this error.
-keep class com.project.main.domain.entity.MyEntityClass { ; }
but I'm adding the whole package
-keep class com.project.main.domain.entity.* { *; }
I also have all the other rules for GSON -> rules
#TypeConverter
fun toMyEntityClass(value: String): MyEntityClass =
gson.fromJson(value, object : TypeToken<MyEntityClass>() {}.type) //Error
I also tried to prescribe just one rule. The rule helps to run the project on 1.5.21 and works. But it doesn't work on 1.6.0 - 1.6.10. I don't want to create an Instance Creator. I have too many models and I will waste a lot of time.
-keep class ** { *; }
For any classes that interact with GSON you have to keep as follow :
-keep class "MODEL CLASSES"
for your issue you can do like :
-keep class com.project.main.domain.entity.** { *; }
It will keep all classes under the entity package.
The problem was solved by itself, after updating the libraries
gson 2.9.0
and kotlin 2.6.21
I didn't do anything, just updated to these versions
I haven't checked 1.6.0 and 1.6.10 works in tandem with gson 2.9.0 but gson didn't work with the previous release version
As a result, I upgraded Kotlin from 1.5.21 -> 1.6.21

Serializer for data class Kotlin not found at build release

I want convert my json string response from API to object:
val obj = Json.decodeFromString<MyModel>(jsonResponseString)
My data class:
#Serializable
data class MyModel(
#SerializedName("field") val field: String
)
It look like very simple and it works on debug mode!
But when a compiled the AppBundle, builded in release mode and download app from Play Store internal testing, I got the following error :
Serializer for class '...' is not found. Mark the class as #serializable or provide the
serializer explicitly.
kotlinx.serialization.internal.Platform_commonKt.serializerNotRegistered
You should add this to your proguard.pro if you're using minifyEnabled true
-keepattributes *Annotation*, InnerClasses
-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations
# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer
-keepclassmembers class kotlinx.serialization.json.** {
*** Companion;
}
-keepclasseswithmembers class kotlinx.serialization.json.** {
kotlinx.serialization.KSerializer serializer(...);
}
# Change here com.yourcompany.yourpackage
-keep,includedescriptorclasses class com.yourcompany.yourpackage.**$$serializer { *; } # <-- change package name to your app's
-keepclassmembers class com.yourcompany.yourpackage.** { # <-- change package name to your app's
*** Companion;
}
-keepclasseswithmembers class com.yourcompany.yourpackage.** { # <-- change package name to your app's
kotlinx.serialization.KSerializer serializer(...);
}
Make sure you replace the placeholder package name with your app package name
Source
I found the next solution:
First step, I added #Keep anotation. Keep anotation denotes that the annotated element should not be removed when the code is minified at build time:
#Keep
#Serializable
data class MyModel(
#SerializedName("field") val field: String
)
Second step, I converted my json to object making a static reference to the serializer:
val objError = Json {ignoreUnknownKeys = true}.decodeFromString(MyModel.serializer(), jsonResponseString)
Dont forget import and implement last version of:
'org.jetbrains.kotlin.plugin.serialization'
And it worked and it save my day!!
I have fixed that with these changes in the Gradle files, in the build project gradle add this line to dependencies:
classpath "org.jetbrains.kotlin:kotlin-serialization:1.5.21"
Add also these to the build app gradle:
plugins {
...
id 'kotlinx-serialization'
}
dependencies {
...
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2'
}
Please note version numbers might be different.
Starting from 1.5.0-RC proguard rules are shipped with library.
Bundled Proguard rules
The kotlinx-serialization-core-jvm JAR file now includes consumer Proguard >rules,
so manual Proguard configuration is no longer necessary for most of the setups.

Cannot serialize Kotlin type with Moshi AND R8

i have this strange problem. When using minify/obfuscation with R8 i have the following error
java.lang.IllegalArgumentException: Cannot serialize Kotlin type <omitted>auth.model.ErrorResponse. Reflective serialization of Kotlin classes without using kotlin-reflect has undefined and unexpected behavior. Please use KotlinJsonAdapter from the moshi-kotlin artifact or use code gen from the moshi-kotlin-codegen artifact.
With no minify/obfuscation everything it's ok. I'm using
val moshi = Moshi.Builder()
.add(BigDecimalAdapter)
.add(KotlinJsonAdapterFactory())
.build()
as readme from moshi, stated. Also in gradle i'm using
implementation("com.squareup.moshi:moshi-kotlin:1.9.3")
and added rules
-keep class com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
-keep class <omitted>auth.model.ErrorResponse
but still have the same exception. what am i missing ?
Thanks
updated
here's my BigDecimalAdapter
object BigDecimalAdapter {
#FromJson
fun fromJson(string: String) = BigDecimal(string)
#ToJson
fun toJson(value: BigDecimal) = value.toString()
}
try adding to your proguard:
-keepclassmembers class * {
#com.squareup.moshi.FromJson <methods>;
#com.squareup.moshi.ToJson <methods>;
}

Android uses the "default" method in the interface to generate apk

Now there is a third-party dependency package: page
It has an interface that contains the default method :
public interface TempInterface {
default String getStr() {
return "test";
}
}
And i create a module : app
There is a class in "app" that uses the above interface
public class AA implements TempInterface {
}
"build.gradle" file in "app" :
dependencies {
compileOnly project(':page')
}
In the generated APK, the following classes appear:
what about *$-CC ?????
And when I decompiled the DEX file, I found that there was no such class at all:
So I'm confused about what this "* $- CC" is ??
Who can help me
the build.gradle :
$-CC file is generated by d8 when the class file compile to dex file.
More details on https://mouaad.aallam.com/java-8-interface-methods-for-android/
why you apply proguard from your app/build.gradle, it obfuscates your class and methods name so that reverse engineering is tough. that is what happens here

Module with Main dispatcher is missing

I'm trying to make a background call to my local database and update the UI with the results using coroutines.
Here is my relevant code:
import kotlinx.coroutines.experimental.*
import kotlinx.coroutines.experimental.Dispatchers.IO
import kotlinx.coroutines.experimental.Dispatchers.Main
import kotlin.coroutines.experimental.CoroutineContext
import kotlin.coroutines.experimental.suspendCoroutine
class WarehousesViewModel(private val simRepository: SimRepository)
: BaseReactViewModel<WarehousesViewData>(), CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Main
override val initialViewData = WarehousesViewData(emptyList())
override fun onActiveView() {
launch {
val warehouses = async(IO) { loadWarehouses() }.await()
updateViewData(viewData.value.copy(items = warehouses))
}
}
private suspend fun loadWarehouses(): List<Warehouse> =
suspendCoroutine {continuation ->
simRepository.getWarehouses(object : SimDataSource.LoadWarehousesCallback {
override fun onWarehousesLoaded(warehouses: List<Warehouse>) {
Timber.d("Loaded warehouses")
continuation.resume(warehouses)
}
override fun onDataNotAvailable() {
Timber.d("No available data")
continuation.resume(emptyList())
}
})
}
}
My problem is that I get a runtime exception:
java.lang.IllegalStateException: Module with Main dispatcher is missing. Add dependency with required Main dispatcher, e.g. 'kotlinx-coroutines-android'
I already added these to my gradle:
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.30.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.26.0'
I'm a bit new to this, can someone help me?
Using just the kotlinx-coroutines-android version solves the problem.
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.30.1'
You may be missing some Proguard rules.
I had the same problem in release build and solved it by adding the following rules:
-keepnames class kotlinx.coroutines.internal.MainDispatcherFactory {}
-keepnames class kotlinx.coroutines.CoroutineExceptionHandler {}
-keepclassmembernames class kotlinx.** {
volatile <fields>;
}
from https://github.com/Kotlin/kotlinx.coroutines/blob/master/ui/kotlinx-coroutines-android/example-app/app/proguard-rules.pro
Use both Core and Android dependency
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.6'
If you're facing this problem with coroutines version 1.3.8, add this rule in your proguard-rules.pro:
-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
./gradlew assembleDebug --rerun-tasks
fixes it if the above answers don't work for you (because you already had the required dependencies and you are using R8 which does not need the proguard rules).
"core" is transitive dependency of "android" version in current version of "kotlinx-coroutines" so only use "android"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'
Just an additional hint if anyone tries the solutions from above and they didn't work.
For me, --no-build-cache didn't help. Instead, a rule in proguard-rules.txt did the job:
-keep class kotlinx.coroutines.android.** {*;}
My setup is kotlinx-coroutines-android:1.3.9, no kotlinx-coroutines-core (I removed it as it turned out to be unnecessary), Kotlin 1.3.72, and Gradle 3.2.1.
I have fixed by doing both version same
'kotlinx-coroutines-android' and ensure it has the same version as 'kotlinx-coroutines-core'
// Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'//same as coroutines-android
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5"//same as coroutines-core
Well, in my case keeping minifyEnabled true was causing the issue. but to achieve the obfuscation it was mandatory for me to keep the minifyEnabled true on the release build. So I did the following changes.
//keep only
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.8'
in your proguard-rules.pro add
-keep class kotlinx.coroutines.android.AndroidDispatcherFactory {*;}
I also required to add the model classes used for API call via retrofit in the proguard-rules.pro
-keep class com.example.test.login.data.model.** { *; }
-keepclassmembers class com.example.test.login.data.model.** { *; }

Categories

Resources