inject dependencies into background services in Dagger2
I have Shared Preferences
as a Dagger singleton component. I need to inject it into a background service, such as FirebaseInstanceService
. Here is my attempt :
public class InstanceIDListenerService extends FirebaseInstanceIdService {
@Inject
Preferences preferences;
@Override
public void onTokenRefresh() {
((MyApp) getApplication()).getSingletonComponent().inject(this);
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
preferences.setFcmToken(refreshedToken);
}
}
Its usage goes like this:
<service android:name="com.fcm.InstanceIDListenerService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
I should use ((MyApp) getApplication()).getSingletonComponent().inject(this) in the onTokenRefresh
listener;
Is it? Is this the right listener to inject dependencies?
Solution
I
know this issue is old, but I’ve been thinking about it for the last few hours and have found a solution.
With the new Dagger2 version, you can now enable your application to implement the HasServiceInjector interface, which allows you to inject content into your service.
A simple example:
1) Create your service module:
@Module
abstract class ServicesModule {
@ContributesAndroidInjector
abstract SomeService ProvideSomeService();
}
2) Add it to your app component:
@Component(modules = {
AndroidSupportInjectionModule.class,
AppModule.class,
ActivitiesModule.class,
ServicesModule.class
})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(App application);
AppComponent build();
}
void inject(App app);
}
3) Have your application implement the above interface:
public class App extends Application implements HasActivityInjector, HasServiceInjector {
@Inject
DispatchingAndroidInjector<Activity> activityInjector;
@Inject
DispatchingAndroidInjector<Service> serviceInjector;
@Override
public void onCreate() {
super.onCreate();
AppInjector.init(this);
}
@Override
public AndroidInjector<Activity> activityInjector() {
return activityInjector;
}
@Override
public AndroidInjector<Service> serviceInjector() {
return serviceInjector;
}
}
4) Finally, inject your service:
public class SomeService extends Service {
@Inject
SomeDependency dependency;
@Override
public void onCreate() {
AndroidInjection.inject(this);
super.onCreate();
}
Do things with your dependencies
}
I’m using a service in my example, but my real-world use case is also using FirebaseInstanceIdService. And it worked.