What’s New for Android Oreo and the impact on Zebra developers

Anonymous (not verified) -
28 MIN READ
430
3

This document details the developer impact of moving to Zebra devices running Android 8.x Oreo (API levels 26 & 27), and is follow-up to my previous posts about preparing for Android Marshmallow (API level 23) and preparing for Android Nougat (API levels 24 & 25). If you are moving from Marshmallow directly to Oreo, I recommend you read the documents in sequence since all the information related to Nougat (e.g. notifications or doze light) is also pertinent to Oreo.

 

Audience for this document

Zebra's new PS20, TC52/57​ and TC72/77 devices will ship with Oreo pre-installed and much of Zebra’s existing portfolio of devices will receive the Oreo update. Any developers targeting deployments featuring at least one Oreo device or devices which will be updated to Oreo should be aware of the changes detailed here. Since Zebra devices are shipping with Android Oreo 8.1 (API 27) this document does not distinguish between 8.0 (API 26) and 8.1

 

Overview

Along with the usual raft of feature additions, there have been some fundamental behavioural changes implemented in Oreo to restrict what applications can do in the background. This will come as little surprise to developers now familiar with the pattern started with Doze mode in Marshmallow. It is important to understand this to ensure applications continue to function as expected after the ‘O’ update. Google has published an overview of the Oreo changes on its developer portal for 8.0 and 8.1 with more detail available for Android 8.0 behavior changes including background execution and location limitations. This document does not replace recommendations from Google, but is designed to supplement those recommendations for enterprise use-cases.

 

Background Limitations

The most impactful changes in Android Oreo for developers are the limitations placed on what an application can do in the background. Google provides some detailed developer documentation on execution and location restrictions and it is important to appreciate the scope of the changes, the possible impact to enterprise developers and ways to mitigate the limitations. These changes continue a pattern first established in Android Marshmallow with Doze mode, that is to enhance battery life at the expense of what an application can do in the background and we see this trend continuing into Android Pie, so it is always best to work with the changes rather than against them where possible.

 

Terminology

For clarity, it is worth defining some terms up front

 

Foreground / Background application

For the purposes of Oreo background limitations, there is a specific definition of what a background application is, and when it is considered to be in the foreground. An application is in the foreground when:

  • It has a visible activity, whether the activity is started or paused
  • It has a foreground service (see next section)
  • Another foreground application is connected to the app, either by binding to one of its services or by making use of one of its content providers.
    • If an app exposes a bindable service (Google uses the WallpaperService and NotificationListenerService as examples) and a visible application binds to the service, then the application that exposes the service is also considered to be in the foreground.
    • Similarly, if an app exposes a content provider, any visible application that makes use that provider will cause both applications to be considered to be in the foreground.

 

Foreground service

A foreground service is an Android service that the user should be actively aware of, and therefore it must present a notification to the user that cannot be dismissed without stopping or removing the underlying service. The most common example is the music player; the user should be aware there is music playing and it makes sense to offer controls in the notification to skip the track or pause the music.

 

Figure 1: Foreground service notification icon

Figure 2: Foreground service notification expanded

 

Notice the notification is present until the music player is dismissed. While it can be tempting to use a foreground service to circumvent background restrictions, care should be taken to avoid providing a negative experience for users. Unless the application is running in lock task mode or immersive mode on older devices, the user will have to contend with a persistent notification that could distract from genuine notifications that need immediate action. As an aside, even lock task mode is not a fool proof solution moving forward, as Pie will allow notifications to be shown during this mode.

 

Background activity option

Google has introduced an option in Oreo in the Settings --> Apps and notifications --> See all Apps --> <Application> --> Battery --> Manage battery usage section.

 

When enabled (the default for apps targeting API 25), this option will cause the application NOT to be subject to background processing limitations when running on Oreo. When disabled (requires manual user intervention), the application will be subject to background processing limitations when running on Oreo.

This option will show up only if:

  • The application was built to target API level 25 or below (For more discussion around the implications of targeting a lower API level, see the 'Changes to the Google Play Store' later in this document)
  • The application has a background service
  • The application is not running on an emulator
  • (There may be other conditions)

The following screenshot highlights the setting for Snapchat, an application notorious for shipping with a low API level to avoid recent Android restrictions.

 

 

Figure 3: The Background activity option

 

You can prevent the user from modifying this setting by preventing access to the settings screen (Access Manager) or the app_info screen (Application Manager), as explained in my previous post about locking down your device. It is recommended that you prevent users from modifying this setting to avoid applications’ functionality being restricted.

 

Limitation: Receiving implicit broadcast intents declared in the manifest

Implicit broadcast intents whose broadcast receiver is declared in the app manifest will no longer be received by an application that targets API 26+ running on Android Oreo or greater. Non-broadcast intents such as those passed to StartActivity or StartService are unaffected.

An implicit intent is any intent that lacks either a package name or a component class name, some examples:

 

Explicit intent:

Intent intent = new Intent(this, SecondActivity.class);

 

Implicit intent:

Uri uri = Uri.parse(“geo:0,0?q=London”);

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

 

Explicit intent:

Uri uri = Uri.parse(“geo:0,0?q=London”);

Intent intent = new Intent(Intent.ACTION_VIEW, uri);

Intent.setPackage(“com.google.android.apps.maps”);

 

Explicit broadcast intents are unaffected and the example the Android docs use is ACTION_MY_PACKAGE_REPLACED which is only sent to the app whose package was replaced, meaning you can register to receive that intent in your manifest.

 

Registering the broadcast receiver in the application manifest will look something like the following:

<receiver android:name=".WifiReceiver" >

   <intent-filter>

     <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />

   </intent-filter>

</receiver>

 

When the Wi-Fi state changes, the WifiManager will send an implicit broadcast intent to all registered receivers, in this case the application’s ‘WifiReceiver’ class.

 

Since it is declared in the manifest, the WifiReceiver class will no longer be called for applications targeting API26+ running on Android Oreo or greater

 

There is an exemption list on Google’s developer site that lists the implicit broadcasts which are not subject to this restriction, for example ACTION_BOOT_COMPLETED, for which there are good reasons for applications to receive them while not running. At the time of this writing, no new exceptions had been added for Android Pie, so I would not expect this list to expand much moving forward.

 

Enterprise implications

Registering implicit broadcast intents in the manifest used to be a reasonably common practice, particularly for apps developed prior to the ‘O’ developer preview. Many applications (not just those built for enterprise) could therefore be affected.

There are a couple of Zebra utilities that expose the ability to create implicit intents; these will no longer be received by a receiver declared in the manifest:

  • DataWedge can be configured to send an implicit broadcast intent whenever a barcode is scanned:

Figure 4: Implicit intents sent by DataWedge

 

  • If the MX Intent CSP is configured to send a broadcast intent as shown in Figure 5, the resultant intent will be implicit. The Intent CSP is callable only from StageNow and not from EMDK.

Figure 5: Implicit intents sent by StageNow

 

 

Mitigation

If you currently register to receive an implicit broadcast intent in your manifest, your options moving forward are as follows:

  1. Move the broadcast registration out of your application manifest and replace it with code to dynamically register or unregister (e.g. during onPause / onResume). To extend the previous example, you could register for WIFI_STATE_CHANGED as follows:
private final BroadcastReceiver receiver = new BroadcastReceiver() {

   @Override

   public void onReceive(Context context, Intent intent) {

      String action = intent.getAction();

      // Handle intent

   }

};

//  onResume

IntentFilter filter = new IntentFilter();

filter.addAction("android.net.wifi.WIFI_STATE_CHANGED");

registerReceiver(receiver, filter);

 

//   onPause

unregisterReceiver(receiver);

 

You can get more creative with this. For example, if you wanted to persist the receiver when the app was in the background, you could add the BroadcastReceiver to a ForegroundService.

 

  1. If you have control over the application sending the implicit intent, consider changing it to an explicit intent. While easy to do in theory, in practice many broadcast intents are designed to be received by multiple applications (hence the name) so this option will only work in the minority of cases.
  2. Continue to target your application with API level 25 or below. Obviously this would mean you do not have access to any of the new Oreo APIs, but it does exclude your application from the restriction. This should not be seen as a long-term solution for a variety of reasons, most notably that Google is going to start enforcing applications to move to “recent API levels” from late 2018. Another good reason not to rely on targeting an earlier Android API is because the user is offered an option to re-enable the restriction from the Oreo settings screen for any application, regardless of target API level. This is the same ‘Background activity’ setting discussed previously.
  3. Google suggests “using a scheduled job to check for the condition that would have triggered the implicit broadcast”. To carry on the earlier example about receiving WIFI_STATE_CHANGED, if you did not need to know this information immediately, you could create a periodic job to run whenever the device is connected to Wi-Fi, and when the job runs, use WifiManager to determine which type of network the device is connected to. Whether this option is appropriate to you will depend heavily on your application logic and what information the intent is delivering.

 

Limitation: Running services in the background

Background applications built with API level 26 or higher and Android services associated with those background applications are subject to several limitations under Oreo to improve battery life and RAM usage. This includes IntentServices and PendingIntent services running in the background. Foreground applications are unaffected by these restrictions.

  • “When the app goes into the background, it has a window of several minutes [emphasis added] in which it is still allowed to create and use services. At the end of that window, the app is considered to be idle. At this time, the system stops the app’s background services, just as if the app had called the services’ Service.stopSelf() methods.”
  • A background application is not allowed to create a background service. A new API has been created in API level 26 to permit a background application to create a foreground service prior to entering the idle state.

A system whitelist exists whereby applications are permitted to run and start services without limitation. However no interface exists to add user applications to this list permanently.  Applications will be temporarily added to the whitelist “for several minutes” in order to handle common background tasks, such as:

  • Handling a high-priority Firebase Cloud Messaging (FCM) message. This applies only to FCM; see the following ‘Enterprise implications’ section for further discussion.
  • Receiving a broadcast SMS or MMS message.
  • Executing a PendingIntent from a notification.

This list is not exhaustive, Google qualifies the list as “when [an app] handles a task that is visible to the user,” so there is room for expansion in future versions. Note that is this completely separate from the whitelist associated with doze mode and battery optimizations and the two whitelists should not be confused.

 

Enterprise implications

Many of the same Enterprise applications that were affected by Marshmallow’s introduction of doze mode also will be affected by Oreo’s limitation on background processes.

Some notable examples:

  • Running an on-premises push messaging system and wishing to control the entire IT stack from end to end (therefore not being able to rely on FCM)
  • Downloading or uploading large files, for example for a product database update or captured batch data.
  • Running a continual background service to check for network traffic on a particular port.

Zebra’s value-added applications and services will be affected in the following ways:

  • DataWedge can be configured to call startService whenever data is captured. If the service to which DataWedge is sending that data has been built with API level 26 or higher, or the target application has disabled background activity, the data will not be sent via startService.
    • If the target application has been built with API level 25, the call to startService will still succeed.
    • Zebra recommends either keeping your target application at API level 25 or delivering the DataWedge data via an alternative mechanism (e.g. startActivity or sendBroadcast).

 

DataWedge 7.0 has introduced support for a new Intent Delivery mechanism, 'sendViaStartForegroundService' and has added a new option, "Use startForegroundService on Failure" to address this change to startService in Oreo.  For more information about both of these features then please refer to the DataWedge Intent documentation.

 

  • Enterprise Home Screen has a feature to automatically launch a list of specified services, as defined in the EHS configuration for <service_auto_launch> . Under Android 8.x the service_auto_launch feature will no longer work. Customers are advised to find alternative ways to satisfy their use cases while the team determines the future of this EHS configuration option..

Figure 6: EHS service auto launch option

 

Enterprise Home Screen 3.0 has introduced two new options: "Foreground Service Auto Launch Enable" and the accompanying "Foreground Service Auto Launch" list to address this change to startService() in Oreo.  For more information about these features please refer to the EHS documentation for advanced settings​.

 

Testing

Although the following commands feature prominently in several blogs, I could not find them listed among Google’s official documentation. They are however featured in Google’s Android Oreo explanation video so can therefore be assumed to be supported.

 

//  runs apps in background

adb shell am make-uid-idle <package>

 

//  force background limitations

adb shell cmd appops set <package> RUN_IN_BACKGROUND deny

 

//  returns app to normal behaviour (based on target SDK)

adb shell cmd appops set <package> RUN_IN_BACKGROUND allow

 

Mitigation

There are various techniques to mitigate the new background restrictions, many of which involve modifying the application code in one way or another:

 

1. Schedule a job: Job scheduling involves defining one or more “triggers” that, when fired, will execute your application’s defined functionality. The advantage of a job scheduler is that it allows Android to be more power-efficient, only running the CPU / networking when required, rather than allowing applications to hold long-running background processes.

 

Common triggers are:

  • Device is connected to a specific network type
  • Device is charging or has a reasonable amount of battery left
  • Job runs periodically
  • Job runs after a minimum amount of time
  • The device is not idle
  • Examples of more triggers are available from the JobInfo.Builder class with new examples being added with each Android release.

 

Multiple APIs are compatible with Job scheduling:

  • JobScheduler introduced in API level 21
  • Firebase Job Dispatcher compatible all the way back to API level 9 and despite the name, does not require the application to use Firebase. GMS is required on the device. Recommended by Google.
  • JobIntentService, part of the support library. Very simple drop-in replacement for IntentService that uses JobScheduler to implement the same logic as IntentService. Recommended by Google.

 

2. The temporary whitelist: Under certain conditions a background application is placed on a temporary whitelist, where it is able to perform background processing, including launching services for “several minutes” without limitation. As previously mentioned, this temporary whitelist is separate from the doze whitelist but does also bypass any effects of doze mode. Applications will be placed on the temporary whitelist under the following conditions:

    • The application receives a high priority FCM message. The message must be high priority, lower priority messages will not have the same effect and will be delivered only when the user next interacts with the device.
    • The application receives an SMS or MMS message.
    • The system executes a PendingIntent as a result of a user tapping on a notification. This PendingIntent will still be processed by the background application.

Realistically, the temporary whitelist would only be used as a mitigation for background limitations in conjunction with FCM. You would not expect to start sending SMS messages or having the user tap multiple notifications to keep your application alive. If you are already using FCM or are considering moving to an FCM deployment, then ensure you are using high priority messages for applications you need to run in the background. FCM should be a suitable solution for many customers, except those with AOSP devices and those who do not wish to rely on external servers as part of their push mechanism.

 

3. Foreground service: If your application is performing work that is noticeable to the user, for example downloading a product database or uploading large files, it makes sense to inform the user and you can use a foreground service to complete the task. From Oreo onwards, the process of running a foreground service is:

There are several examples available from Google which show how existing applications were altered to use a foreground service.

 

4. Finally, as far as the Google-recommended approaches go, you could defer background work until the application is naturally in the foreground, though this would be heavily use-case dependant.

 

5. Continue to target your application with API level 25 or below. Again, this should not be seen as a long-term solution; Google is going to start enforcing applications to move to “recent API levels” from late 2018. As noted previously, the ‘Background activity’ setting also can be used by users to circumvent this workaround.

 

Limitation: Update frequency from Location APIs

Any background application or service making use of Android location APIs will only receive location updates “a few times each hour.” Unlike the previous two noted limitations, this limitation exists for any application running on an Oreo device regardless of target API level, and is not affected by the Background activity option.

 

Having such infrequent updates might have an impact on your application, so it is important to understand if and how your application will be affected. Realistically, if you need to get a location from a background service in Oreo, you are probably running in a Job or are triggered by a pending intent or FCM message. In any case, the issue is not how frequently you can receive updates, but more likely the age of the (cached) update you have just received.

 

Affected APIs

The following Android location APIs are affected:

  • Fused Location Provider Client which replaced the Fused Location Provider API. Both are affected.
  • Location Manager. I have written about location manager extensively in a previous post. Essentially, any available Google location API to which you can ask ‘where am I’ is subject to this limitation.
  • Wi-Fi Manager startScan will only perform a full scan ‘a few times each hour’. As I wrote about in a previous post, it is possible to scan for nearby apps and use Google’s Geolocation REST API to receive back Google’s best guess for that device’s location based on its nearby apps. The limitation to startScan means that this technique for determining location without relying on LocationServices will no longer work. Note also that in Android Pie this method is marked as deprecated.

 

The following location APIs are not affected:

  • The batched version of the fused location provider. This allows for bread-crumb use cases to determine the historic location of a device at a greater resolution than would be achieved by calling the FLP manually at regular intervals.
  • Geofencing. If your use cases involve knowing whether the device has entered, has left or is dwelling within a pre-defined outdoor area, then you should consider using Geofences, which allows your application to receive a callback whenever such an event occurs. You can geofence a building to determine when a device has entered or left that building, but the reliability of geofences indoors is highly dependent on the environment and is likely to be sub-optimal.
  • ActivityRecognitionClient which replaces the earlier ActivityRecognitionApi can be used to determine if the user is performing various activities such as walking or driving.
  • Any indoor-based APIs, including 3rd party APIs that rely on BLE or other hardware dependant technologies such as the magnetometer, are unaffected.
  • APIs for Zebra technologies such as RFID or Worry Free Wi-Fi are unaffected.

 

Enterprise implications

Google’s intention by implementing these location restrictions is to lock down use of the APIs to a specific set of use cases to enhance device power management.

The supported use cases are:

  • Foreground applications such as navigation apps providing turn by turn directions
  • Device tracking applications such as bread-crumbing to determine the historical location of a device
  • Geofencing – whether a device has entered or exited a pre-defined area.

 

Several potential Enterprise use cases are impacted by the location API limits:

  • Real time route planning for transport and logistics use cases, updating existing routes based on the real-time outdoor position of the device.
  • “Find my device” to locate a device in real time outdoors, e.g. to gather devices in preparation for the next shift or locate devices requiring battery replacement. Requires the device to maintain its location.
  • Device tracking to provide historical location data. Although batched location is still available through the FLP this use case may have been previously met using the standard API, so it might require a code change in the application.

 

Mitigation

Many of the same techniques used to mitigate background processing limitations also can be used to cope with background location limits under Oreo. Remember that unlike the previous limitations noted here, location limits apply regardless of the target SDK.

  1. Foreground service: Background location limits do not apply to applications with a foreground service or are themselves in the foreground. This is designed to cater for applications that the user will interact with (think navigation), but also might be useful in other situations.  One example is a ‘find my device’ use case: a foreground service could be created in response to a high-priority FCM message to determine the latest device position. Google provides an example showing how to use a foreground service to determine a device location.
  2. Passive listener: If a different application in the foreground is requesting location updates, a background application can “piggy-back” on the request to receive updates at a faster rate, as if they too were in the foreground. This is achieved by using the passive listener. If no other foreground application is requesting updates, none will be received via the passive listener. This will depend heavily on what applications you are running on your device. For consumer devices, it is a reasonable assumption that many applications rely on user location to provide their functionality, but the same is not necessarily true for applications running on an enterprise device.
  3. Bread-crumbing: As noted previously, if your use cases revolve solely around logging the historical location of devices, consider using the batched location functionality of the Fused Location Provider.
  4. Geofencing: Again, if your use cases revolve solely around detecting whether a device is inside or outside of a specified area(s), a retain store, for example, consider using a Geofence.

 

Summary of Oreo background limitations

 

  Receiving Implicit broadcast intents Running services in the background Update frequency from Location APIs
Description Implicit broadcast intents can no longer be registered for from the application manifest. An application cannot run or have running services while in the background. Many location APIs restrict the location update frequency to 3 or 4 times per hour.
Notable affected enterprise use cases Relies on DataWedge intents or MX Intent capability Non-FCM push based solutions, network monitoring, long running downloads or uploads Functionality dependent on real-time location tracking (e.g. “find my device”)
Affects APIs targeting less than 26? No, unless user manually re-enables it from the settings UI No, unless user manually re-enables it from the settings UI Yes
Recommended Mitigation Rework app to use dynamic broadcast receivers in code. Target an API level less than 26 as an interim solution. Use a Job scheduling API or a foreground service. Target an API level less than 26 as an interim solution. Use a foreground service or a geofence / batched location (depending on use case)

 

Notification Enhancements

Android Oreo introduces several enhancements to notifications to give the user more control over which notifications they can receive from applications:

  • Notification channels allow developers to group notifications together. To give a consumer use case: a game might have a channel to notify the player they have won a treasure and a separate channel to notify the player they haven’t played in a while… the player is undoubtedly happy they are able to silence the latter notification without affecting the former. Enterprise applications are different, notification control is often handled by an administrator who does not want the user silencing or modifying notifications.
  • Notification dots, also known as badges were introduced in Oreo to provide additional notification functionality for supported launchers. Neither the default launcher included in Zebra devices nor Enterprise Home Screen support notification badges.
  • Snoozing: Sliding a notification to the right or left provides an additional option under Oreo, Snooze, identified by the clock icon. Snoozing the notification allows the user to dismiss it for a period of time (15 mins, 30 mins, 1 hour, 2 hours), after which time it will re-appear at the same priority. Note that persistent (ongoing) notifications cannot be snoozed.
 

Figure 7: Notification snoozing: A notification is received

Figure 8: Notification snoozing: The notification is slid

 

Figure 9: Notification snoozing: The notification is snoozed

 

It is not possible to prevent a notification from being snoozed without making the notification persistent (ongoing).

  • There are some other notification features added in Oreo which are applicable to enterprise applications:
    • You can detect when a user manually dismisses a notification using onNotificationRemoved
    • You can set the background colour of a notification, possibly to match any company branding
    • You can set a timeout after which notifications will be automatically cancelled, potentially useful to confine a notification to a user’s shift.

 

JobScheduler improvements

As previously noted, there are a number of limitations to background processing introduced in Oreo. Google is promoting the JobScheduler API as the solution for “90%” of consumer use cases that require background processing. While the same figure for enterprise use cases may not quite be 90%, undoubtedly the solution for many enterprise background use cases will be to transition to the Job Scheduler API.

An overview of the Job Scheduler was given earlier in this post under the mitigation steps for the limitation of running services in the background. Under Oreo additional triggers have been added to increase the usefulness of the JobScheduler API as well as the new JobIntentService. The JobScheduler API continues to evolve and at the time of this writing, it had been announced that additional triggers would be added in Android Pie.

 

Installing apps from unknown sources

As explained in the Android docs the “Allow unknown sources” system setting has been removed and replaced with the “Install unknown apps” permission. Additional information is available in Google’s  application publishing documentation.

This setting controls whether the device is permitted to install applications that were not obtained from the Google Play Store, affecting the following techniques for application distribution:

  • Clicking on the apk from the file manager (after downloading or transferring the apk to the device)
  • Using an application marketplace other than the Play Store.

 

Installation via the MX AppManager is not affected. This covers installation via StageNow, EMDK for Android or EMDK for Xamarin.

The MX Settings Manager Unknown Sources parameter will be affected, and any future deployment making use of that function should consult the documentation for that feature.

 

Picture-in-picture

Starting in Oreo, any application can support Picture-in-Picture (PIP) mode. This allows an app to display extra content in a small window in the corner of the screen (see below). This functionality is designed for video playback, either to display media or to show a contact for the duration of a VOIP call. Enterprise use cases might include the showing of a video of how to undertake some machine maintenance while allowing the user also to do other things.

 

Zebra is not taking any special steps to handle PIP mode, and any non-PIP application will continue to work underneath a PIP overlay. The application beneath the PIP overlay is not in the background, so is not subject to the background limits and will continue to work as though it is in the foreground. For example, the following screenshot shows the DataWedge demo application capturing data while displaying a video picture-in-picture.

 

Figure 10: VLC running picture-in-picture with the DataWedge demo

 

Autofill framework

To aid with form data entry, Google has extended its Autofill Framework, which automatically populates Web forms in Chrome, to work with native apps. The target use cases are primarily consumer-focused, for entering login credentials or credit card information, for example. But there is great potential for enterprise data-entry applications as well.

 

The data to populate application forms comes from an autofill service.  Since it is possible to create your own autofill service, it can be customized to your specific industry or application needs. Please see Google’s documentation on autofill for more information as well as their accompanying sample app which shows how to create an autofill service.

 

At the time of this writing, it was  not possible to provision the autofill service on the device through an EMM or any Zebra API. This manual provisioning step will therefore be required:

Settings --> System --> Languages & input --> Advanced --> Input assistance --> Autofill service.

 

Webview APIs

Several Webview APIs have been added in Oreo for applications that use an embedded WebView. Of particular interest is integration with the existing Safe Browsing API.

 

You can enhance the security of your application by enabling Safe Browsing on your WebView. This will ensure that any URL the user is navigating to has not been flagged by Google as potentially harmful.

 

Zebra’s own Enterprise Browser product embeds a WebView, and the product team is planning on giving developers the option of enabling the Safe Browsing feature in an upcoming release of the product, although no dates for this feature are yet available.

 

Pinning shortcuts and widgets

Oreo introduces pinned shortcuts, which builds on the app shortcuts first introduced in Android Nougat. In Oreo, it is now possible to create separate icons to represent individual shortcuts in supported launchers.