Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keep broadcast receiver running after application is closed

I need to keep broadcast receiver running all the time after app has been started.

Here is the code that registers this receiver in the application

    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ScreenEventsReceiver();
    registerReceiver(mReceiver, filter);

And code for receiver

public class ScreenEventsReceiver extends BroadcastReceiver {
     public static boolean wasScreenOn = true;

     @Override
     public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            wasScreenOn = false;
            Log.d("ScreenEventReceiver", "ON");
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            wasScreenOn = true;
            Log.d("ScreenEventReceiver", "ON");
        }
     }
}
like image 861
Sergey Pekar Avatar asked May 29 '13 21:05

Sergey Pekar


People also ask

Can broadcast receiver run in background?

If you want a background receiver, you need to register it inside the AndroidManifest (with intent filter), add an IntentService and start it when you receive a broadcast in the receiver.

What is the time limit of broadcast receiver?

As a general rule, broadcast receivers are allowed to run for up to 10 seconds before they system will consider them non-responsive and ANR the app.

Does broadcast receiver run on main thread?

onReceive always run in the UI thread? Yes.

Is it necessary to unregister a broadcast receiver?

It's always suggested to register and unregister broadcast receiver programmatically as it saves system resources.


4 Answers

You can use a service

In main app start/stop the service

Intent service = new Intent(context, MyService.class); context.startService(service); ... Intent service = new Intent(context, MyService.class); context.stopService(service); 

service

public class MyService extends Service {  private static BroadcastReceiver m_ScreenOffReceiver;   @Override  public IBinder onBind(Intent arg0)  {   return null;  }   @Override  public void onCreate()  {   registerScreenOffReceiver();  }   @Override  public void onDestroy()  {   unregisterReceiver(m_ScreenOffReceiver);   m_ScreenOffReceiver = null;  }   private void registerScreenOffReceiver()  {   m_ScreenOffReceiver = new BroadcastReceiver()   {    @Override    public void onReceive(Context context, Intent intent)    {      Log.d(TAG, "ACTION_SCREEN_OFF");      // do something, e.g. send Intent to main app    }   };   IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);   registerReceiver(m_ScreenOffReceiver, filter);  } } 
like image 113
j.holetzeck Avatar answered Sep 25 '22 07:09

j.holetzeck


Accepted answer is not an actual answer i think. I will explain what the issue. I think you are testing your app in the Huawie, Oppo, Vivo, Xiomi,asus....... or some devices. With that devices if we close the application they will also close our broadcast receivers. So thats the problem.(To check that use a with pixel nexus emulator). I will explain how to resolve this.``

  • we would add our app to the protected app list. OS only allow to them to continue broadcast receiver activities.(Copy this array declaration to your code)

    private static final Intent[] POWERMANAGER_INTENTS = {
        new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
        new Intent().setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
        new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
        new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),
        new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
        new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
        new Intent().setComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
        new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
        new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
        new Intent().setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
        new Intent().setComponent(new ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")),
        new Intent().setComponent(new ComponentName("com.htc.pitroad", "com.htc.pitroad.landingpage.activity.LandingPageActivity")),
        new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.MainActivity"))};
    
  • Put these code to your onCreate Method. Here i used shared preference for check it only first time of the app open.

`

final SharedPreferences.Editor pref =    getSharedPreferences("allow_notify", MODE_PRIVATE).edit();    pref.apply(); final SharedPreferences sp =    getSharedPreferences("allow_notify", MODE_PRIVATE)`;


    if(!sp.getBoolean("protected",false)) {
        for (final Intent intent : POWERMANAGER_INTENTS)
            if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {

            AlertDialog.Builder builder  = new AlertDialog.Builder(this);
            builder.setTitle("Alert Title").setMessage("Alert Body")
                    .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            startActivity(intent);
                            sp.edit().putBoolean("protected",true).apply();

                        }
                    })
                    .setCancelable(false)
                    .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    })
                    .create().show();
            break;
like image 44
Tharuka Lakshan Avatar answered Sep 26 '22 07:09

Tharuka Lakshan


Be careful if you are using Android 4.4.x as there is a bug which kills background services when closing the app. I was testing my app in Android 4.4.2 and I had the same problem. Here there is a detailed explanation:

http://www.androidpolice.com/2014/03/07/bug-watch-stopping-apps-on-android-4-4-2-can-silently-kill-related-background-services-a-fix-is-on-the-way/

like image 29
Ana María Martínez Gómez Avatar answered Sep 26 '22 07:09

Ana María Martínez Gómez


You cannot receive some broadcast events through components declared in manifest.

These events are

  • ACTION_BATTERY_CHANGED
  • ACTION_CONFIGURATION_CHANGED
  • ACTION_SCREEN_OFF (You are playing with this event)
  • ACTION_SCREEN_ON (You are playing with this event)
  • ACTION_TIME_TICK

Reference https://developer.android.com/reference/android/content/Intent.html#ACTION_SCREEN_ON

So in your specific events, you will have to create a Service & you will have to register your event explicitly in service onCreate() with with Context.registerReceiver().

For other events, entry in manifest is sufficient.

like image 25
Vivek A Naik Avatar answered Sep 24 '22 07:09

Vivek A Naik