Random Musings on the Q Developer Preview 1

Each time Google releases a new developer preview, I rummage through the API differences report the high-level overviews, and even the release blog post, to see if there are things that warrant more attention from developers. I try to emphasize mainstream features that any developer might reasonably use, along with things that may not get quite as much attention, because they are buried in the JavaDocs.

As with the previous two releases, Q seems to be lacking a prominent user-facing feature. Q is certainly better, but I have no idea what I will tell my mother that she’ll gain if her phone gets the Q update at some point.

However, there are a number of changes for developers.

What Will Piss Off Developers

Google has done quite a bit over the past several releases to improve privacy and security in Android. That tends to be a double-edged sword, though, where the changes break existing app functionality. So, for example, developers of file managers are going to be rather disgruntled with scoped storage, which says that you can no longer access all of external storage via the filesystem.

The roles system is an interesting concept. At one level, it might mostly be there for the benefit of the Play Store and other app distribution channels, to better identify whether apps are justified in holding certain permissions. However, the relationship between roles and permissions is almost completely undocumented. For example, does ROLE_SMS “Can send and receive SMS messages; can read contacts” mean that no other app can read the contacts, despite requesting the READ_CONTACTS permission? The fact that we need to run experiments and attempt to reverse-engineer the documentation is never a good sign.

Other things will just pour salt into existing wounds. For example, the “non-SDK interfaces” push continues in Q, so developers that dodged bullets in P might now run into problems in Q, if their preferred hack is no longer available.

Plus, there is your usual barrage of changes that won’t affect everyone but might dramatically impact some developers. Starting an activity from the background has long been considered to be poor form; developers who stuck with it now have problems. SYSTEM_ALERT_WINDOW has been dodgy for years; developers who stuck with it now have problems. Background access to the clipboard is gone. Using locations in the background is overhauled. And so on.

What Will Piss Off Me

Google says that they have changed onResume() onPause(), and android:resizeableActivity, but they did not seem to document what changed. ¯\_(ツ)_/¯ At least on the onResume()/onPause() stuff, prior reports indicate that multi-window environments — including foldables — will now leave apps in the resumed state even if they no longer have the input focus. There appears to be a new onTopResumedActivityChanged() activity callback to find out if this activity is now the “top resumed activity”, which I am guessing means “the activity with the input focus”.

What Has Me Worried

There is a whole new set of APIs around “content capture”. Unfortunately, the central class has “TODO” for its documentation. However, it is tied to the detestable autofill APIs and seems to report when views come and go. In the hands of responsible individuals, this has interesting characteristics for app testing. In the hands of irresponsible individuals, this could be yet another privacy leak.

Similarly, there is an InspectionCompanion “used to inspect views”. This, at least, seems like it may be only some kind of in-process capability, even though it is largely undocumented.

There is a new GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY permission, which “allows an application to get the screen lock complexity and prompt users to update the screen lock to a certain complexity level”. On the surface, this seems fine, but this is a normal permission, so users are not prompted about it. Historically, this sort of functionality was limited to device administration apps.

There is a new SMS_FINANCIAL_TRANSACTIONS permission, which “allows financial apps to read filtered sms messages”. However, I don’t know how one defines either “financial apps” or “filtered sms messages”. The protection level of this permission is undocumented.

There is a new setAllowSystemGeneratedContextualActions() method on Notification.Builder that “determines whether the platform can generate contextual actions for a notification. By default this is true.” Frankly, the notion that Android will automatically put actions into our notifications creeps me out.

What Has Me Wondering How Far Down the Rabbit Hole Goes

Google has been pushing us away from background services for a couple of releases, forcing a lot of developers to switch to foreground services. Now, with Q, there are “types” of foreground services, described via an android:foregroundServiceType attribute (in the manifest?). Available types include phoneCall, mediaPlayback, location, dataSync, and connectedDevice. The startForeground() call can now also pass in the type of foreground service it will be (or a FOREGROUND_SERVICE_TYPE_MANIFEST flag to say “read the values from the manifest”). So, now we have services, then foreground services, then types of foreground services. What’s next? Subtypes? Plus, it remains to be seen what the system does with this type information.

What Has Me Intrigued

RecoverableSecurityException makes its return, having been in one of the past rounds of developer previews but removed from the SDK prior to release. If you catch one of these, you have a dedicated message and RemoteAction for being able to help fix whatever the problem is.

There is a new android:useAppZygote attribute for <service> in the manifest. It allows an isolated service (android:isolatedProcess) to have its process forked from “an Application Zygote, instead of the regular Zygote”. From the docs, my guess is that this is here for Chrome and similar apps that may want to fork lots of isolated processes for executing possibly-unsafe code. However, isolation from the regular app zygote may also mean that attacks that affect the app zygote (and therefore all normal app processes) might not affect these isolated services.

There is a new isRunningInUserTestHarness() method on ActivityManager. This apparently is not to detect normal instrumentation tests, but rather some other style of tests for “a device farm/testing harness (such as Firebase Test Lab)”. The idea is that you would use this flag to skip over stuff that might screw up such tests. It remains to be seen exactly where this is true or false.

In Android 8.0, we gained the ability to launch an activity into a particular display. This is a useful alternative to the Presentation API. Apparently, though, there are some external displays that will show up in the system as displays, but for which you cannot show an activity on them. There is a new isActivityStartAllowedOnDisplay() method on ActivityManager to use to determine if a particular display is good for activities. My best guess is that this is for foldables, but that’s just a guess.

There are a bunch of new methods on NotificationManager. A lot center around the notion that you can allow some other app to post notifications on your app’s behalf (a “delegate”).

Font, FontFamily, and related classes are now part of the framework APIs.

An entire MediaPlayer2 and related classes were added, apparently as a replacement for MediaPlayer. I have not worked with ExoPlayer, so I do not know how MediaPlayer2 might relate to ExoPlayer in terms of API or implementation.

There is now a DnsResolver class “for asynchronous dns querying”. In related news, AWLTCLB (Abbreviations Would Like Their Capital Letters Back).

Uri has toSafeString(), which attempts to redact some information to make the resulting text safe for logging purposes. My guess is that the resulting string will then be useless for debugging, but perhaps I am being pessimistic.

They added a FileUtils class, mostly containing various copy() methods.

Environment now offers dedicated public directories for audiobooks (DIRECTORY_AUDIOBOOKS) and screenshots (DIRECTORY_SCREENSHOTS).

PowerManager now offers methods to get the “thermal status” (i.e., is the device being throttled to reduce its temperature) and register a callback for status changes. This may be useful for games or other high-intensity apps, so they can provide a UI indicator that explains why things are now running more slowly (so the device can cool down).

The new settings panels seem nice, though I’m uncertain why bloggers keep insisting this has something to do with slices. We show a settings panel via startActivity(), so most likely they are just activities themed as a bottom sheet dialog. Then again, it would be nice if slices were used for something. Just sayin’.

What Is Now an Ex-API

The entire preference system, outside of SharedPreferences, is deprecated. This includes PreferenceManager and the entire preference UI. Developers are steered towards the AndroidX replacements.

ACTION_INSTALL_PACKAGE and ACTION_UNINSTALL_PACKAGE are deprecated. Instead, we appear to need to use the more-cumbersome PackageInstaller API.

ACTION_NEW_OUTGOING_CALL is deprecated. There are new CallRedirectionService and CallScreeningService APIs for apps that formerly did that sort of work by listening for ACTION_NEW_OUTGOING_CALL broadcasts.

The “preferred activities” APIs in PackageManager are now deprecated.

NetworkInfo is deprecated, along with the methods on ConnectivityManager that return a NetworkInfo.

StorageVolume.createAccessIntent() is deprecated. More importantly, it will fail fast. This was used to request access to one of the Environment public directories, as an alternative to needing READ_EXTERNAL_STORAGE and therefore getting access to the entire external storage area. It would appear that the scoped storage feature not only replaces this but is incompatible with this. So, if you are using createAccessIntent(), you will need to add code to take a new approach on Android Q and higher devices.

Where Things Go From Here

There are six beta releases on the docket. Beta 4, due in early June, is supposed to have final APIs, so I’ll have a few more “random musings” posts to write in the upcoming weeks.

Plus, I’ll be giving some of this new stuff a workout, and I’ll have new material for subscribers covering Android Q soon.


Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!