Mike Korcha

Blog

This is a continuation on my post about updating to O in development from...far too long ago...

Updating to Android Oreo Continued

After a bug report and a bit of free time, I decided to get Media Button Overlay finally published and up to par with the latest API upgrades. Some things from the Developer Preview changed, so I decided to document the couple of changes needed to get things fully operational again.

Bumping the API Version

The obvious easy change - changing the compileSdkVersion, buildToolsVersion, and targetSdkVersion in my Gradle build file:

android {
    compileSdkVersion 27
    buildToolsVersion "27.0.1"

    // ...

    defaultConfig {
        // ...
        minSdkVersion 14
        targetSdkVersion 27
        // ...
    }
}

I also had to update the Gradle version and support library versions, but Android Studio handled this for me already.

Starting the Service

The startServiceInForeground method of the NotificationManager was removed. Luckily, something a bit more straightforward was added to Context instead: startForegroundService. It's like startService, but requiring that foreground service promotion happens within an ANR interval.

..

On that note, I moved foreground promotion to the service onStartCommand:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    startForeground(NOTIFICATION_ID, MainActivity.getForegroundNotification(this));
    return START_NOT_STICKY;
}

Notification Channel

Android Oreo also requires that notifications be added to a channel. I either overlooked this entirely in the first developer preview or it wasn't made apparent/wasn't a thing at the time. A notification channel helps the system categorize notifications properly in the shade, and are created by the developer at execution.

// ...
if(Build.VERSION.SDK_INT >= 26) {
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    NotificationChannel channel = new NotificationChannel(getPackageName(), "Media Button Overlay", NotificationManager.IMPORTANCE_LOW);
    channel.setDescription("Persisting notifications for Media Button Overlay");
    channel.enableLights(false);
    channel.enableVibration(false);
    manager.createNotificationChannel(channel);
}
// ...

I do this at app start. Creating a notification channel, then attempting to recreate it just uses the existing one, so no excess channels are created.

I had to switch from the NotificationCompat builder to the standard Notification builder. This is so I can add the channel ID properly to the notification when it is launched. This is done with the setChannelId method. I also modified it to work properly for lower supported Android versions, as I don't want to modify the minimum requirements. Here is the snippet:

// ...
Notification.Builder builder = new Notification.Builder(context)
        .setSmallIcon(R.drawable.ic_notification)
        .setContentTitle(context.getResources().getString(R.string.app_name))
        .setContentText(context.getResources().getString(text_resource))
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)
        .setOngoing(true);
if(Build.VERSION.SDK_INT < 26) {
    builder.setPriority(Notification.PRIORITY_LOW);
}
else {
    builder.setChannelId(context.getPackageName());
}
if(Build.VERSION.SDK_INT < 16) {
    return builder.getNotification();
}
return builder.build();

Final Thoughts

I should probably pay more attention to final release notes, or changes between developer previews, as it was a bit frustrating to have to change some more things around. Regardless, fixing it up was much less painful than the initial change was. A copy of my diff for Media Button Overlay can be found here (again, ignore IDE files).


  • development
  • android
  • media-button-overlay
Written 2017-11-20