简体   繁体   中英

Android alarm is cancelled when cleared from recent app list in KITKAT

My application targets KITKAT and up android version and i am trying to create repetitive notification daily via Alarm Manager below is my code :

public class AlarmReceiver extends BroadcastReceiver {
    public static final String MY_ACTION = "mymasterpeice.foreverservice.myaction";

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

        if (intent.getAction().equals(MY_ACTION)) {
            // Do something here
            // For our recurring task, we'll just display a message
            Toast.makeText(context, "I'm running", Toast.LENGTH_SHORT).show();
            // displayNotification(context, "Checkout New Articles");
            sendNotification(context, "Checkout New Articles - Team");

        }


    }

    /**
     * Issues a notification to inform the user that server has sent a message.
     */
    private static void sendNotification(Context context, String message) {
        if (message != null && !TextUtils.isEmpty(message)) {
            int icon = R.mipmap.ic_launcher;
            long when = System.currentTimeMillis();
            NotificationManager notificationManager = (NotificationManager)
                    context.getSystemService(Context.NOTIFICATION_SERVICE);
            String title = context.getString(R.string.app_name);
            Intent notificationIntent = new Intent(context, MainActivity.class);
            // set intent so it does not start a new activity
            notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                    Intent.FLAG_ACTIVITY_SINGLE_TOP);
            PendingIntent intent =
                    PendingIntent.getActivity(context, 0, notificationIntent, 0);
            Notification.Builder builder = new Notification.Builder(context);
            notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                    Intent.FLAG_ACTIVITY_SINGLE_TOP);
            builder.setSmallIcon(icon)
                    .setContentTitle(title)
                    .setContentText(message)
                    .setContentIntent(intent);
            Notification notification = builder.getNotification();
            notificationManager.notify(icon, notification);
        }
    }


}

Main Activity :

public class MainActivity extends AppCompatActivity {

    private String TAG=MainActivity.class.getSimpleName();
    public static final String MY_ACTION = "mymasterpeice.foreverservice.myaction";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setRecusrringTimer();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    private void setRecusrringTimer() {
        Intent myIntent = new Intent(MY_ACTION);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(
                this, 0, myIntent, 0);
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        Calendar firingCal = Calendar.getInstance();
        Calendar currentCal = Calendar.getInstance();
        firingCal.set(Calendar.HOUR, 7); // At the hour you wanna fire
        firingCal.set(Calendar.MINUTE, 0); // Particular minute
        firingCal.set(Calendar.SECOND, 0); // particular second
        long intendedTime = firingCal.getTimeInMillis();
        long currentTime = currentCal.getTimeInMillis();
        if (intendedTime >= currentTime) // you can add buffer time too here to ignore some small differences in milliseconds
        {
            alarmManager.setRepeating(AlarmManager.RTC,
                    intendedTime, AlarmManager.INTERVAL_DAY,
                    pendingIntent);
            Log.d(TAG, "setRecusrringTimer ");
        } else {
            intendedTime = firingCal.getTimeInMillis();
            Log.d(TAG, "setRecusrringTimer ");
            alarmManager.setRepeating(AlarmManager.RTC,
                    intendedTime, AlarmManager.INTERVAL_DAY,
                    pendingIntent);

        }
    }

}

Manifest :

    <receiver android:name=".AlarmReceiver">
        <intent-filter>
            <action android:name="mymasterpeice.foreverservice.myaction"/>
        </intent-filter>
    </receiver>

Issue is This code runs properly on Kitkat device until app is in memory , there are some delays like as in doc specified :

Note: Beginning with API 19 (KITKAT) alarm delivery is inexact: the OS will shift alarms in order to minimize wakeups and battery use. There are new APIs to support applications which need strict delivery guarantees; see setWindow(int, long, long, PendingIntent) and setExact(int, long, PendingIntent). Applications whose targetSdkVersion is earlier than API 19 will continue to see the previous behavior in which all alarms are delivered exactly when requested.

But When app is not in memory the alarm manager does not show notification . I am specifically targeting Kitkat and above version of android.

I lost 1 month of my time for the same issue. Finally I found the solution. For the recent Android versions(exact version I am not sure ), an option called 'Auto Launch' have been introduced, which means the user can actually configure whether any app can be automatically started or not. So please check whether your app has permission for auto launch. This setting location may vay based on phone manufacturer. So you need to search for this 'Auto Lanuch' option in your phone settings. Even if it doesn't work, try removing your app from the 'Optimizations List' as well, which you can find in the settings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM