web-dev-qa-db-ja.com

Dagger 2を使用してMyFirebaseMessagingServiceにデータベースを提供し、fcmメッセージをローカルにandroid

データベースインスタンスをMyFirebaseMessagingServiceを拡張するFirebaseMessagingServiceクラスに渡して、dataペイロードをローカルに保存できるようにするにはどうすればよいですか?

注:アプリでdagger 2を既に設定していますが、完全に機能しています。

以下はMyFirebaseMessagingServiceクラスです。

class MyFirebaseMessagingService @Inject constructor(exampleOneDao: ExampleOneDao?) : FirebaseMessagingService() {

    override fun onMessageReceived(remoteMessage: RemoteMessage?) {
    //need db instance to store data payload locally (Room)
    }
}

以下は、Dagger2のAppModuleクラスです。

@Module(includes = arrayOf(ViewModelModule::class))
class AppModule() {

    // --- DATABASE INJECTION ---
    @Provides
    @Singleton
    internal fun provideDatabase(application: Application): MyDatabase {
        return Room.databaseBuilder(application,
               MyDatabase::class.Java, "MyDatabase.db")
              .build()
    }

    @Provides
    @Singleton
    internal fun provideExampleOneDao(database: MyDatabase): ExampleOneDao {
        return database.exampleOneDao()
    }

    @Provides
    @Singleton
    internal fun provideMyFirebaseMessagingService(exampleOneDao: 
        ExampleOneDao): MyFirebaseMessagingService {
           return MyFirebaseMessagingService(exampleOneDao)
    }
}

データベースとdaoをMyFirebaseMessagingServiceクラスに提供することは可能ですか?

上記のメソッドを使用してexampleOneDaoMyFirebaseMessagingServiceクラスに提供しようとしましたが、次のExceptionがスローされます。

MyFirebaseMessagingService: Java.lang.InstantiationException: Java.lang.Class<com.example.user.app.firebase.messaging.MyFirebaseMessagingService> has no zero argument constructor

ありがとうございました。

10
Sharoon Amjid

最終的にこのリンクから解決策を得ました: https://github.com/googlesamples/Android-architecture-components/issues/25

MyFirebaseMessagingServiceServiceクラスであるため、Serviceクラスへの注入の場合、Daggerは依存関係をServiceクラスに注入する方法を提供します。以下は、サービスクラスでインジェクションを有効にする手順です。

1)アプリケーションにHasServiceInjectorを実装させ、サービスにDispatchingAndroidInjectorを注入します。

public class App extends Application implements HasActivityInjector, HasServiceInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingActivityInjector;

    // Add this line
    @Inject
    DispatchingAndroidInjector<Service> dispatchingServiceInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        AppInjector.init(this);
    }

    @Override
    public AndroidInjector<Activity> activityInjector() {
        return dispatchingActivityInjector;
    }

    // override this method after implementing HasServiceInjector
    @Override
    public AndroidInjector<Service> serviceInjector() {
        return dispatchingServiceInjector;
    }

}

2)サービスにインジェクションを実行するための新しいモジュールを作成します。

@Module
abstract class ServiceBuilderModule {

    // for my case, the service class which needs injection is MyFirebaseMessagingService
    @ContributesAndroidInjector
    abstract MyFirebaseMessagingService contributeMyFirebaseMessagingService();

}

3)アプリケーションのコンポーネントに新しいモジュールを登録します。

@Component(modules = {
        AndroidSupportInjectionModule.class,
        AppModule.class,
        ActivityBuilderModule.class,
        // Need to define previously created module class here
        ServiceBuilderModule.class
})
@Singleton
public interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(App application);
        AppComponent build();
    }
    void inject(App app);
}

4)最後に、AndroidInjection.inject(this)。を追加するサービスのメソッドonCreateをオーバーライドします。

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    //So now we are able to inject here same as we do in Activity. No need for constructor injection
    @Inject ExampleOneDao exampleOneDao

    // Override this method first
    @Override
    public void onCreate() {
        AndroidInjection.inject(this);
        super.onCreate();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // use your dao here to store remoteMessage data payload into your database, e.g exampleOneDao.save(somethingHere)
    }


}
16
Sharoon Amjid

Daggerとの依存関係をサービスに注入するには、型エラーMyFirebaseMessagingServiceを回避するために、コンストラクターからではなく、パブリッククラス変数を使用する必要があります。ゼロ引数コンストラクターはありません。

ソリューション パスを実装した後

から:

class MyFirebaseMessagingService @Inject constructor(exampleOneDao: ExampleOneDao?) : FirebaseMessagingService() {

    override fun onMessageReceived(remoteMessage: RemoteMessage?) {
    //need db instance to store data payload locally (Room)
    }
}

に:

class MyFirebaseMessagingService : FirebaseMessagingService() {

@Inject 
private lateinit var exampleOneDao: ExampleOneDao? 

    override fun onMessageReceived(remoteMessage: RemoteMessage?) {
    //need db instance to store data payload locally (Room)
    }
}

GL

ソース

0
CORONEL Braian

Kotlinの実装は次のとおりです。

Application.kt

@Inject
lateinit var dispatchingServiceInjector: DispatchingAndroidInjector<Service>

override fun serviceInjector(): AndroidInjector<Service> {
    return dispatchingServiceInjector
}

Module.kt

@Module
abstract class FirebaseServiceModule {
    @ContributesAndroidInjector
    abstract fun contributeMyFirebaseMessengingService(): MyFirebaseMessengingService
}

Component.kt

@Component(modules = [FirebaseServiceModule::class])
interface Component {
    ...
}

MyFirebaseMessengingService.kt

override fun onCreate() {
    AndroidInjection.inject(this);
    super.onCreate()
}
0
sonique