10 min read

In this tutorial, we will discuss adding finishing touches to your Android app before you release it to the play store such as using the Android 6.0 Runtime permission model, scheduling an alarm,  receiving notification of a device boot, Using AsyncTask for background work recipe, adding speech recognition to your app,  and adding Google sign-in to your app.

This tutorial is an excerpt taken from the book ‘Android 9 Development Cookbook – Third Edition’, written by Rick Boyer. The book explores more than 100 proven industry standard recipes and strategies to help you build feature-rich and reliable Android Pie apps.

The Android 6.0 Runtime Permission Model

The old security model was a sore point for many in Android. It’s common to see reviews commenting on the permissions an app requires. Sometimes, permissions were unrealistic (such as a Flashlight app requiring internet permission), but other times, the developer had good reasons to request certain permissions. The main problem was that it was an all-or-nothing prospect.

This finally changed with the Android 6 Marshmallow (API 23) release. The new permission model still declares permissions in the manifest as before, but users have the option of selectively accepting or denying each permission. Users can even revoke a previously granted permission.

Although this is a welcome change for many, for a developer, it has the potential to break the code that was working before. Google now requires apps to target Android 6.0 (API 23) and above to be included on the Play Store. If you haven’t already updated your app, apps not updated will be removed by the end of the year (2018).

Getting ready

Create a new project in Android Studio and call it RuntimePermission. Use the default Phone & Tablet option and select Empty Activity when prompted for Activity Type.

The sample source code sets the minimum API to 23, but this is not required. If your compileSdkVersion is API 23 or above, the compiler will flag your code for the new security model.

How to do it…

We need to start by adding our required permission to the manifest, then we’ll add a button to call our check permission code. Open the Android Manifest and follow these steps:

  1. Add the following permission:

  1. Open activity_main.xml and replace the existing TextView with this button:

  1. Open MainActivity.java and add the following constant to the class:
private final int REQUEST_PERMISSION_SEND_SMS=1;
  1. Add this method for a permission check:
private boolean checkPermission(String permission) { 
    int permissionCheck = 
         ContextCompat.checkSelfPermission( 
            this, permission); 
    return (permissionCheck == 
         PackageManager.PERMISSION_GRANTED); 
}
  1. Add this method to request permission:
private void requestPermission(String permissionName, int permissionRequestCode) {    
    ActivityCompat.requestPermissions(this, new String[]{permissionName}, 
            permissionRequestCode);
}
  1. Add this method to show the explanation dialog:
private void showExplanation(String title, String message, 
                             final String permission, 
                             final int permissionRequestCode) {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(title)
            .setMessage(message)
            .setPositiveButton(android.R.string.ok,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface    
                        dialog,int id) 
{
                            requestPermission(permission,    
                            permissionRequestCode);
                        }
                    });
    builder.create().show();
}
  1. Add this method to handle the button click:
public void doSomething(View view) {
    if (!checkPermission(Manifest.permission.SEND_SMS)) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, 
                Manifest.permission.SEND_SMS)) {
            showExplanation("Permission Needed", "Rationale",
                    Manifest.permission.SEND_SMS, REQUEST_PERMISSION_SEND_SMS);
        } else {
            requestPermission(Manifest.permission.SEND_SMS,
                    REQUEST_PERMISSION_SEND_SMS);
        }
    } else {
        Toast.makeText(MainActivity.this, "Permission (already) 
        Granted!", Toast.LENGTH_SHORT)
                .show();
    }
}
  1. Override onRequestPermissionsResult() as follows:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], 
                                       int[] grantResults) {
    switch (requestCode) {
        case REQUEST_PERMISSION_SEND_SMS: {
            if (grantResults.length > 0 && grantResults[0] ==
                    PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(MainActivity.this, "Granted!", Toast.LENGTH_SHORT)
                        .show();
            } else {
                Toast.makeText(MainActivity.this, "Denied!", Toast.LENGTH_SHORT)
                        .show();
            }
            return;
        }
    }
}
  1. Now, you’re ready to run the application on a device or emulator.

How it works…

Using the new Runtime Permission model involves the following:

  1. Check to see whether you have the desired permissions
  2. If not, check whether we should display the rationale (meaning that the request was previously denied)
  3. Request the permission; only the OS can display the permission request
  4. Handle the request response

Here are the corresponding methods:

  • ContextCompat.checkSelfPermission
  • ActivityCompat.requestPermissions
  • ActivityCompat.shouldShowRequestPermissionRationale
  • onRequestPermissionsResult
Even though you are requesting permissions at runtime, the desired permission must be listed in the Android Manifest. If the permission is not specified, the OS will automatically deny the request.

How to schedule an alarm

Android provides AlarmManager to create and schedule alarms. Alarms offer the following features:

  • Schedule alarms for a set time or interval
  • Maintained by the OS, not your application, so alarms are triggered even if your application is not running or the device is asleep
  • Can be used to trigger periodic tasks (such as an hourly news update), even if your application is not running
  • Your app does not use resources (such as timers or background services), since the OS manages the scheduling

Alarms are not the best solution if you need a simple delay while your application is running (such as a short delay for a UI event.) For short delays, it’s easier and more efficient to use a Handler, as we’ve done in several previous recipes.

When using alarms, keep these best practices in mind:

  • Use as infrequent an alarm timing as possible
  • Avoid waking up the device
  • Use as imprecise timing as possible; the more precise the timing, the more resources required
  • Avoid setting alarm times based on clock time (such as 12:00); add random adjustments if possible to avoid congestion on servers (especially important when checking for new content, such as weather or news)

Alarms have three properties, as follows:

  • Alarm type (see in the following list)
  • Trigger time (if the time has already passed, the alarm is triggered immediately)
  • Pending Intent

A repeating alarm has the same three properties, plus an Interval:

  • Alarm type (see the following list)
  • Trigger time (if the time has already passed, it triggers immediately)
  • Interval
  • Pending Intent

There are four alarm types:

  • RTC (Real Time Clock): This is based on the wall clock time. This does not wake
    the device.
  • RTC_WAKEUP: This is based on the wall clock time. This wakes the device if it
    is sleeping.
  • ELAPSED_REALTIME: This is based on the time elapsed since the device boot.
    This does not wake the device.
  • ELAPSED_REALTIME_WAKEUP: This is based on the time elapsed since the
    device boot. This wakes the device if it is sleeping.

Elapsed Real Time is better for time interval alarms, such as every 30 minutes.

Alarms do not persist after device reboots. All alarms are canceled when a device shuts down, so it is your app’s responsibility to reset the alarms on device boot.

The following recipe will demonstrate how to create alarms with AlarmManager.

Getting ready

Create a new project in Android Studio and call it Alarms. Use the default Phone & Tablet option and select Empty Activity when prompted for Activity Type.

How to do it…

Setting an alarm requires a Pending Intent, which Android sends when the alarm is triggered. Therefore, we need to set up a Broadcast Receiving to capture the alarm intent. Our UI will consist of just a simple button to set the alarm. To start, open the Android Manifest and follow these steps:

  1. Add the following <receiver> to the <application> element at the same level as the existing <activity> element:

  1. Open activity_main.xml and replace the existing TextView with the
    following button:

  1. Create a new Java class called AlarmBroadcastReceiver using the following code:
public class AlarmBroadcastReceiver extends BroadcastReceiver {    
    public static final String ACTION_ALARM= "com.packtpub.alarms.ACTION_ALARM";

    @Override
    public void onReceive(Context context, Intent intent) {
        if (ACTION_ALARM.equals(intent.getAction())) {
            Toast.makeText(context, ACTION_ALARM, Toast.LENGTH_SHORT).show();
        }
    }
}
  1. Open ActivityMain.java and add the method for the button click:
public void setAlarm(View view) {
    Intent intentToFire = new Intent(getApplicationContext(), AlarmBroadcastReceiver.class);
    intentToFire.setAction(AlarmBroadcastReceiver.ACTION_ALARM);
    PendingIntent alarmIntent = PendingIntent.getBroadcast(getApplicationContext(), 0,
            intentToFire, 0);
    AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    long thirtyMinutes=SystemClock.elapsedRealtime() + 30 * 1000;
    alarmManager.set(AlarmManager.ELAPSED_REALTIME, thirtyMinutes, alarmIntent);
}
  1. You’re ready to run the application on a device or emulator.

How it works…

Creating the alarm is done with this line of code:

alarmManager.set(AlarmManager.ELAPSED_REALTIME, thirtyMinutes, 
     alarmIntent);

Here’s the method signature:

set(AlarmType, Time, PendingIntent);
Prior to Android 4.4 KitKat (API 19), this was the method to request an exact time. Android 4.4 and later will consider this as an inexact time for efficiency, but will not deliver the intent prior to the requested time. (See setExact() as follows if you need an exact time.)

To set the alarm, we create a Pending Intent with our previously defined alarm action:

public static final String ACTION_ALARM= "com.packtpub.alarms.ACTION_ALARM";

This is an arbitrary string and could be anything we want, but it needs to be unique, so we prepend our package name. We check for this action in the Broadcast Receiver’s onReceive() callback.

There’s more…

If you click the Set Alarm button and wait for thirty minutes, you will see the Toast when the alarm triggers. If you are too impatient to wait and click the Set Alarm button again before the first alarm is triggered, you won’t get two alarms. Instead, the OS will replace the first alarm with the new alarm, since they both use the same Pending Intent. (If you need multiple alarms, you need to create different Pending Intents, such as using different Actions.)

Cancel the alarm

If you want to cancel the alarm, call the cancel() method by passing the same Pending Intent you have used to create the alarm. If we continue with our recipe, this is how it would look:

alarmManager.cancel(alarmIntent);

Repeating alarm

If you want to create a repeating alarm, use the setRepeating() method. The Signature is similar to the set() method, but with an interval. This is shown as follows:

setRepeating(AlarmType, Time (in milliseconds), Interval, PendingIntent);

For the Interval, you can specify the interval time in milliseconds or use one of the predefined AlarmManager constants:

  • INTERVAL_DAY
  • INTERVAL_FIFTEEN_MINUTES
  • INTERVAL_HALF_DAY
  • INTERVAL_HALF_HOUR
  • INTERVAL_HOUR

Receiving notification of device boot

Android sends out many intents during its lifetime. One of the first intents sent is ACTION_BOOT_COMPLETED. If your application needs to know when the device boots, you need to capture this intent.

This recipe will walk you through the steps required to be notified when the device boots.

Getting ready

Create a new project in Android Studio and call it DeviceBoot. Use the default Phone & Tablet option and select Empty Activity when prompted for Activity Type.

How to do it…

To start, open the Android Manifest and follow these steps:

  1. Add the following permission:

  1. Add the following <receiver> to the <application> element, at the same level as the existing <activity> element:

  1. Create a new Java class called BootBroadcastReceiver using the following code:
public class BootBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(
                "android.intent.action.BOOT_COMPLETED")) {            
            Toast.makeText(context, "BOOT_COMPLETED", Toast.LENGTH_SHORT).show();
        }
    }
}
  1. Reboot the device to see the Toast.

How it works…

When the device boots, Android will send the BOOT_COMPLETED intent. As long as our application has the permission to receive the intent, we will receive notifications in our Broadcast Receiver.

There are three aspects to make this work:

  • Permission for RECEIVE_BOOT_COMPLETED
  • Adding both BOOT_COMPLETED and DEFAULT to the receiver intent filter
  • Checking for the BOOT_COMPLETED action in the Broadcast Receiver

Obviously, you’ll want to replace the Toast message with your own code, such as for recreating any alarms you might need.

Thus, in this article, we looked at different factors that need to be checked off before your app gets ready for the play store.  We discussed three topics: Android 6.0 Runtime permission model, scheduling an alarm and detecting a device reboot.  If you found this post useful, be sure to check out the book ‘Android 9 Development Cookbook – Third Edition’, to learn about using AsyncTask for background work recipe, adding speech recognition to your app,  and adding Google sign-in to your app.

Read Next

Building an Android App using the Google Faces API [ Tutorial]

How Android app developers can convert iPhone apps

6 common challenges faced by Android App developers

Tech writer at the Packt Hub. Dreamer, book nerd, lover of scented candles, karaoke, and Gilmore Girls.