Search code examples
androidservicebroadcastreceiver

I want my service and broadcast receiver to run even if app is cleared from app list or forced stop


I want my service and broadcast receiver to run in background even if app is closed or force stopped.

My receiver is detecting screen on response and doing the task. Its working fine when app is open and when app is in app list but not closed. When i clear the app from app list, it is not detecting the screen on response. I have tried many ways but couldn't succeed. Help me out.

Manifest file :-

<receiver
        android:name=".broadcastReceiver.MyReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.SCREEN_OFF"/>
            <action android:name="android.intent.action.SCREEN_ON"/>
        </intent-filter>
    </receiver>

    <service
        android:name=".service.MyService"
        android:enabled="true"
        android:exported="true"
        android:stopWithTask="false">

    </service>

MyService class :-

private var myReceiver:MyReceiver?=null

private var defaultUEH:Thread.UncaughtExceptionHandler?=null
private var uncaughtExceptionHandler = object:Thread.UncaughtExceptionHandler{

    override fun uncaughtException(thread: Thread?, ex: Throwable?) {

        Log.d("Exception found","Uncaught exception start!")
        ex!!.printStackTrace()

        unregisterReceiver(myReceiver)

        var intent = Intent(applicationContext, MyService::class.java)
        intent.setPackage(packageName)
        var pendingIntent = PendingIntent.getService(applicationContext,1,intent,PendingIntent.FLAG_ONE_SHOT)
        var alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmManager.set(AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime()+1000,pendingIntent)
        System.exit(2)

    }

}

override fun onBind(intent: Intent): IBinder? {
   return null
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

    var intentFilter = IntentFilter("android.intent.action.SCREEN_OFF")
    intentFilter.addAction("android.intent.action.SCREEN_ON")

    myReceiver = MyReceiver()
    registerReceiver(myReceiver , intentFilter)

    return START_STICKY
}

override fun onCreate() {
    super.onCreate()
    Log.d("Service" , "onCreate fun")
}

override fun onDestroy() {

    super.onDestroy()

    Log.d("Service" , "onDestroy fun")
}

override fun onTaskRemoved(rootIntent: Intent?) {

    unregisterReceiver(myReceiver)

    var intent = Intent(applicationContext, MyService::class.java)
    intent.setPackage(packageName)
    var pendingIntent = PendingIntent.getService(this,1,intent,PendingIntent.FLAG_ONE_SHOT)
    var alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
    alarmManager.set(AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime()+1000,pendingIntent)
    super.onTaskRemoved(rootIntent)

}

MyReceiver class:-

override fun onReceive(context: Context?, intent: Intent?) {

    Log.d("Where ","Broadcast")
    if (intent!!.action.equals(Intent.ACTION_SCREEN_ON)){

        var dashboardActivity = DashboardActivity.instance
        var isSosEnabled = dashboardActivity!!.getSos()

        if (isSosEnabled){
            Log.d("Service Sos Enabled","True")
        }else{
            Log.d("Service Sos Enabled", "False")
        }
    }

}

Solution

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