In the code below, I have a boot_completed BroadcastReceiver, where in onReceive I register another BroadcastReceiver to monitor calls changes. But it throws ReceiverCallNotAllowedException, as according to document this happens when trying to register a BroadcastReceiver from within another BroadcastReceiver. So, what's your suggestion in this case, knowing that I don't want to launch an activity to register the call receiver.
ReceiverCallNotAllowedException This exception is thrown from Context#registerReceiver and Context#bindService when these methods are being used from an BroadcastReceiver component. In this case, the component will no longer be active upon returning from receiving the Intent, so it is not valid to use asynchronous APIs.
ServiceStarter.java (The one receives boot_completed intent)
public class ServiceStarter extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent != null && intent.getAction() != null){
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) || Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
registerCallReceiver(context);
}
}
}
public void registerCallReceiver(Context aCtx){
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.PHONE_STATE");
// CallReceiver extends BroadcastReceiver
CallReceiver receiver = new CallReceiver();
aCtx.registerReceiver(receiver, intentFilter);
}
AndroidManifest.xml
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!--This part is inside the application-->
<receiver android:name=".CallReceiver" >
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
I'm considering having a dummy service, that I start it from the ServiceStarter class, and use this dummy service to register the CallReceiver. What do you think.
Edit 1:
I created a dummy service to be started by ServiceStarter (A receiver gets called when the mobile boots), and in the dummy service I register the CallReceiver (BroadcastReceiver that monitors changes in calls status). But I ended up with the following exception:
Service has leaked IntentReceiver in android
ServiceStarter.java (The one receives boot_completed intent)
public class ServiceStarter extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent != null && intent.getAction() != null){
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()) || Intent.ACTION_LOCKED_BOOT_COMPLETED.equals(intent.getAction())) {
startDummyService(context);
}
}
}
public void startDummyService(Context aCtx){
Intent intent = new Intent(aCtx, DummyService.class);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
aCtx.startForegroundService(intent);
} else {
aCtx.startService(intent);
}
}
DummyService.java (Where I register CallReceiver broadcast)
public class DummyService extends Service {
@Override
public void onCreate() {
super.onCreate();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.intent.action.PHONE_STATE");
CallReceiver receiver = new CallReceiver();
registerReceiver(receiver, intentFilter);
}
@Override
public int onStartCommand(Intent aIntent, int aFlags, int aStartId){
super.onStartCommand(aIntent, aFlags, aStartId);
return START_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
I finally found the solution to the ReceiverCallNotAllowedException that takes place when registering a BroadcastReceiver (CallReceiver) from another BroadcastReceiver (ServiceStarter).
This will cause the exception:
public void registerCallReceiver(Context aCtx){
aCtx.registerReceiver(receiver, intentFilter);
}
This will not cause the exception:
public void registerCallReceiver(Context aCtx){
aCtx.getApplicationContext().registerReceiver(receiver, intentFilter);
}