Android Alarm Clock Tutorial to Schedule and Cancel

By Arvind Rai, June 13, 2015
In this page we will provide android alarm clock tutorial to schedule and cancel. To do this android provides the API that are AlarmManager, PendingIntent and WakefulBroadcastReceiver. Here we will also discuss these API and finally we will create a simple alarm clock. Alarms clock are based on exact and inexact time, repeating and non-repeating. From android API 19, all repeating alarms are inexact. In our example, we have two button start and stop. On click of start, time picker will be displayed and after selecting time, alarm will be scheduled. Before execution if we click stop, then alarm will be canceled which are scheduled.

AlarmManager : Schedule Alarm

android.app.AlarmManager accesses the system alarm services. It can schedule to run any application in the future. To do this an Intent is registered with AlarmManager. Registered alarm also works if device is asleep but it does not work for reboot and turned off mobile. AlarmManager holds a wait lock on CPU as long as receiver's onReceive() method is executing. This feature is because AlarmManager has to ensure that phone will not sleep till it is broadcasting. Find the code snippet how to use it.
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
PendingIntent  pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);  
Find the description of some constants of AlarmManager . Pending intent is fired with different scenario.

ELAPSED_REALTIME : It considers the amount of time since the phone is booted and it does not wake the device.
ELAPSED_REALTIME_WAKEUP : Same as ELAPSED_REALTIME, but phone wakes up.
RTC : It is used to fire pending intent at specified time but phone does not wake up.
RTC_WAKEUP : Same as RTC but phone wakes up.

Find some methods which are used to schedule alarms. These methods are based on exact, inexact time of execution and repeating or single execution.

set(int type, long triggerAtMillis, PendingIntent operation) : Schedules the alarm and if there is already an alarm by the intent then previous one will be canceled. It allows executing only one time.
setExact(int type, long triggerAtMillis, PendingIntent operation) : It behaves same as set() but it does not allow OS to adjust time. The alarm will fire on exact time.
setRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) : It behaves same as set() but repeats for the given interval of time.
setInexactRepeating(int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) : Same as setRepeating() but the executing time will not be exact.
setWindow(int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) : Executes within a given window of time and works same as set(). It can be used for strict ordering of execution in case of multiple alarms.

Now find some constants which gives time in milliseconds and are used for repeating alarm interval. These are INTERVAL_DAY , INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_DAY , INTERVAL_HALF_HOUR , INTERVAL_HOUR .

Find some sample of alarm execution. The below alarm will execute after 15 minutes and repeat after every 15 minutes.
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    AlarmManager.INTERVAL_FIFTEEN_MINUTES, AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);  
The below alarm will execute only one time after 15 minute.
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
   SystemClock.elapsedRealtime() + 15* 60 * 1000, pendingIntent);  

PendingIntent

android.app.PendingIntent is a reference of a token maintained by system describing the original data used to retrieve it. We give a PendingIntent to another application. In this way we grant a permission to other application to execute it. If the owning application is killed, PendingIntent is still usable by other application. In future if creating application finds the same token of PendingIntent, then it can cancel it. PendingIntent can be initialized by using below methods of its own
1. getActivity(Context, int, Intent, int)
2. getActivities(Context, int, Intent[], int)
3. getBroadcast(Context, int, Intent, int)
4. getService(Context, int, Intent, int)
All the above methods returns the instance of PendingIntent. If using alarm, we do as below.
Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
PendingIntent  pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);  

WakefulBroadcastReceiver

android.support.v4.content.WakefulBroadcastReceiver is a helper class that receives a device wakeful event. We override onReceive() method where we can call our service or perform our task. In our case we will play alarm. WakefulBroadcastReceiver uses wake lock, so we must provide WAKE_LOCK permission in AndroidManifest.xml. WakefulBroadcastReceiver is implemented as
public class AlarmReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent) {
	//perform your task
    }	
}  

How to Cancel Alarm Clock

To cancel alarm, AlarmManager provides cancel() method. We can use it as follows.
alarmManager.cancel(pendingIntent);
 

Complete Example

Find alarm clock complete example.

Create Activity, Alarm Receiver and Time Picker


MainActivity.java
package com.concretepage.android;
import java.util.Calendar;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends FragmentActivity{
	private static int timeHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
	private static int timeMinute = Calendar.getInstance().get(Calendar.MINUTE);
	TextView textView1;
	private static TextView textView2;
	public static TextView getTextView2() {
		return textView2;
	}
	AlarmManager alarmManager;
	private PendingIntent pendingIntent;
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.mylayout);
		textView1 = (TextView)findViewById(R.id.msg1);
		textView1.setText(timeHour + ":" + timeMinute);
		textView2 = (TextView)findViewById(R.id.msg2);
		
		alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
                Intent myIntent = new Intent(MainActivity.this, AlarmReceiver.class);
                pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);
        
                OnClickListener listener1 = new OnClickListener() {
			public void onClick(View view) {
				textView2.setText("");
				Bundle bundle = new Bundle();
				bundle.putInt(MyConstants.HOUR, timeHour);
				bundle.putInt(MyConstants.MINUTE, timeMinute);
				MyDialogFragment fragment = new MyDialogFragment(new MyHandler());
				fragment.setArguments(bundle);
                                FragmentManager manager = getSupportFragmentManager();
                                FragmentTransaction transaction = manager.beginTransaction();
                                transaction.add(fragment, MyConstants.TIME_PICKER);
                                transaction.commit();
			}
               };
        
               Button btn1 = (Button)findViewById(R.id.button1);
               btn1.setOnClickListener(listener1);
               OnClickListener listener2 = new OnClickListener() {
			public void onClick(View view) {
				textView2.setText("");
				cancelAlarm();
			}
              };
              Button btn2 = (Button)findViewById(R.id.button2);
              btn2.setOnClickListener(listener2);
        }
        class MyHandler extends Handler {
    	   @Override
    	   public void handleMessage (Message msg){
    		Bundle bundle = msg.getData();
    		timeHour = bundle.getInt(MyConstants.HOUR);
    		timeMinute = bundle.getInt(MyConstants.MINUTE);
    		textView1.setText(timeHour + ":" + timeMinute);
    		setAlarm();
    	  }
        }
        private void setAlarm(){
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, timeHour);
	        calendar.set(Calendar.MINUTE, timeMinute);
                alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        }
        private void cancelAlarm() {
               if (alarmManager!= null) {
        	   alarmManager.cancel(pendingIntent);
               }
        }
}  

AlarmReceiver.java
package com.concretepage.android;
import android.content.Context;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.support.v4.content.WakefulBroadcastReceiver;
public class AlarmReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent) {
        MainActivity.getTextView2().setText("Enough Rest. Do Work Now!");
        Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
        Ringtone ringtone = RingtoneManager.getRingtone(context, uri);
        ringtone.play();
    }
} 



MyDialogFragment.java
package com.concretepage.android;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.DialogFragment;
import android.widget.TimePicker;
public class MyDialogFragment extends DialogFragment {
	private int timeHour;
	private int timeMinute;
	private Handler handler;
	public MyDialogFragment(Handler handler){
		this.handler = handler;
	}
	@Override
	public Dialog onCreateDialog(Bundle savedInstanceState) {
            Bundle bundle = getArguments();
            timeHour = bundle.getInt(MyConstants.HOUR);
            timeMinute = bundle.getInt(MyConstants.MINUTE);
            TimePickerDialog.OnTimeSetListener listener = new TimePickerDialog.OnTimeSetListener() {
			public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
				timeHour = hourOfDay;
				timeMinute = minute;
				Bundle b = new Bundle();
				b.putInt(MyConstants.HOUR, timeHour);
				b.putInt(MyConstants.MINUTE, timeMinute);
				Message msg = new Message();
				msg.setData(b);
				handler.sendMessage(msg);
			}
	    };
	    return new TimePickerDialog(getActivity(), listener, timeHour, timeMinute, false);
	}
} 

MyConstants.java
package com.concretepage.android;
public abstract class MyConstants {
	public static final String HOUR = "time_hour";
	public static final String MINUTE = "time_minute";
	public static final String TIME_PICKER = "time_picker";
} 

AndroidManifest.xml

We must provide permission of WAKE_LOCK and register the receriver. In our case we have to register our AlarmReceiver.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.concretepage.android"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk android:minSdkVersion="19" />
    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
    <application
        android:allowBackup ="false"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity  android:name=".MainActivity" android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver android:name=".AlarmReceiver"/>
    </application>
</manifest> 

Layout XML


mylayout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#D1C4E9"
    android:orientation="vertical" >
    <Button
        android:id="@+id/button1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/btn_start"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
	android:layout_gravity="center"
	android:textColor="#FF8A80"
	android:textSize="100sp"
	android:id="@+id/msg1"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/btn_stop"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
	android:layout_gravity="center"
	android:textColor="#4CAF50"
	android:textSize="50sp"
	android:id="@+id/msg2"/>
</LinearLayout> 

strings.xml


strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">Concrete Page</string>
    <string name="btn_start"> Start </string>
    <string name="btn_stop"> Stop </string>
</resources> 

Output

Android  Alarm Clock Tutorial to Schedule and Cancel | AlarmManager, PendingIntent and WakefulBroadcastReceiver Example

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us