Android AlarmManager Broadcast Receiver And Service

Filed Under: Android

In this tutorial, we’ll be discussing AlarmManager and Broadcast Receiver and see how to trigger a Background Service using them in our Android Application.

AlarmManager Broadcast Receiver Service

An AlarmManager is used to trigger some code at a specific time. It uses the Android SDK’s alarm service and runs independently of the application’s lifecycle.

To start an Alarm Manager you need to first get the instance from the System. Then pass the PendingIntent which would get executed at a future time that you specify.


AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

Intent alarmIntent = new Intent(context, MyAlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
int interval = 8000;
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);

There are different types of Alarm Manager that can be invoked:

  • setInExactAndRepeating – This doesn’t trigger the alarm at the exact time.
  • setExact – Setting an alarm manager using this ensures that the OS triggers the alarm at almost the exact time.
  • setExactAndAllowWhileIdle – This method came up with Android M. These types of alarms are allowed to get executed even in low power modes.

You need to be careful while using the Alarm Manager since they can consume battery if not handled properly.
Normally, an alarm manager cannot repeat before a minute. Also in low power mode, the duration can increase to up to 15 minutes.

Broadcast Receivers listen to system-wide and application events.
In order to trigger a Broadcast Receiver when the system is rebooted, you need to call ACTION_BOOT_COMPLETED.

In the following section, we’ll be showing how to use an Alarm Manager to trigger a Broadcast Receiver which ultimately calls a background service.

Project Structure

Android Alarm Broadcast Service Project

Android Alarm Broadcast Service Project

Code

You need to register your Broadcast Receiver and Service in the AndroidManifest.xml as shown below:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.journaldev.androidalarmbroadcastservice">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver
            android:name=".MyBroadCastReceiver"
            android:directBootAware="true"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <service
            android:name="com.journaldev.androidalarmbroadcastservice.MyService"
            android:enabled="true"
            android:exported="false"
            android:process=":remote" />
    </application>

</manifest>

In order to ensure that the Broadcast Receiver gets triggered properly on reboot in Android N and above, you need to set the directBootAware to be true and LOCKED_BOOT_COMPLETED

The code for the activity_main.xml layout is given below:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnStartAlarm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Alarm"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnCancelAlarm"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel Alarm"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnStartAlarm" />

</android.support.constraint.ConstraintLayout>

The code for the MainActivity.java is given below:


package com.journaldev.androidalarmbroadcastservice;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    Button btnStartAlarm, btnCancelAlarm;

    AlarmManager alarmManager;
    PendingIntent pendingIntent;

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

        btnStartAlarm = findViewById(R.id.btnStartAlarm);
        btnCancelAlarm = findViewById(R.id.btnCancelAlarm);

        alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        Intent alarmIntent = new Intent(this, MyBroadCastReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);

        btnStartAlarm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startAlarm();
            }
        });

        btnCancelAlarm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cancelAlarm();
            }
        });
    }

    private void startAlarm() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, 0, pendingIntent);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, 0, pendingIntent);
        } else {
            alarmManager.set(AlarmManager.RTC_WAKEUP, 0, pendingIntent);
        }


    }

    private void cancelAlarm() {
        alarmManager.cancel(pendingIntent);
        Toast.makeText(getApplicationContext(), "Alarm Cancelled", Toast.LENGTH_LONG).show();
    }
}

The code for the MyBroadcastReceiver.java file is given below:


package com.journaldev.androidalarmbroadcastservice;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class MyBroadCastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {

            Intent serviceIntent = new Intent(context, MyService.class);
            context.startService(serviceIntent);
        } else {
            Toast.makeText(context.getApplicationContext(), "Alarm Manager just ran", Toast.LENGTH_LONG).show();
        }

    }
}

We trigger the Service when the phone is rebooted. Inside the Service, we start a repeating alarm.
The code for the MyService.java class is given below:


package com.journaldev.androidalarmbroadcastservice;

import android.app.AlarmManager;
import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.support.annotation.Nullable;

public class MyService extends IntentService {


    public MyService() {
        super("MyService");
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {

        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        Intent alarmIntent = new Intent(this, MyBroadCastReceiver.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, 0, 10000, pendingIntent);
    }
}

The output of the above application in action is given below:

Android Alarm Broadcast Service Output

Android Alarm Broadcast Service Output

That brings an end to this tutorial. You can download the project from the link below:

Comments

  1. gloomyad says:

    I suppose this code is not for sdk 26 and upper. Android 8 has sdk 26 and it doesn’t support setInexactRepeating because of DOZE.

  2. Rox says:

    Hello. I’m install your app to my phone (Android 8.1) but after reboot is nothing happend. Can you help to fix this?

    1. SARA says:

      ITS NOT WORKING

  3. b nagesh rao says:

    hi i am learning android please tell from where to learn and please provide some tips

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages