Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Alarm Manager Not working when app is Killed

Tags:

android

I want to schedule an alarm that fire's every 1 min and wake up my app. It is working on Emulator, but not working on customised OS phones like VIVO, OPPO, MIUI etc. I have written a Sticky service & a broadcast Receiver. When service will be destroyed or TaskRemoved, i called method named sendBroadcast() that will trigger my Broadcast Receiver and My Brodcast Receiver will start the service again by calling startservice(intent) method. But this is Not working when app is killed. When app is in Foreground it working fine. I want Alarm Manger will work when an app is Killed.

This is my code below--

My MainActivity.java file to start the service--

public class MainActivity extends AppCompatActivity
{

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Intent alarmIntent = new Intent(this, AlarmService.class);
    startService(alarmIntent);


}   }

My Sticky Service code is --

public class AlarmService extends Service
{

private String TAG ="AlarmService";
@Override
public void onCreate()
{
    sendBroadcast();
    super.onCreate();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
    Log.e(TAG, "onStartCommand");
    //return super.onStartCommand(intent, flags, startId);
    return Service.START_STICKY;
}


@Override
public void onDestroy() {
    sendBroadcast();
    super.onDestroy();
}


@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}


@Override
public void onTaskRemoved(Intent rootIntent) {
    sendBroadcast();
    super.onTaskRemoved(rootIntent);
}

private void sendBroadcast()
{
    Intent intent = new Intent(this,AlarmReceiver.class);
    //intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            this.getApplicationContext(), 234324243, intent, 0);
    AlarmManager alarmManager = (AlarmManager) getApplicationContext().getSystemService(ALARM_SERVICE);

    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 5);
    if (alarmManager != null)
    {
        //System.currentTimeMillis() + (i * 100),
        alarmManager.setRepeating(
                AlarmManager.RTC_WAKEUP,
                System.currentTimeMillis(),
                60000,
                pendingIntent);
    }
}}

My BroadcastReceiver is as follows --

public class AlarmReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
    // For our recurring task, we'll just display a message
    Toast.makeText(context, "I'm running", Toast.LENGTH_LONG).show();
    generateNotification(context);

    //restartJobScheduler(context);
    if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) restartJobScheduler(context);
    else restartService(context);

}

private void restartJobScheduler(Context context)
{
    Log.i("MyBroadCastReceiver", "onReceive");
    //context.startForegroundService(service);
    FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
    Job myJob = dispatcher.newJobBuilder()
            .setService(MyJobService.class)
            .setTag("myFCMJob")
            .build();
    dispatcher.mustSchedule(myJob);
}

private void restartService(Context context)
{
    Intent restartServiceIntent = new Intent(context, AlarmService.class);
    context.startService(restartServiceIntent);

}}

My Android.Manifest file is as below---

<receiver android:name=".AlarmReceiver">
        <intent-filter>

            <action android:name="android.intent.action.BOOT_COMPLETED" />

        </intent-filter>
    </receiver>

    <service
        android:name=".MyJobService"
        android:exported="false"
        android:stopWithTask="false">
        <intent-filter>
            <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE" />
        </intent-filter>
    </service>

    <service android:name=".AlarmService"
        android:exported="false"
        android:label="Alarm Service"
        android:stopWithTask="false">

        <intent-filter>
            <action android:name="com.example.tas9.alarmmanager.AlarmService" />
        </intent-filter>

    </service>
like image 726
Rohan Shinde Avatar asked Apr 20 '18 10:04

Rohan Shinde


People also ask

Does Alarm Manager persist even after reboot?

The AlarmManager service is a convenient class to schedule working on your Android application; however, when the device shuts down or reboots, all your alarms will be lost since the system does not retain them between system restarts.

How do I turn off alarm manager on Android?

In order to delete : AlarmManager alarmManager = (AlarmManager) getSystemService(Context. ALARM_SERVICE); Intent myIntent = new Intent(getApplicationContext(), SessionReceiver. class); PendingIntent pendingIntent = PendingIntent.


Video Answer


3 Answers

Ok, so i personally wasted 6 hours today, doing everything which is described in the official doc - https://developer.android.com/training/scheduling/alarms.html. I also tried different setups like - ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP etc. Nothing really helped me, my alarms would only work when the app was opened, and as soon as i would close the app(removed it from the task bar) no alarms would fire. I've found the solution here by accident - https://issuetracker.google.com/issues/150080941#comment5 - we are only seeing this when the app is launched via the green play button from studio, and not in an indepdent session such as when sideloading the apk or when clicking on the app icon from the device.

TL;DR - Try to test you alarm manager functionality by sideloading the apk, and not by launching it via green play button in Android Studio.

like image 82
nvr Avatar answered Oct 27 '22 03:10

nvr


The problem is the way, you are trying to install the app.

App is in Foreground or background state: In such case installing the app via the Android Studio's Run (play) button will work fine

App is being killed: Build the APK, download & install in your phone, it will work fine. Installing the app via Android Studio will not work.

To sum up, simply build the APK (Build --> Build APK), it will work in every scenario.

This is just a clarification of the above answer by @nvr

like image 34
Gopal Dan Avatar answered Oct 27 '22 04:10

Gopal Dan


On some devices you will need to manually add your app to the list of apps allowed to run in the background. Otherwise, even with a "sticky" Service, Android will not restart the Service once the process has been killed. Manufacturers do this to save battery life.

In the settings, there should be a way to add your app to the list of "protected apps" or "apps allowed to run in the background". Look in the power management settings or the Apps settings.

like image 32
David Wasser Avatar answered Oct 27 '22 04:10

David Wasser