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.