从另一个 BroadcastReceiver 中注册 BroadcastReceiver 时出现 ReceiverCallNotAllowedException

ReceiverCallNotAllowedException when registering a BroadcastReceiver from within another BroadcastReceiver

在下面的代码中,我有一个 boot_completed BroadcastReceiver,在 onReceive 中我注册了另一个 BroadcastReceiver 来监视调用变化。但它抛出 ReceiverCallNotAllowedException,因为 according to document 当尝试从另一个 BroadcastReceiver 中注册一个 BroadcastReceiver 时会发生这种情况。那么,在这种情况下,您的建议是什么,因为我不想启动 activity 来注册呼叫接收器。

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(收到boot_completed意图)

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>

我正在考虑使用一个虚拟服务,我从 ServiceStarter class 启动它,并使用这个虚拟服务来注册 CallReceiver。你怎么看。

编辑 1:

我创建了一个由 ServiceStarter 启动的虚拟服务(移动设备启动时调用接收器),并在虚拟服务中注册了 CallReceiver(监视呼叫状态变化的 BroadcastReceiver)。但我最终遇到了以下异常:

Service has leaked IntentReceiver in android

ServiceStarter.java(收到boot_completed意图)

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(我注册CallReceiver广播的地方)

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;
}
}

So, what's your suggestion in this case, knowing that I don't want to launch an activity to register the call receiver

在清单中注册广播。该特定广播出现在 the list of implicit broadcasts for which you can register in the manifest.

我终于找到了从另一个 BroadcastReceiver (ServiceStarter) 注册 BroadcastReceiver (CallReceiver) 时发生的 ReceiverCallNotAllowedException 的解决方案。

这会导致异常:

public void registerCallReceiver(Context aCtx){
   aCtx.registerReceiver(receiver, intentFilter);
}

这不会引起异常:

public void registerCallReceiver(Context aCtx){
   aCtx.getApplicationContext().registerReceiver(receiver, intentFilter);
}

来源: https://www.py4u.net/discuss/700956