Thursday, April 30, 2015

Example of using AlarmManager to trigger BroadcastReceiver / alarmManager.set() and setExact()

A simple example of using AlarmManager to trigger a BroadcastReceiver to be called in 10 seconds later.


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.

reference: http://developer.android.com/reference/android/app/AlarmManager.html

This example also show how to determine calling set() or setExact() depends on Build.VERSION.SDK_INT. But no demo how in-exact with calling set(), because  alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.

AlarmReceiver.java
package com.example.androidalarm;

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

public class AlarmReceiver extends BroadcastReceiver {

 @Override
 public void onReceive(Context context, Intent intent) {
  
  Toast.makeText(context, 
   "AlarmReceiver.onReceive()", 
   Toast.LENGTH_LONG).show();
 }

}

activity_main.xml
<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:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.androidalarm.MainActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <Chronometer
        android:id="@+id/chronometer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <Button
        android:id="@+id/setnocheck"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Set Alarm 10 sec later - alarmManager.set()" />
    
    <Button
        android:id="@+id/setwithversioncheck"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Set Alarm 10 sec later - with SDK Version check" />

</LinearLayout>

MainActivity.java
package com.example.androidalarm;

import java.util.Calendar;
import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.Toast;


public class MainActivity extends ActionBarActivity {
 
 Chronometer chronometer;
 Button btnSetNoCheck, btnSetWithVerCheck;
 final static int RQS_1 = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        chronometer = (Chronometer)findViewById(R.id.chronometer);
        btnSetNoCheck = (Button)findViewById(R.id.setnocheck);
        btnSetNoCheck.setOnClickListener(onClickListener);
        btnSetWithVerCheck = (Button)findViewById(R.id.setwithversioncheck);
        btnSetWithVerCheck.setOnClickListener(onClickListener);
    }
    
    @SuppressLint("NewApi") 
    OnClickListener onClickListener = new OnClickListener(){

  @Override
  public void onClick(View v) {
   chronometer.setBase(SystemClock.elapsedRealtime());
      chronometer.start();
      
      //10 seconds later
      Calendar cal = Calendar.getInstance();
      cal.add(Calendar.SECOND, 10);
      
      Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
      PendingIntent pendingIntent = 
       PendingIntent.getBroadcast(getBaseContext(), 
         RQS_1, intent, PendingIntent.FLAG_ONE_SHOT);
      AlarmManager alarmManager = 
       (AlarmManager)getSystemService(Context.ALARM_SERVICE);
      
      if(v==btnSetNoCheck){
       alarmManager.set(AlarmManager.RTC_WAKEUP, 
        cal.getTimeInMillis(), pendingIntent);
       Toast.makeText(getBaseContext(), 
        "call alarmManager.set()", 
        Toast.LENGTH_LONG).show();
      }else{
       if(Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
       {
        alarmManager.set(AlarmManager.RTC_WAKEUP, 
         cal.getTimeInMillis(), pendingIntent);
        Toast.makeText(getBaseContext(), 
         "call alarmManager.set()", 
         Toast.LENGTH_LONG).show();
       }else{
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, 
         cal.getTimeInMillis(), pendingIntent);
        Toast.makeText(getBaseContext(), 
         "call alarmManager.setExact()", 
         Toast.LENGTH_LONG).show();
       }
      }
      
  }
     
    };

}

Need to modify AndroidManifest.xml to add <receiver android:name=".AlarmReceiver" android:process=":remote" />
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidalarm"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="22" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <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" android:process=":remote" />
    </application>

</manifest>


download filesDownload the files.

1 comment:

Unknown said...

Thankyou for your tutorial, it is very usefull for me and it works..
I want to ask. in this tutorial you set the time for 10 seconds.
how about if i want the time for 1 hour or 1 week?
I'm already try for 1 hour, i add the code like this:
cal.add(Calendar.HOUR, 1):
but the results is strange, the notification sometimes didn't out, even it is come but then dissappear very fast..
can you help me?

Regards,