Random Musings on the P Developer Preview 2

Whenever Google publishes a new developer preview, I wander through through the API differences report and the high-level overviews, to see if there are things that require more attention from developers, with an emphasis on mainstream features that any developer might reasonably use. I also tend to emphasize things that may not get quite as much attention, because they are buried in the JavaDocs.

On the whole, Android P Developer Preview 2 (P DP2) did not make that many changes, certainly none that are “big ticket” user-facing items. As with P DP1, I’m at a loss to tell my mother what she’ll be getting if she elects to replace her Nexus 5X with something newer that will get Android P.

In my P DP1 random musings, I suggested that perhaps the reason for the lack of changes was “a focus on cleaning things up in preparation for future versions of Android”. Certainly we are seeing elements of that come out of Google I|O, specifically the AndroidX repackaging of Google’s libraries and the new Jetpack initiative. I’ll blog more about those tomorrow, as neither are really tied to Android P.

However, just because there were no big changes does not mean that there were no changes. Here are some things that I found that may be of interest to you. These are incremental changes in P DP2 — see my P DP1 random musings for other Android P changes.

What Works Now, That Didn’t Before

One of the security benefits that was touted for Android P was that cleartext Internet traffic — http instead of https, for example — would be banned by default. However, in my tests, this did not work, either for WebView or for HttpURLConnection. The underlying bug has now been fixed. You will now start seeing exceptions due to cleartext traffic that you had not seen in P DP1, let alone previous versions of Android. Ideally, you switch to encrypted connections. If you need to support http URLs, though, you will need to set up network security configuration and set up cleartextTrafficPermitted="true" for the domain(s) for which you still need http support.

Android P was documented to require a FOREGROUND_SERVICE permission for you to use startForeground(). This is a normal permission, so you merely need the <uses-permission> element, not runtime permission support. However, in P DP 1, this did not work. Now it does, so you will need to add this permission.

I wrote about AppComponentFactory in my P DP1 random musings. It’s a way for you to override the default reflection-based way that the framework creates instances of your activities, services, manifest-registered receivers, and providers. However, it was completely broken on P DP1. But, it works now, at least for activities — I have not yet tried other components.

What’s New in the War on Background Processing

I thought that Google had declared victory already. Apparently, they are adopting a “take no prisoners” approach to the War on Background Processing, introducing a bunch of changes in P DP2.

The worst is the “app standby buckets”. In Android 6.0-8.1, your app would move into an “app standby” category if the user had not visited the app’s UI recently, and while in “app standby”, it was pretty much as if Doze mode was on all the time for your app. Now, there are four major “buckets”: active, working set, frequent, and rare, with progressively stronger restrictions placed on app operation. In particular:

  • FCM high-priority messages — formerly Google’s recommended approach for getting your app to react to external data changes — will be capped in the “frequent” and “rare” buckets

  • Device manufacturers can decide for themselves when and how to categorize apps into these buckets

The user can also elect to manually restrict background operations for your app. If the user does, basically nothing works: no jobs, no alarms, no network. There are no “idle maintenance windows” or anything of the sort. The only thing that works when you are restricted this way are FCM high-priority messages, and app standby means that they might not work either. The user can enable background restrictions on their own by visiting Settings > Apps > (your app) > Advanced > Battery > Background Restriction. However, Android P is documented to prompt the user about misbehaving apps:

  • Those that use partial wakelocks for more than an hour, and

  • Those with a targetSdkVersion of 26 or lower that have “excessive background services” (whatever that means).

There is a new isBackgroundRestricted() method on ActivityManager. Based on the documentation, it appears that this will return true if the user goes and elects to restrict your background operation manually.

There is a table of what the effects are for different types of scenarios, such as the four app standby buckets.

The power change documentation also has:

Android P makes a number of improvements to battery saver mode. The device manufacturer determines the precise restrictions imposed.

IMHO, Google has a bizarre definition of “improvements”, if “random behavior based on device manufacturer whim” is an “improvement”.

As I have been recommending for the past few years, do not write apps that need to have reliable background work.

What Works as Before, Strangely

If your app’s targetSdkVersion is 16 or lower, the user gets a warning dialog on the first run of the app, indicating that the app is really old. This may be a prelude to an outright ban on running such apps.

Frankly, if it will be a ban, it would be nice if Google would clarify that point, and adjust the preview’s dialog to reflect that fact. If, on the other hand, the plan is for this dialog to be the only effect (at least for Android P), that too would be good to know.

What Changed from Before, Strangely

In P DP1, FingerprintManager was more-or-less deprecated and replaced with FingerprintDialog. In P DP2, FingerprintDialog is gone, replaced with BiometricPrompt. The docs indicate that BiometricPrompt will support a range of biometric forms of authentication, including face recognition and iris scanning. I sincerely hope that it largely stops there, as “swab the inside of your cheek with your phone so we can collect a DNA sample” will be challenging for users of phablets. Also, ew.

P DP1 added a Person class for use with the improved MessagingStyle form of Notification. P DP2 also has Person, but Person got upgraded out of the Notification classes and now is android.app.Person.

After 10 years, Google finally admitted that onCreateThumbnail() in Activity never really worked, and so it is now deprecated.

If you experimented with the “key fallback” options in P DP1, note that those View methods are now addOnUnhandledKeyEventListener() and removeOnUnhandledKeyEventListener().

If you experimented with the “tracing” stuff added to WebView in P DP1, you realized that little of it would even compile. That’s OK, as it is significantly changed now in P DP2. I have not had a chance to try any of it to see if it works.

What Else Caught My Eye

ImageDecoder has been slightly improved, in that it now supports assets as well as files and content. However, Google has indicated that it will not support streams.

BatteryManager now offers a computeChargeTimeRemaining() method, returning the estimated number of milliseconds before the device runs out of power. You might use this for your own in-app warnings regarding power levels, if your app consumes a lot of power (e.g., video player).

Settings now has ACTION_DATA_USAGE_SETTINGS, to lead the user to the data usage screen in the Settings app, where available.

UiAutomation now has grantRuntimePermission() and revokeRuntimePermission(), for improved testing in the world of runtime permissions.