Android AlarmManager - Repeating/Recurring Alarms.


How to make a repeating alarm with cancellation. The alarm can ring even if the activity is not started.

Gradle Scripts.
These are the gradle scripts that we modify

[](#build.gradle(module:app)Build.Gradle(Module:App)

  • Our app level build.gradle file.
  • We specify compilesdk,minimum sdk,target sdk and dependencies.
  • Note that the minimum sdk for this project isn't that strict,it is much lower than that specified below.
  • We also add dependencies using 'compile' statement.
  • Our activity shall derive from the appCompatActivity to make it target earlier android versions.
    apply plugin: 'com.android.application'

    android {
        compileSdkVersion 26
        buildToolsVersion "26.0.0"
        defaultConfig {
            applicationId "com.tutorials.hp.repeatingalarm"
            minSdkVersion 15
            targetSdkVersion 26
            versionCode 1
            versionName "1.0"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:26.+'
        compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
        compile 'com.android.support:design:26.+'
        testCompile 'junit:junit:4.12'
    }

AndroidManifest.xml

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

        <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">
            <activity
                android:name=".MainActivity"
                android:label="@string/app_name"
                android:theme="@style/AppTheme.NoActionBar">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

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

    </manifest>

LAYOUTS

activity_main.xml

  • ActivityMain.xml.
  • This is a template layout for our MainActivity.
  • Root layout tag is CoordinatorLayout from design support library.
  • CordinatorLayout is viewgroup that is a superpowered on framelayout.
  • CoordinatorLayout is intended for two primary use cases:
    As a top-level application decor or chrome layout
    As a container for a specific interaction with one or more child views
  • Inside our CordinatorLayout we add : AppBarLayout,FloatingActionButton and include content_main.xml.
  • AppBarLayout is vertical LinearLayout that implements scrolling features of material design concept.
  • It should be a direct child of CordinatorLayout, otherwise alot of features won't work.
  • Inside the AppBarLayout we add our toolbar,which we give a blue color.
  • We will add our widgets in our content_main.xml, not here as this is a template layout.
  • Finally we have a FloatingActionButton, a class that derives from android.support.design.widget.VisibilityAwareImageButton.
    Its the round button you see in our user interface.
    <?xml version="1.0" encoding="utf-8"?>

    <android.support.design.widget.CoordinatorLayout 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="com.tutorials.hp.repeatingalarm.MainActivity">

        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay" />

        </android.support.design.widget.AppBarLayout>

        <include layout="@layout/content_main" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="@dimen/fab_margin"
            app:srcCompat="@android:drawable/ic_dialog_email" />

    </android.support.design.widget.CoordinatorLayout>

content_main.xml

  • Our ContentMain.xml file.
  • Shall get inflated to MainActivity.
  • Root tag is ConstraintLayout.
  • Contains EditTexts and two buttons.
  • User will enter the number of seconds after which alarm rings in edittext.
  • Then click start button to start alarm.
  • And Cancel button to cancel alarm.
    <?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"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:context="com.tutorials.hp.repeatingalarm.MainActivity"
        tools:showIn="@layout/activity_main">

        <LinearLayout
            android:layout_width="368dp"
            android:layout_height="327dp"
            android:orientation="vertical"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="8dp">
            <EditText
                android:id="@+id/timeTxt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentTop="true"
                android:ems="10"
                android:hint="Number of seconds"
                android:inputType="numberDecimal"
                />

            <Button
                android:id="@+id/startBtn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignRight="@+id/timeTxt"
                android:layout_below="@+id/timeTxt"
                android:text="Start"
                />
            <Button
                android:id="@+id/cancelBtn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignRight="@+id/timeTxt"
                android:layout_below="@+id/timeTxt"
                android:text="Cancel"
                />

        </LinearLayout>

    </android.support.constraint.ConstraintLayout>

MyReceiver.java

  • Our MyReceiver class.
  • Derives from android.content.BroadcastReceiver.
  • We override onReceive() method and perform task to be done when alarm rings here.
    package com.tutorials.hp.repeatingalarm;

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

    public class MyReceiver extends BroadcastReceiver {
        /*
       RING ALARM WHEN IN WHEN WE RECEIVE OUR BROADCAST
        */
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Alarm Ringing...", Toast.LENGTH_SHORT).show();
        }
    }

MainActivity.java

  • Our MainActivity class.
  • Derives from AppCompatActivity which is a Base class for activities that use the support library action bar features.
  • Methods: onCreate(),initializeViews(),initializeAlarmManager(),go().
  • Inflated From activity_main.xml using the setContentView() method.
  • The views we use are EditTexts and buttons.
  • Reference them from our layout specification using findViewById().
  • Initialize alarm manager.
  • Start alarm using the setInExactRepeating().
    package com.tutorials.hp.repeatingalarm;

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

    public class MainActivity extends AppCompatActivity {

        Button startBtn,cancelBtn;
        EditText timeTxt;
        AlarmManager alarmManager;
        PendingIntent pi;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);

             initializeViews();
             initializeAlarmManager();

            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    go();
                }
            });

        }

        /*
        INITIALIZE VIEWS
         */
        private void initializeViews()
        {
            timeTxt= (EditText) findViewById(R.id.timeTxt);
            startBtn= (Button) findViewById(R.id.startBtn);
            cancelBtn= (Button) findViewById(R.id.cancelBtn);

            startBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    go();
                }
            });
            cancelBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    if(alarmManager != null)
                    {
                        alarmManager.cancel(pi);
                    }
                }
            });
        }
        /*
        INITIALIZE AND START OUR ALARM
        */
        private void initializeAlarmManager()
        {
            // INITIALIZE INTENT
            Intent intent=new Intent(this,MyReceiver.class);

            //PASS CONTEXT,YOUR PRIVATE REQUEST CODE,INTENT OBJECT AND FLAG
            pi= PendingIntent.getBroadcast(this,0,intent,0);

            //INITIALIZE ALARM MANAGER
            alarmManager= (AlarmManager) this.getSystemService(ALARM_SERVICE);
        }

        /*
        START OUR ALARM
         */
        private void go()
        {
            //GET TIME IN SECONDS
            int time=Integer.parseInt(timeTxt.getText().toString());

            //SET THE ALARM
           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
                alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+(time*1000),time*1000,pi);
                Toast.makeText(MainActivity.this, "Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();

            }else
            {
                alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,System.currentTimeMillis()+(time*1000),time*1000,pi);
                Toast.makeText(MainActivity.this, "Yes Alarm set in "+time+" seconds", Toast.LENGTH_SHORT).show();

            }
        }

    }

How do You Feel after reading this?

According to scientists, we humans have 8 primary innate emotions: joy, acceptance, fear, surprise, sadness, disgust, anger, and anticipation. Feel free to tell us how you feel about this article using these emotes or via the comment section. This feedback helps us gauge our progress.

Help me Grow.

I set myself some growth ambitions I desire to achieve by this year's end regarding this website and my youtube channel. Am halfway. Help me reach them by:




Recommendations


What do You Think

Dear readers drop us your comments below. We are building a community of students and learners. Start by dropping us your suggestions below. What tutorials do you want us to do for example? Where can we improve? What are some awesome resources out there? Do you have any code you want to share with us?
By the way that example or snippet you have lying in your computer can really help beginner programmers. We can share it here with other students.

Previous Post Next Post