This should be obvious but I can't find the solution. Many people have asked it and the reply is usually to just switch to a context-registered receiver instead. I have an accessibility service which needs to be notified when the Manifest-declared receiver picks up something. Obviously this can't be done with an interface since I can't find a way to get the instance of the receiver. Here's some code:
Manifest:
<service
android:name=".MyAccessibilityService"
android:exported="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:process=":listenerProcess4">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibilityservice" />
</service>
<receiver
android:name=".MyBroadcastReceiver"
android:exported="false"
android:process=":listenerProcess4">
<intent-filter>
<action android:name="roastie_toastie" />
</intent-filter>
</receiver>
Receiver:
public class MyBroadcastReceiver extends BroadcastReceiver {
BroadcastReceivedListener mBroadcastReceivedListener;
public void setBroadcastReceivedListener(BroadcastReceivedListener broadcastReceivedListener) {
mBroadcastReceivedListener = broadcastReceivedListener;
}
@Override
public void onReceive(Context context, Intent intent) {
mBroadcastReceivedListener.broadcastReceived();
}
public interface BroadcastReceivedListener {
void broadcastReceived();
}
}
MyAccessibilityService:
public class MyAccessibilityService extends AccessibilityService implements MyBroadcastReceiver.BroadcastReceivedListener {
boolean lightsAreOn = true;
@Override
public void broadcastReceived() {
lightsAreOn = false;
}
}
I asked a couple of times for concrete scenarios, and you did not really provide any, so I am going to answer with an abstract scenario: suppose that your broadcast is designed to send a command to the service.
In that case, you could:
Implement a singleton (here called CommandBus
, for lack of a better idea of a name). Ideally, that singleton would be set up by a dependency inversion framework (e.g., Dagger/Hilt).
Have CommandBus
expose some reactive way to get commands to the service. If you were using Kotlin, that could be a SharedFlow
. Since you are using Java, that could be an RxJava Observable
, or perhaps a simple callback.
Have MyAccessibilityService
get access to the CommandBus
singleton and use whatever you set up in step #2 to find out about commands.
Have CommandBus
expose an API to hand it commands to deliver to the service (e.g., a sendCommand()
method).
Have MyBroadcastReceiver
get access to the CommandBus
singleton and call the method from step #4 in onReceive()
.
At this point, when MyBroadcastReceiver
receives a broadcast, it tells CommandBus
to send the command, which then flows over to MyAccessibilityService
, which goes and does something.