Random Musings on the Android 14 Developer Beta 1

When 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.

We’ve moved out of developer previews and into beta releases. That slows down the pace of change, but still there some things worth mentioning. My focus is on the developer side; see Mishaal Rahman’s Twitter thread for a broader look at Beta 1.

What Got Top-Line Attention?

One trend with these musings is that I cover something before Google does, for one reason or another. Some stuff from my DP2 musings that were announced this time were:

Also, Path is no longer a largely write-only API, which has been a large pain point for developers over the years.

Something I noticed in DP2 but didn’t understand enough to write about is the new limitation on accessibility services. Apps can indicate certain UI elements that are only available to “true” accessibility services, those that actually help people with accessibility. Mishaal Rahman wrote more about that. You can use ACCESSIBILITY_DATA_SENSITIVE_YES or android:accessibilityDataSensitive to enable this.

What Else At Least Was Announced

The concept of “non-dismissable notifications” was always a bit scary, insofar as apps can really annoy users with those. They have been slowly becoming more dismissable, and Android 14 makes them mostly dismissable.

While dynamic code loading via PathClassLoader and kin might get you banned from the Play Store, it’s still a technique used by many an app. Android 14 requires that code to be marked as read-only, once you are targeting Android 14.

Eight years ago, I published some safe unZIP code to avoid path traversal attacks. Android 14 now enforces that at the system level, for apps targeting Android 14. I really hope safe unZIP code becomes available in a Jetpack library, so it can be used by all apps on more OS versions. Bonus points if they also stop ZIP bombs.

One hole in the background activity start limitation was IPC. Other apps could arrange to start activities by convincing some other app to start them, such as via a PendingIntent. Android 14 makes that opt-in, for apps targeting Android 14.

What’s Outta Here

overridePendingTransition() on Activity is deprecated, replaced by overrideActivityTransition().

Google removed the “data transfer” type of JobInfo.

What Could Be Kinda Wild

The IntentFilter class appears to now allow filtering by extras. Since the parameter is a PersistableBundle, this is not merely filtering based on the existence of extras by name, but presumably they also must match on value. Prior to this, extras were purely “payload” of an Intent and were not something that you could filter upon. It will be interesting to see where Google puts this to use.

What Else Caught My Eye

View continues to get handwriting recognition APIs.

Google’s ill-documented HttpEngine now supports a bi-directional stream API, backed by a BidirectionalStream class.

The NetworkCapabilities API now explicitly supports Thread, of particular interest to those working with Matter.

I had not realized this, but apparently getType() on a ContentProvider was not defended by read permissions. Since that could leak information (the MIME type for a particular Uri), they added getTypeAnonymous(). getType() will be protected by read permissions for providers that also implement getTypeAnonymous().

In DP1, Google stated that context-registered receivers might not receive broadcasts in real time. They have now added some APIs for the reverse direction: a broadcast itself, via BroadcastOptions, can have a deferral policy. The description of DEFERRAL_POLICY_UNTIL_ACTIVE sounds a lot like their DP1 announcement… except this would be opt-in by the sender. 🤔

Broadcasts now have some form of “delivery group” semantics, though the documentation on this is confusing.

And, there is now a dedicated exception if you try to startForeground() a service that is not actually started.