Android O Developer Preview Teardown, For The Developers!

Aritra Roy
Aritra's Musings
Published in
11 min readApr 9, 2017

--

Google have recently introduced the Android O Developer Preview and as it is with every other Android update, we are excited. We don’t know what ‘O’ is going to stand for (Oreo? or Oatmeal Pie?) but what we do know is that there are lots of new features, improvements and API changes that this update brings to the developers.

If you are excited just like me and can’t wait to get your hands on all the new stuff that Android O brings to the table, then you are absolutely at the right place. In this article, we are going to discuss all the important features and changes in Android O and how you can benefit from it. So without wasting any time further, let’s get started.

Dive Into The Picture-In-Picture Mode

If you remember, Google introduced the picture-in-picture mode for the Android TV users back in Android Nougat itself, in which the user could pin a particular video at one corner of the screen while navigating between different apps.

This significantly improved the multitasking experience of the user as they could consume the media content simultaneously while browsing or navigating other apps. But unfortunately, this cool feature was only available on the Android TV platform until now when Android O introduces it with all its glory for the mobile and tablet platforms as well.

Previously, developers were quite reluctant to implement this feature as it was only available on Android TV and as we all know how tiny the Android TV marketplace is in comparison to that of the phones and tablet marketplace.

Schematic representation of the picture-in-picture mode

But now it is the perfect time for us to start exploring this feature in deeper detail with its introduction to all Android devices with Android O. If you have an app with video playback, image slideshow or anything of that sort, then you must give it a try.

Implementing this feature is pretty straightforward as well. You need to declare an attribute, android:supportsPictureInPicture to true in your AndroidManifest for the particular Activity to enable PIP for it. Previously before Android O, you also needed to add the android:resizableActivity to true but now that is not mandatory.

<activity android:name="VideoPlaybackActivity"
android:supportsPictureInPicture="true"
...>

Now your Activity knows that it needs to support the PIP mode, but that’s not enough. You need to manually call enterPictureInPictureMode()when you want your users to enter the mode. You can also customize the way the PIP frame looks and works (like aspect ratio, actions, etc.) by passing the PictureInPictureArgs to the enterPictureInPictureMode() method.

There are a few gotchas though. In PIP mode, you need to remove several UI elements from your Activity as the PIP window is quite tiny in size (240x135dp). You also need to seamlessly restore those hidden UI elements when the user exits the PIP mode to give a consistent user experience. To get this working, you can use the handy onPictureInPictureModeChanged(boolean) callback.

@Override
public void onPictureInPictureModeChanged(boolean isInPIPMode) {
if (isInPIPMode) {
// Hide the controls in picture-in-picture mode
...
} else {
// Restore the UI elements again
...
}
}

Another important thing that you shouldn’t miss is that when your Activity enters the PIP mode, the onPause() lifecycle method is called and your Activity is actually in the “paused” state. We generally tend to pause any media playback in onPause(), but it defeats the whole purpose of the PIP mode, isn’t it?

So from now on, instead of pausing any media playback in onPause() you should do it in onStop(). But if your application logic still forces you to pause the playback in onPause(), there are better ways to do that without messing up the PIP mode.

@Override
public void onPause() {
// Do not pause playback in PIP mode
if (isInPictureInPictureMode()) {
...
} else {
// It is safe to pause the playback
...
}
}

If you want to check a working sample using the picture-in-picture mode, then here is a Github repo you should definitely check out.

Start Using The New Notification Channels

Google has been changing the notification system starting from Lollipop and they are not done yet. With every Android release, new features and enhancements are brought to the notification system to make things more easy and simple for the users.

Android O introduces the notification channels, giving more power to the users for managing their notifications in a more convenient and efficient way. The control is now moved from individual notifications to a group or channel of notifications.

And if you think carefully, it is really good from a developers point of view as well. Previously, users could completely block your app from showing any notification if they got annoyed with your frequent promotional notifications or something of that sort (you know what I mean). But now if they get annoyed with your app’s promotional notifications, they can block that particular channel leaving all other channels untouched.

Your app can create as many notification channels as necessary using the straightforward createNotificationChannel() method.

You can also customize this notification channel in any way you want. Here is a quick example for you to get started.

NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// The identifier of the channel
String id = ...;
// The user visible name of the channel
CharSequence name = ...;
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(id, name, importance);// Configure the notification channel
channel.enableLights(true);
channel.setLightColor(Color.RED);
channel.enableVibration(true);
notificationManager.createNotificationChannel(channel);

Android O onwards, if you want to send a notification, you must set a channel for that notification using the channel identifier and you are good to go. Remember, all notification must belong to a channel for which it makes the most sense.

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// Sets an id for the notification, so it can be updated.
int notiId = 1;
// The id of the channel it should belong to
String CHANNEL_ID = ...;
// Create a notification and set the notification channel
Notification notification = new Notification.Builder(this)
.setContentTitle("Message")
.setContentText("Content")
.setSmallIcon(R.drawable.ic_noti)
.setChannel(CHANNEL_ID)
.build();
// Send the notification
notificationManager.notify(notiId, notification);

Now all the notifications you send from your app get properly categorized into their appropriate channels. Users can customize the behavior of any channel (lights, sounds, vibration, etc.) or block a particular channel completely if they really want to.

Apps don’t have the permission to programmatically change the settings of a notification channel or override the choices made by the user, but you can always read the settings of any channel using the getNotificationChannel() API.

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// Get access to a particular notification
NotificationChannel notificationChannel = notificationManager.getNotificationChannel(“CHANNEL_ID”);
// Or the list of all notification channels your app has created
List<NotificationChannel> notificationChannels = notificationManager.getNotificationChannels();

Managing notifications (for both users and developers) would be so much better with the introduction of this feature. If you want your app to target the latest Android O, then make sure to implement these changes as necessary.

Save Time With The New AutoFill Framework

If you have ever used apps like LastPass, DashLane, 1Password then you have seen autofilling in action. But the problem is that this autofilling mechanism needs to be built by all apps individually and it is not a trivial thing to do as well.

But now Android O brings the all-new shiny Autofill Framework which can make it super easy for apps to autofill usernames, passwords, emails, credit card details or any other form related data with ease. Though this feature might not be useful to all kinds of apps out there, but for those who do need this, this can prove to be a life-saver.

To start using this feature, your app needs to have an autofill service which can parse the client Activity’s View hierarchy, find the autofill-able views and fill those views which the framework has appropriate data for.

1Password demonstrating the Autofill Framework

But if you are targeting Android O and you want your app’s views to be detected and auto-filled by the Autofill Framework, then you might need to do some extra work. If you are using Android’s standard Views and ViewGroups then you don’t need to do anything extra to get the autofill feature work automatically for your app.

But if you wrote some fancy custom view, then you need to expose some metadata that the Autofill Framework needs to work its magic. Whenever your custom view is autofilled, an autofill event is triggered and this is when your custom view should know how to handle this autofilled data by appropriately overriding the autoFill(AutoFillValue).

Your custom view should also override getAutoFillType() and getAutoFillValue() to tell the framework what type of view it actually is and what its current autofillable value is.

Here is a complete working sample for you to get started with the new AutoFill Framework.

More Battery Life Improvements

We know how serious Google is getting when it comes to the battery life of the Android devices. The Doze Mode introduced in Marshmallow brought a significant improvement in the battery life of our devices. This was enhanced and fine-tuned further in the Extended Doze Mode introduced in Android Nougat.

Android O will be bringing even more battery improvements by tapping into how various apps consume battery while they are in the background. Now apps running in the background will have limited access to what they can do mainly in three areas — background services, implicit broadcasts and location updates, which by far are the most notorious culprits in draining battery. Well played, Google!

There are limitations imposed on background services restricting them to run for a window of a few minutes only (if your app is not in the foreground) after which they are essentially stopped preventing any further battery abuse. An obvious solution to avoid this limitation would be to use the JobScheduler as much as possible. The JobScheduler is quite smart in scheduling jobs and batching them intelligently so that your device can enjoy a sound sleep for a longer period of time. Here is an excellent article that can help you make the necessary changes for Android O.

We already knew that there were some restrictions placed on Broadcast Receivers in Android Nougat, but Android O makes them even more strict. Now you cannot register implicit broadcasts in your app’s manifest (except for a few). You have to do that programmatically while your app is running using the registerReceiver() method. All explicit broadcasts are fine though.

This is a very judicious decision as there are lots of unnecessary broadcasts sent to apps which don’t even need to listen to them at the current moment, thereby wasting a lot of battery juice.

There are also some restrictions imposed on how apps fetch location updates while in the background. If your app is in the background then it cannot retrieve location updates more than a few times per hour (the exact number will be decided before the final release). And this restriction is applicable to all apps irrespective of their target SDKs. This might sound a bit scary for some apps for sure.

If you need to receive faster location updates, consider moving your app to the foreground, or use a foreground service or use the GeoFencingApi which is quite well-optimized for battery consumption.

Get Started With Adaptive Icons

As the name suggests, Google is trying to create icons for apps which can have different shapes for different devices and OEMs. For example, your app can have a square icon on a Samsung Galaxy S7 and a rounded icon on a Nexus 5X.

The idea here is that each device would provide a mask which can be used by the operating system to render icons of different shapes. This will allow OEMs to have unique looking home screens quite easily. As I see, it is the first baby step from Google towards a native theme engine (which was always present on custom ROMs like CynogenMod).

These adaptive app icons can be used in the app shortcuts, inside the Settings app, in the sharing dialogs or the overview screen. The adaptive icons can also support various visual effects (like zoom, bounce, etc.) when the user interacts with them.

Implementing adaptive icons in your app is pretty simple. All you need to do is create a maskable icon and specify two layers in it — the foreground and background layer.

<maskable-icon>
<background android:drawable="@color/ic_background"/>
<foreground android:drawable="@mipmap/ic_foreground"/>
</maskable-icon>

This is a very impressive and welcoming step by Google trying to create a unified icon language.

A Bit More On Android O

We have already discussed some of the major features and changes introduced in Android O, but that’s not all. There are several small but interesting and important changes introduced in Android O that must know.

Till now, we needed to use 3rd-party libraries (like Calligraphy) if we wanted to have custom fonts in our app. But with Android O, you will have native support for fonts as resources in your app. Thank you Google for bringing this finally. It could have been done before, but better late than never.

And there are also talks about brining it to the support library as well. Don’t throw away Calligraphy from your project till then.

Another notable introduction is the Autosizing TextView. This can come in handy when you have dynamic content on the screen and you want your text to expand or contract depending on the screen space available on the device. You probably have been using this “autosizing” feature through 3rd-party libraries before, but now it’s built-in Android itself.

If you have a photo gallery like application where you need to show images of various color spaces accurately, then there is a good news for you. From Android O, image color space will not be limited to sRGB only and applications will be able to display Adobe RGB, ProPhoto RGB and other color spaces properly. You can also convert between different color spaces easily,

// Convert from sRGB to AdobeRGB
ColorSpace.Connector connector = ColorSpace.connect(
ColorSpace.get(ColorSpace.Named.SRGB),
ColorSpace.get(ColorSpace.Named.ADOBE_RGB));
float[] adobeRGB = connector.transform(r, g, b);

If you have been using the Accessibility Services in your app, then there are quite a lot of additions in Android O that you might want to look at like the dedicated accessibility button in the navigation bar, fingerprint gestures, word highlighting, and much more.

The AnimatorSet also brought a very cool change allowing you to seek and reverse animations. You are welcome to get a bit more creative with animations from now.

Last but not the least, they have introduced a new permission, android.permission.ANSWER_PHONE_CALLS which can allow apps to programmatically answer incoming phone calls. Now just imagine the different utility apps we can build using this cool feature.

Android O certainly brings quite a lot of new features and improvements for the developers to play with. These APIs are obviously not final and can change before the final release of Android O, but it gives us a good idea of what Android O is going to be like and some time for us to start making our apps ready before the new dessert is finally served.

If you have found this useful, then please consider recommending and sharing it with your friends and other developers. This article was originally published on TechBeacon.

Click the 💚 below to show your support and share it with other fellow Medium users.

--

--

Design-focused Engineer | Android Developer | Open-Source Enthusiast | Part-time Blogger | Catch him at https://about.me/aritra.roy