Home » Android » android – Can't register receiver dynamically

android – Can't register receiver dynamically

Posted by: admin June 15, 2020 Leave a comment

Questions:

Can’t register receiver dynamically at boot. I have no activity. And I do not want to register it in the service.

Boot Receiver where I register another receiver:

package zzz.zzz.zzz;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;

public class AutoStart extends BroadcastReceiver
{   
    @Override
    public void onReceive(Context context, Intent intent)
    {   
        if ((intent.getAction() != null) && (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")))
        {
            IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
            filter.addAction(Intent.ACTION_SCREEN_OFF);
            BroadcastReceiver mReceiver = new ScreenReceiver();
            context.registerReceiver(mReceiver, filter);
        }
    }
}

Receiver that I want to register:

package zzz.zzz.zzz;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class ScreenReceiver extends BroadcastReceiver 
{
    @Override
    public void onReceive(Context context, Intent intent)
    {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) 
        {
            // some code            
        }
        if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) 
        {
            // some code        
        }
    }
}

LogCat:

10-12 15:03:45.849: ERROR/AndroidRuntime(240): Uncaught handler: thread Thread-8 exiting due to uncaught exception
10-12 15:03:45.859: ERROR/AndroidRuntime(240): android.content.ReceiverCallNotAllowedException: IntentReceiver components are not allowed to register to receive intents
10-12 15:03:45.859: ERROR/AndroidRuntime(240):     at android.app.ReceiverRestrictedContext.registerReceiver(ApplicationContext.java:126)
10-12 15:03:45.859: ERROR/AndroidRuntime(240):     at android.app.ReceiverRestrictedContext.registerReceiver(ApplicationContext.java:120)
10-12 15:03:45.859: ERROR/AndroidRuntime(240):     at zzz.zzz.zzz.RegisterReceiver$1.run(RegisterReceiver.java:18)
10-12 15:03:46.159: ERROR/ContactsProvider(98): Cannot determine the default account for contacts compatibility
10-12 15:03:46.159: ERROR/ContactsProvider(98): android.accounts.AuthenticatorException: bind failure
10-12 15:03:46.159: ERROR/ContactsProvider(98):     at android.accounts.AccountManager.convertErrorToException(AccountManager.java:1096)
10-12 15:03:46.159: ERROR/ContactsProvider(98):     at android.accounts.AccountManager.access$500(AccountManager.java:74)
10-12 15:03:46.159: ERROR/ContactsProvider(98):     at android.accounts.AccountManager$BaseFutureTask$Response.onError(AccountManager.java:1003)
10-12 15:03:46.159: ERROR/ContactsProvider(98):     at android.accounts.IAccountManagerResponse$Stub.onTransact(IAccountManagerResponse.java:69)
10-12 15:03:46.159: ERROR/ContactsProvider(98):     at android.os.Binder.execTransact(Binder.java:287)
10-12 15:03:46.159: ERROR/ContactsProvider(98):     at dalvik.system.NativeStart.run(Native Method)
10-12 15:03:46.879: ERROR/MediaPlayerService(31): Couldn't open fd for content://settings/system/notification_sound
10-12 15:03:46.889: ERROR/MediaPlayer(52): Unable to to create media player
How to&Answers:

The answer is in the error message: IntentReceiver components are not allowed to register to receive intents. You can’t register a new BroadcastReceiver in an existing BroadcastReceiver.

Answer:

I have launched the service in ACTION_BOOT_COMPLETED as

@Override
public void onReceive(Context context, Intent intent) {

    Log.d("BootReceiver", "onReceive() intent: " + intent.getAction());

    if (intent.getAction() != null) {

        // Boot completed
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            if(!isMyServiceRunning(context)){
                startTheService(context);
            }
        }

that will create my application behind of scene:

public class MyApplication extends Application

and there I have override the onCreate :

@Override
public void onCreate() {
    super.onCreate();
    Log.d("MyApplication", "registering for screen states");
    registerClassBecauseManifestIsNotEnough(getApplicationContext()) ;
}

private void registerClassBecauseManifestIsNotEnough(Context context) {
    IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ScreenStateBroadcastReceiver();       
    context.registerReceiver(mReceiver, intentFilter);
}

Problem solved for me, at least.

Answer:

can’t you register this in the manifest ?

Answer:

For widget needed a solution. Here is how I have solved:

private static boolean isRegisteredFromCode = false;
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

        for (int i = 0; i < appWidgetIds.length; ++i) {
            RemoteViews layout = buildLayout(context, appWidgetIds[i]);
            appWidgetManager.updateAppWidget(appWidgetIds[i], layout);
        }
        super.onUpdate(context, appWidgetManager, appWidgetIds);

        if(!isRegisteredFromCode){
            isRegisteredFromCode = true;
            context.getApplicationContext().registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_OFF));
            context.getApplicationContext().registerReceiver(this, new IntentFilter(Intent.ACTION_SCREEN_ON));
        }       
    }

Widget is a BroadcastReceiver

Answer:

A quite easy solution launches the new services in a separated thread:

public class BootServiceReceiver extends BroadcastReceiver {    

    @Override
    public void onReceive(Context context, Intent intent) {
        // Launcher is a Singleton. 
        // Note that you pass it context.getApplicationContext() as parameter
        final Launcher launcher=Launcher.get(context.getApplicationContext());
        new Thread(new Runnable() {

            @Override
            public void run() {
                launcher.doActions();
            }
        }).start();
    }
}

In the Launcher we have:

public class Launcher {
    private static Launcher instance;
    private Context ctx;
    private BroadcastReceiver receiver1, receiver2;

    private Launcher(Context ctx) {
        this.ctx=ctx;
    }

    public static Launcher get(Context ctx) {
        if (yo==null)
            yo=new Launcher(ctx);
        return yo;
    }

    public void doActions() {
        receiver1=new Receiver1();
        IntentFilter filter1=new IntentFilter(Service1.MY_ACTION);
        ctx.registerReceiver(receiver1, filter1);

        Intent i1=new Intent(ctx, Service1.class);
        ctx.startService(i1);


        receiver2=new Receiver2();
        IntentFilter filter2=new IntentFilter(Service2.MY_ACTION);
        ctx.registerReceiver(receiver2, filter2);

        Intent i2=new Intent(ctx, Service2.class);
        ctx.startService(i2);
    }
}