NoSuchMethodError when using realm.io in a library - java

I transferred the model classes of my Android app inlcuding realm.io functions into a library following the advices described in the realm.io Java docs section Sharing schemas.
I'm facing a NoSuchMethodError when my app (indirectly) calls realm.io methods which are in the the library.
java.lang.NoSuchMethodError: No static method copyOrUpdate(Lio/realm/Realm;Lmy/package/structure/MyModelClass;ZLjava/util/Map;)Lmy/package/structure/MyModelClass; in class Lio/realm/MyModelClassRealmProxy; or its super classes (declaration of 'io.realm.MyModelClassRealmProxy' appears in /data/user/0/my.name.space/files/.jrebel/load-dexes/bundle3/classes.zip)
at io.realm.MyModuleMediator.copyOrUpdate(MyModuleMediator.java:98)
at io.realm.Realm.copyOrUpdate(Realm.java:1164)
at io.realm.Realm.copyToRealmOrUpdate(Realm.java:757)
Here is how my library looks like:
build.gradle (project)
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
classpath 'io.realm:realm-gradle-plugin:1.0.1'
}
}
build.gradle (library module)
apply plugin: 'com.android.library'
apply plugin: 'realm-android'
...
buildTypes {
release {
minifyEnabled false
signingConfig signingConfigs.release
proguardFile getDefaultProguardFile('proguard-rules.pro')
}
}
...
proguard-rules.pro
I used this snippet as a template
-keep class io.realm.annotations.RealmModule
-keep #io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep #io.realm.internal.Keep class * { *; }
-keep my.package.MyModelClass
-dontwarn javax.**
-dontwarn io.realm.**
MyModule.java
package my.package;
import io.realm.annotations.RealmModule;
#RealmModule(library = true, allClasses = true)
public class MyModule { }
MyRealm.java
package my.package;
import ...
public class MyRealm {
private final RealmConfiguration realmConfig;
public MyRealm(Context context) {
realmConfig = new RealmConfiguration.Builder(context)
.name("name.of.my.config")
.modules(new MyModule())
.build();
}
public Realm getRealm() {
return Realm.getInstance(realmConfig);
}
}
MyModelClass.class
package my.package;
import ...
public class MyModelClass extends RealmObject {
public void save(Context context) {
Realm realm = new MyRealm(context).getRealm();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm bgRealm) {
bgRealm.copyToRealmOrUpdate(MyModelClass.this);
}
});
realm.close();
}
}
In my actual app I call something like this which is causing the Exception:
MyActivity.java
// ...
MyModelClass c = new MyModelClass();
c.save(context);
The code above was working well when everything was in the app project.
Am I missing something general?
Is there something more I need to consider regarding the proguard settings of the lib?
May JRebel cause this kind of problem?

I think you might not be using it correctly, I will suggest that you see a full working example like the one they reference are the end of that Sharing Schemas link. The link is to this repository full working example of realm lib and app. I would suggest that you take a look at the Zoo class from the library, the methods are the only thing exposed to the application as you can see in the app's activity here (line 148 and downwards).
I think this was just a confusion on your part, because from what I understood you are calling your library class and using it like it was a Realm instance for that activity context which is not the case. Hope this can steer you in the right path!
Basically you simply create an instance based on you configuration so you don't need to pass a context there.

This happens with JRebel, I would suggest you try with the latest version of it if the issue still persists try not using it.

I received the same error message as the original post.
java.lang.NoSuchMethodError: No static method copyOrUpdate(Lio/realm/Realm;Lmy/package/structure/MyModelClass;ZLjava/util/Map;)Lmy/package/structure/MyModelClass; in class Lio/realm/MyModelClassRealmProxy; or its super classes (declaration of 'io.realm.MyModelClassRealmProxy' appears in /data/user/0/my.name.space/files/.jrebel/load-dexes/bundle3/classes.zip)
at io.realm.MyModuleMediator.copyOrUpdate(MyModuleMediator.java:98)
at io.realm.Realm.copyOrUpdate(Realm.java:1164)
at io.realm.Realm.copyToRealmOrUpdate(Realm.java:757)
But my problem was a different one. I had one Realm module in a library and an additional Realm module in my app. Unfortunately both modules contain an entity with the same class name (but in different packages).
The code generation for realm creates only only one io.realm.<classname>RealmProxy class. Because of that I got the above mentioned exception.
The solution is quite simply: Just rename of the entities.

Related

How to access a dependency of a dependency in Java/Gradle?

I'm trying to access a library that is implemented in a library that I implement. I own both these libraries. I.e.:
Lib1 has a certain class I want to access in the consumer app, say Car.java:
public class Car {
public Int wheelsCount;
}
Lib2 has an api which returns the class Car from lib1:
gradle.build:
...
api 'com.me.lib1:1.0' //From maven central (not currently live)
import com.lib1.Car
interface MyApi {
public Car getCar();
}
Consumer's gradle.build: implementation 'com.me.lib2:1.0'
MyApi api = getMyApi()
api.getCar() // Error
Cannot access class 'com.lib1.Car'. Check your module classpath for missing or conflicting dependencies
Question: Is there a way to do this using gradle?
I am not sure what you’re asking. Here is an example which I think should roughly do what you were talking about?
We have a gradle project with 3 subprojects, car, garage and app. car and garage provide libraries, whereas app is our application. Aside from these directories, the root directory contains only a settings.gradle with this content:
rootProject.name = 'example'
include 'car', 'garage', 'app'
Moving on, we have the car project which provides an interface. It’s build.gradle looks like this:
plugins {
id 'java-library'
}
Other than that, it only contains our interface at src/main/java/car/Car.java:
package car;
public interface Car {
void drive();
}
garage is a consumer for the car project, and provides a way to get new Cars. So we need to declare an api dependency on :car like this:
plugins {
id 'java-library'
}
dependencies {
api project(':car')
}
The Garage class itself looks like this (under src/main/java/garage/Garage.java:
package garage;
import car.Car;
public class Garage {
public Car getCar() {
return () -> { System.out.println("Hello World!"); };
}
}
Finally, we have our application which just needs an implementation dependency on garage to use it and a JavaExec task to run it:
plugins {
id 'java'
}
dependencies {
implementation project(':garage')
}
task run(type: JavaExec) {
main = 'app.Main'
classpath = sourceSets.main.runtimeClasspath
}
The actual implementation again goes to src/main/java/app/Main.java:
package app;
import garage.Garage;
public class Main {
public static void main(String[] args) {
Garage g = new Garage();
g.getCar().drive();
}
}
Now we can run the whole thing with gradle :app:run, which should give us output along these lines:
> Task :app:run
Hello World!
BUILD SUCCESSFUL in 506ms
6 actionable tasks: 1 executed, 5 up-to-date
<-------------> 0% WAITING
> IDLE
So as you can see, there’s nothing special you need to do beyond the things you’ve already stated. This is assuming you’re using classpaths. If you’re using the Java 9+ module system there are some additional steps, but this would be beyond the scope of this question I think.

Kotlin's JvmDefault - still need to declare the method ?

I am building my Spring Boot 1.5 + Kotlin 1.2.41 project into a jar. One of the interfaces in the jar has the #JvmDefault and it compiles fine with the flag (if I remove the flag, it fails).
Now, I am trying to use this interface in another java project, in which I define the Kotlin project as a dependency.
In one implementing class, I don't override the default method. Intellij seems to be OK with it, as it doesn't complain. However, when I compile with Maven, I get :
[ERROR] attempting to assign weaker access privileges; was public
If I implement the method (with some dummy implementation), then it compiles... but it defeats the purpose of the default interface.
Any idea what could be wrong ?
When opening the Kotlin interface code from the java project, here's the decompiled code I see :
public interface CrawlerOutput {
#kotlin.jvm.JvmDefault public open fun finalize(): kotlin.Unit { /* compiled code */ }
public abstract fun output(analyzedRepository: com.myCompany.Repository): kotlin.Unit
}
My java code implementing the interface :
public class CsvOutput implements CrawlerOutput {
#Override
public void output(Repository repository) throws IOException {
log.info("own output is receiving some data !");
}
/**
* IF I REMOVE BELOW METHOD, MAVEN CAN'T COMPILE IT ANYMORE,
* COMPLAINING OF WEAKER ACCESS PRIVILEGE
*/
#Override
public void finalize(){
}
}
Am I missing something ?
Thanks
Vincent
Your method name conflicts with java.lang.Object.finalize(). The error should be fixed if you choose a different method name.
Android Studio and JVM always update its versions. As a result of that some of you may experience this error message.
Inheritance from an interface with '#JvmDefault' members is only allowed with -Xjvm-default option
Don't worry . The solution is very simple. Just add below code part to the end of android block of your app level build.gradle file and sync.
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
freeCompilerArgs += [
"-Xjvm-default=all",
]
}
}

Android room persistent: AppDatabase_Impl does not exist

My app database class
#Database(entities = {Detail.class}, version = Constant.DATABASE_VERSION)
public abstract class AppDatabase extends RoomDatabase {
private static AppDatabase INSTANCE;
public abstract FavoritesDao favoritesDao();
public static AppDatabase getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, Constant.DATABASE).allowMainThreadQueries().build();
//Room.inMemoryDatabaseBuilder(context.getApplicationContext(),AppDatabase.class).allowMainThreadQueries().build();
}
return INSTANCE;
}
public static void destroyInstance() {
INSTANCE = null;
}
}
Gradle lib:
compile "android.arch.persistence.room:runtime:+"
annotationProcessor "android.arch.persistence.room:compiler:+"
And when i ask for instance it will give this error, AppDatabase_Impl does not exist
in my application class
public class APp extends Application {
private boolean appRunning = false;
#Override
public void onCreate() {
super.onCreate();
AppDatabase.getAppDatabase(this); //--AppDatabase_Impl does not exist
}
}
For those working with Kotlin, try changing annotationProcessor to kapt in the apps build.gradle
for example:
// Extensions = ViewModel + LiveData
implementation "android.arch.lifecycle:extensions:1.1.0"
kapt "android.arch.lifecycle:compiler:1.1.0"
// Room
implementation "android.arch.persistence.room:runtime:1.0.0"
kapt "android.arch.persistence.room:compiler:1.0.0"
also remember to add this plugin
apply plugin: 'kotlin-kapt'
to the top of the app level build.gradle file and do a clean and rebuild (according to https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#6)
In Android Studio, if you get errors when you paste code or during the build process, select Build >Clean Project. Then select Build > Rebuild Project, and then build again.
UPDATE
If you have migrated to androidx
def room_version = "2.3.0" // check latest version from docs
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
UPDATE 2 (since July 2021)
def room_version = "2.3.0" // check latest version from docs
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
Just use
apply plugin: 'kotlin-kapt'
in app build.gradle
And keep both in dependencies
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
kapt "android.arch.persistence.room:compiler:$rootProject.roomVersion"
EDIT
In newer version don't need to add both dependencies at a time
Just use, hope it will work.
kapt 'android.arch.persistence.room:compiler:1.1.1'
I had this error when I missed
#Database(entity="{<model.class>})
Ensure that the entity model specified in the annotation above refers to the particular model class and also ensure that the necessary annotation:
#Entity(tableName = "<table_name>" ...)
is properly defined and you'd be good
if you are using kotlin classes to implement database then
use
apply plugin: 'kotlin-kapt'
and
kapt "android.arch.persistence.room:compiler:1.1.1"
in your gradle file, it will work.
For Kotlin Developers
Use this:
implementation "android.arch.persistence.room:runtime:1.0.0"
kapt "android.arch.persistence.room:compiler:1.0.0"
And add apply plugin: 'kotlin-kapt' to the top of the app level build.gradle.
For Java Developers
implementation "android.arch.persistence.room:runtime:1.0.0"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
It is not just about updating your dependencies. Make sure all your Room dependencies have the same version.
implementation 'android.arch.persistence.room:rxjava2:1.1.0-alpha2'
implementation 'android.arch.persistence.room:runtime:1.1.0-alpha2'
annotationProcessor "android.arch.persistence.room:compiler:1.1.0-alpha2"
In the sample snippet above, all my Room dependencies have the same version 1.1.0-alpha2
Agreed with the above answers
The solution is as below. Change annotationProcessor to kapt as below
// annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
I meet with the problem, because I forget #Dao annotation
#Dao
public interface SearchHistoryDao {
#Query("SELECT * FROM search_history")
List<SearchHistory> getAll();
#Insert
void insertAll(SearchHistory... histories);
#Delete()
void delete(SearchHistory history);
}
Room Official tutorial
make sure to add correct dependency for room in build.gradle
ext {
roomVersion = '2.1.0-alpha06'
}
// Room components
implementation "androidx.room:room-runtime:$rootProject.roomVersion"
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
kapt "androidx.room:room-compiler:$rootProject.roomVersion"
androidTestImplementation "androidx.room:room-testing:$rootProject.roomVersion"
And below line at the top-
apply plugin: 'kotlin-kapt'
I met this problem because I have forgotten the apt dependences
implementation "android.arch.lifecycle:extensions:$archLifecycleVersion"
implementation "android.arch.persistence.room:runtime:$archRoomVersion"
annotationProcessor "android.arch.lifecycle:compiler:$archLifecycleVersion"
annotationProcessor "android.arch.persistence.room:compiler:$archRoomVersion"
after added the annotationProcessor, and rebuild it, the problem solved.
If you are using kotlin, add kotlin annotation processor plugin to app level build.gradle
plugins {
id "org.jetbrains.kotlin.kapt"
}
Also remove annotationProcessor and replace it with kapt
Instead of
dependencies {
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
}
Use
dependencies {
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
}
The annotationProcessor only works in java environment. The kapt takes care of both java and kotlin. If something wrong with your implementation, those plugins will show them at the compile time.
Had the same problem. Implemented the few classes and interface as officially told in a new example project created by Android Studio:
https://developer.android.com/training/data-storage/room/
All mentioned solutions above did not help, the necessary _Impl files according to my database class were not generated by Room. Finally executing gradle clean build in terminal gave me the hint that lead to the solution:
"warning: Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide room.schemaLocation annotation processor argument OR set exportSchema to false."
I added the parameter exportSchema = false in the database class
#Database(entities = arrayOf(User::class), version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
}
And then it worked, found these two generated files in the app module under generatedJava:
AppDatabase_Impl
UserDao_Impl
I don't understand this behaviour as the parameter is said to be optional, see
https://stackoverflow.com/a/44645943/3258117
The question is pretty old, but I've stumbled on this today and none of the provided answers helped me. Finally I managed to resolve it by noticing that google documentation actually is still adopted to Java and not Kotlin by default, actually they have added a comment which I've ignored
For Kotlin use kapt instead of annotationProcessor
So, instead of
annotationProcessor "androidx.room:room-compiler:$room_version"
If you are developing with Kotlin, you should use:
kapt "androidx.room:room-compiler:$room_version"
In my kotlin app, I just added the following line at the top of my build.gradle file :
apply plugin: 'kotlin-kapt'
And the following line in the dependencies section:
kapt "androidx.room:room-compiler:2.2.5"
I hope it fixes your issue.
In my case, I was testing the connectivity for room database and I have put the testing class inside the directory which I have created inside the AndroidTest folder. I have moved it out of the custom directory, then it worked pretty well.
The same phenomenon occurred to me.
following
implementation "android.arch.persistence.room:runtime:1.1.1"
Adding causes another build error but tracks the cause from the log.
In my case, there was an error in the SQL implementation.
After fixing, the build was successful.
So you may want to check the implementation of the entire room library instead of looking at the crashed locals.
Use the following gradle link:
compile 'android.arch.persistence.room:runtime:1.0.0-alpha9'
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0-alpha9'
You need to create a different singleton class and get the AppDatabase from there like this:
RoomDB.java
public class RoomDB {
private static RoomDB INSTANCE;
public static AppDatabase getInstance(Context context) {
if (INSTANCE == null) {
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, Constant.DATABASE).allowMainThreadQueries().build();
//Room.inMemoryDatabaseBuilder(context.getApplicationContext(),AppDatabase.class).allowMainThreadQueries().build();
}
return INSTANCE;
}
public static void destroyInstance() {
INSTANCE = null;
}
App.java
public class App extends Application {
private boolean appRunning = false;
#Override
public void onCreate() {
super.onCreate();
RoomDB.getInstance(this); //This will provide AppDatabase Instance
}
The issue is more around the correct library that is not included in the gradle build. I had a similar issue and added the missing
testImplementation "android.arch.persistence.room:testing:$room_version
Changing the dependencies in my gradle file did'nt help me in fixing the error.I had missed this Database annotation in class where Room database was initialized which was causing this issue.
#Database(entities = [UserModel::class], version = 1)
Ensure that the entity model specified in the annotation above refers to the particular model class
For Kotlin Developers
if you checked Dao and Entity and also used Kapt and there is no problem, I guess there is a problem with your kotlin version if you are using kotlin 1.4 and above.
update Room to last version from this link.
2.3.0-alpha03 solved my problem.
For me, the Android Studio automatically updated dependencies as soon as you include any of the Room database related imports. But as per https://developer.android.com/jetpack/androidx/releases/room#declaring_dependencies you need to update few. Here is how my code-base looks like:
AppDatabase.kt
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
#Database(entities = arrayOf(MyEntity::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun myDAO(): MyDAO
companion object {
#Volatile private var instance: AppDatabase? = null
private val LOCK = Any()
operator fun invoke(context: Context)= instance ?: synchronized(LOCK){
instance ?: buildDatabase(context).also { instance = it}
}
private fun buildDatabase(context: Context) = Room.databaseBuilder(context,
AppDatabase::class.java, "db-name.db")
.build()
}
}
Update the build.gradle as specified in one of the answers:
apply plugin: 'kotlin-kapt' // this goes with other declared plugin at top
dependencies { // add/update the following in dependencies section
implementation 'androidx.room:room-runtime:2.2.3'
// annotationProcessor 'androidx.room:room-compiler:2.2.3' // remove this and use the following
kapt "androidx.room:room-compiler:2.2.3"
}
Sync the gradle and you should be good to go.
In addition to missing
annotationProcessor "android.arch.persistence.room:compiler:x.x.x"
I had also missed adding the below annotation in my class
#Entity(tableName = "mytablename")
Nothing works from above answers and I noticed that the issue persists for me when I'm using room version2.3.0 or 2.4.2. However, 2.5.0-alpha01 version works well when I applied it.
build.gradle:app
def roomVersion = '2.5.0-alpha01'
implementation "androidx.room:room-ktx:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
testImplementation "android.arch.persistence.room:testing:$roomVersion"
In my case just by changing annotationProcessor to kapt on my room-compiler dependency, did the work.
As of Jan 2023 - I faced a similar issue after refactoring my code to use ServiceLocator class.
I resolved it by going on a spree of changing room versions. It worked with 2.5.0-alpha02
version_room = "2.5.0-alpha02" <-- build.gradle (project)
//Room
implementation "androidx.room:room-runtime:$version_room"
kapt "androidx.room:room-compiler:$version_room"
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$version_room"
implementation("androidx.room:room-guava:$version_room")
I am running the following on Android Eel 2020.1.1:
version_kotlin = "1.7.21"
version_android_gradle_plugin = "4.0.1"
Reading the example here:
Room Example
I fixed this error just using the correct (I guess it is) annotationProcessorFile, as follows:
annotationProcessor "android.arch.persistence.room:compiler:<latest_version>"
Also, I upgraded to 2.2.0 either in Room Version as in Lifecycle version.
Once synchronized the graddle, I could start working with Room.
So, Good luck! And let the code be with you!
Not in the case of OP, but this also happens when you mistakenly use implementation instead of annotationProcessor like this:
implementation "android.arch.persistence.room:compiler:x.x.x"
Instead of this:
annotationProcessor "android.arch.persistence.room:compiler:x.x.x"
Just in case anyone out there should make the same mistake as I did, don't call your database class "Database" or you'll get the same error.
check this annotation above class
#Database(entities = arrayOf(Schedule::class), version = 1)
abstract class AppDatabase : RoomDatabase() {
// ....
}

extending abstract class in realm giving error

i have a class A
public abstract class A extends RealmObject{
}
public class B extends A {
}
error: A RealmClass annotated object must be derived from RealmObject
As far as I know, subclassing a subclass of RealmObject isn´t supported by Realm in Android for the moment, but there's already a feature in their roadmap in order to improve this point ( https://github.com/realm/realm-java/issues/761 ).
At least, you can always duplicate fields between model classes, to simulate subclassing (not very elegant though).
Inheritance is not supported (answer based on v1.1.0), only interface implementation is.
To me I solved this issue by removing the dependency.
compile 'io.realm:realm-android:1.1.0'
and put the class path as:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:1.1.0"
}
}
and also put plugin as:
apply plugin: 'realm-android'
Further you can visit to Realm

How to use dagger in a android library project

I'm currently trying to add Dagger to my android projects. For the apps projects its easy and clear to me, how to build the ObjectGraph. But I dont quite know whats the best way to do this in my android library projects.
Should I keep building the ObjectGraph in the Application class of the apps and pass the OG over to a LibraryModule - plussing the OG of library to the Apps OG? Or should i build the whole ObjectGraph in the library?
What if I need to inject a class in the library by ObjectGraph.inject(this)? In my Apps projects I can get the OG from the Application class. But how to handle this in the library? Should I add a #Provides method for the ObjectGraph?
Big thanks for your help.
Edit:
In short: How can I call ObjectGraph.inject(this) in my library project where I don't have access to the OG because it is being builded in the Application Class?
In case someone using Dagger 2 gets here, this is the way I've done in my App:
In the library module I've created the following Module and Component:
#Module
public class ModuleUtil {
#Provides
public RestTemplate provideRestTemplate() {
return new RestTemplate();
}
}
#Singleton
#Component(
modules = {
ModuleUtil.class
})
public interface MainComponent {
void inject(Postman postman);
}
And then I've created the Singleton below in order to manage the injections:
public class DaggerWrapper {
private static MainComponent mComponent;
public static MainComponent getComponent() {
if (mComponent == null) {
initComponent();
}
return mComponent;
}
private static void initComponent () {
mComponent = DaggerMainComponent
.builder()
.utilModule(new ModuleUtil())
.build();
}
}
When some class from the library module needs to inject its members, I simply call DaggerWrapper.getComponent().inject(this); and that't it.
I'm doing this way:
#Module classes belong to the main project and they provide implementations which you are injecting to library elements, so there are no #Module classes in the library projects
Library elements which are expecting dependency must have access to ObjectGraph and call .inject() on themselves, but main project should give ObjectGraph instance to the library with provided #Module dependency
How to get ObjectGraph from main project into the library? You could have interface like this:
interface Injector {
void inject(Object object);
public ObjectGraph getObjectGraph();
}
Context objects like Activity or Application class implements this interface (holders of ObjectGraph objects).
If you have example of Activity in the library module which needs something to inject from the main project this would look like this:
class LibraryActivity extends Activity {
#Inject ActivationModule instance;
void onCreate(... ) {
Injector injector = (Injector)getApplicationContext();
injector.inject(this)
}
}
ActivationModule is the class/interface in the library project.
Main project has application class which implements Injector interface and creates ObjectGraph with provided dependecy for ActivationModule in the library project.
class MyApplicationInTheMainProject extends Application implements Injector {
ObjectGraph graph;
#Override
public void onCreate() {
super.onCreate();
graph = ObjectGraph.create(new ActivationModuleImpl(this));
}
#Override public void inject(Object object) {
graph.inject(object);
}
#Override public ObjectGraph getObjectGraph() {
return graph;
}
}
#Module(injects = {
LibraryActivity.class
}, library = true)
class ActivationModuleImpl implements ActivationModule {
....
}
if you are giving this library to people and they dont know nothing about your scenario so you must write it in a way that your Dagger works perfectly without any help from user. (the easier to work with the better practice)
i just wrote some library for you to show how to do it. i wrote the library in a way that you can even run it standalone and see the result in the messages tab. user of your library doesnt need to know nothing about dagger and does nothing he just uses the library and dagger will be configured:
https://github.com/amirziaratii/libraryUsingDagger.git
if this library is something you use it yourself and for your own project, the best practice is do it like in this project of my friend:
https://github.com/mmirhoseini/trakt.tv
all your questions are answered in these two projects. ask any question and ill answer in comment.

Categories