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
- 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 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 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 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(); } } }