AlarmManager Stops after removing app from recents

2019-06-12 17:09发布

问题:

I am new to this part of android, and here I aim to use alarm manager to run a code snippet every 2 minute which will poll a server (using the website's api) and based on the returned JSON generate notification. After a looking up the web I thought one of the best option in my case will be using intent service and android.

Manifest of Services and Recievers

<service
    android:name=".NotifyService"
    android:enabled="true"
    android:exported="false" >
</service>
<receiver
    android:name=".TheReceiver"
    android:enabled="true"
    android:exported="true" >
</receiver>
<receiver
    android:name=".OnOffReceiver"
    android:enabled="true"
    android:exported="true" >
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
</receiver>

Part in the flash screen activity where I call the intent service which is responsible for polling for notification:

Intent msgIntent = new Intent(this, NotifyService.class);
    startService(msgIntent);

The receiver to start the alarm on device start:

public class OnOffReceiver extends BroadcastReceiver
{
    private AlarmManager alarmMgr;
    private PendingIntent alarmIntent;
    public OnOffReceiver(){}
    @Override
    public void onReceive(Context context, Intent intent)
    {
        Intent service = new Intent(context, NotifyService.class);
        service.setAction(NotifyService.CREATE);
        context.startService(service);
    }
} 

The IntentService Class

public class NotifyService extends IntentService
{
    public NotifyService()
    {
        super("NotifyService");
    }
    public static final int STATUS_RUNNING = 0;
    public static final int STATUS_FINISHED = 1;
    public static final int STATUS_ERROR = 2;

    @Override
    protected void onHandleIntent(Intent intent)
    {
        if (intent != null)
        {
            final String action = intent.getAction();
        }
        StartStuff();
    }

    public void StartStuff()
    {
        Intent intent = new Intent(this, TheReceiver.class);
        PendingIntent pend_intent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,1200,1200, pend_intent); 
     //1200ms to make it easier to test
    }

}

The receiver class which sets notification, for testing pupose I am not doing any network related work here just making a simple notification to check if the app is running in all situations

public class TheReceiver extends BroadcastReceiver
{
    public TheReceiver(){}
    @Override
    public void onReceive(Context context, Intent intent)
    {
         Toast.makeText(context, " Success ", Toast.LENGTH_SHORT).show();
         Log.d("Notification", "The Receiver Successful");
        showNotification(context);

    }
    private void showNotification(Context context)
    {         
        NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(context).setContentTitle("My notification").setContentText("Hello World!");
        mBuilder.setDefaults(Notification.DEFAULT_SOUND);
        mBuilder.setAutoCancel(true);
        NotificationManager mNotificationManager =
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(1, mBuilder.build());

    }  
} 

However the notification come only when the app is running or in the recent apps tray. It does not start notifying when the phone reboots, nor does it notify after the app is removes from the recent apps tray.

The app needs Notify users like other apps (like gmail, whatsapp) do, even if they are swiped out of the recent apps tray. Timeliness and punctuality are not very big issue as delay up to 5 to 10 minutes are tolerable. (I intend to poll ever 2 minutes though.)

Where am I going wrong? Also, is there a better way to go about the problem?

回答1:

To keep a receiver active after closing the app is to use

android:process=":remote"

in the manifest file for the receiver that needs to be kept alive.

 <receiver
        android:name=".TheAlarmReceiver"
        android:process=":remote">
 </receiver>

in the manifest for the receiver (TheReceiver in this case) that we need to keep active after the app closes.

P.S. : I also changed the way I use IntentsService and AlarmManager for the application, as my previous(above) implementation is not a very good way to go around it.



回答2:

If an App is killed from recent apps or from "force stop" it won't restart by itself. The user has to start the app again in order to make it run again. There is no way to prevent this. It's just the way android works.

However there is a way to make your app run oon boot. Check out this link.