Random Musings on the P Developer Preview 1
Each time Google releases a new developer preview, I rummage through the API differences report and the high-level overviews, to see if there are things that warrant 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.
As with Android O, Android P seems to be lacking a signature user-facing feature. It even lacks what I would consider to be a signature developer-facing feature. P, at least in the first developer preview, is an incremental advance. This might represent maturation of the platform, a focus on cleaning things up in preparation for future versions of Android, or changes in staff allocation emphasizing other Google projects. It might also be “sandbagging”, with signature features showing up in future developer previews.
That being said, there are a number of things that I found curious and interesting.
Usually in these “random musings” posts, I have something that scares me. Occasionally, I have lots of things that scare me. Fortunately, this is a fairly mild release, and while these are early P days, I’m not scared yet.
AppComponentFactory is going to be a double-edged sword.
You can define a subclass of
AppComponentFactory and register it in the
manifest in the
<application> element. Then, whenever the framework
needs to create an instance of an
AppComponentFactory will be asked
to do that work. You are given a
String of the component name
that appeared in the manifest, and an
BroadcastReceiver). Your job is to return the desired object. It would
appear that you could chain to the superclass for those components that
you do not want to handle differently, allowing you to focus on the scenarios
where you want to do something different than what the framework normally does.
Let’s use an
Activity an an example. Normally, when the user taps the
home screen launcher icon, Android creates an instance of the designated
Activity subclass using the zero-argument public constructor. However,
if the app has a registered an
AppComponentFactory and overrides the
instantiateActivity() method, that will be called, and it needs to return
Use some other sort of constructor, perhaps involving dependency injection
Have a generic placeholder
<activity>element, and decide in Java code what the actual
Activitywill be, by using other information in the
Intentand perhaps other state information in the app
Create some sort of
ActivityWrapperthat wraps the real
Activitysubclass, where the wrapper can do logging and such, forwarding all calls onto the wrapped
And so on. Hence, this capability could be useful for a variety of scenarios.
However, it certainly simplifies the implementation of certain types of malware and crapware. Now I don’t even need to mess with the existing code. All I need to do is:
Create and register an
instantiateActivity()(or whatever) to put my own wrapper around the app’s real component
Ship the altered app by whatever my preferred distribution channel is
Get results from my wrappers (e.g., report everything the user types in, slap ad banners over the UI, replace the app’s own ad banners with my own)
So, app repackagers will be all over this. Right now, that’s probably a semi-manual process; this change makes it easier to automate. So, with the good, we also get the bad.
This facility first came to my attention from Mishaal Rahman of XDA-Developers.
It existed in some Android 8.0 builds, and possibly Android 8.1, as hidden
Application, rather than through this separate
Changes You Should Pay Attention To
Some deprecations that I pointed out earlier – such as accessing hidden APIs and device admin policy changes, do appear to be coming to fruition. In particular, libraries that you use might be using some hidden APIs, even if you are not. Keep a close eye on your dependencies and upgrade them as appropriate.
Also, a rumored change has come to pass: the framework
classes are deprecated. This is a nudge to get you to use the ones from the Support
Library, for consistent implementations across device versions. Note that there
are not direct analogues for everything in the Support Library (e.g., no
Once you set your
P (or, eventually, 28?), you will be
forced to use
https by default. Attempts to use
http URLs will result in
an exception. If you still need access to unencrypted Web content, you will need to
opt into that behavior.
Also, once you set your
P, you need to request
This is a
normal permission, so you just need the
in the manifest. It is not really clear why they introduced this, but it is something
that you will need. OTOH, this seems to be the only change related to the
years-old “War on Background Processing”, so perhaps we have turned the corner
on that subject.
If you have ancient instrumentation tests, they may break, until you either update them to use JUnit4 or you opt into the legacy testing library.
Android 7.0-8.1 stopped requiring
FLAG_ACTIVITY_NEW_TASK. I pointed out this
flaw ~18 months ago, and again
a year ago. Much to my shock
and amazement, this has been addressed with P, and so
you need that flag again
when starting an activity from a non-activity
Context, such as from a
BroadcastReceiver. This returns us to the behavior from Android 6.0 and
older OS versions, and so you probably already have this flag, unless your
minSdkVersion is 24 or higher.
While there are many other behavior changes, those seem to be the ones that are likely to affect the most developers.
Stuff That Needs More Explanation
The JavaDocs for
A SliceProvider allows an app to provide content to be displayed in system spaces. This content is templated and can contain actions, and the behavior of how it is surfaced is specific to the system surface.
It is unclear what “system spaces” and “system surfaces” refer to (lockscreen? notification shade? something else?)
The JavaDocs for
Sliceand the release notes for 28.0.0-alpha1 Support Library suggest that the content is app-to-app, not app-to-system-surface
So, there may be something cool here, but the documentation is really scant on the subject.
View (at minimum) have a new
method. This works just like
findViewById(), but it throws an exception when
there is no
View matching the ID, instead of returning
null. It is unclear
where and why we would use this.
In addition, there is a
that “provides an API for developers to send events to statsd”. It is unclear
what this means or why we would use it.
You can now attach a “semantic action” to a
Notification.Action, such as indicating
that this action will delete something, archive something, “thumbs up” something, etc.
It is unclear if this will be used for accessibility or if it has some other role.
Stuff That Seems Intriguing
We now have a
that we can attach to a widget. Presumably, it embiggens things.
There is a static
disableWebView() method on
WebView, which tells Android
to not allow any
WebView use in this process. If you have a multi-process app,
and you know that some of your processes do not use
WebView, calling this will
prevent you from accidentally loading
WebView and incurring the memory overhead.
However, it does this by throwing an exception, so this may be the sort of thing
that you only use in
debug builds for tracking down unexpected
StrictMode now offers callbacks. For any violation, you can have a listener
called on an
Executor that you supply. Your listener is handed a
object, which is a subclass of
Throwable. Hopefully (presumably?) this
Violation is generated at the point of the bad code, so you can examine
the stack trace and decide what to do. This may make it possible to create
StrictMode reporting tools, including tying them into your
existing crash logging system.
WebView offers a
TracingController that can be used to “enable/disable tracing for parts
of code and to collect tracing data”. You get a JSON block back, designed for
chrome://tracing in your favorite Web browser whose name starts
Apps can now find out what autofill service the user has chosen, if any, via
This would be useful if your app wants to have a whitelist of trusted autofill
services that you are willing to use, blocking autofill if the user chose one
that you do not recognize.
Other Stuff Worth Noting
AccessibiltyService can now
on behalf of the user.
The API differences report will note things being removed that do not appear
to be removed. For example,
the differences report indicates that a bunch of methods were removed
Those methods are still there in the full JavaDocs.
There is a new
Settings action (
to take the user to a screen listing the removable media on the device and
which apps have access to that media. In particular, if the user denied
your app access to the removable media, and clicked “Don’t ask again” on the
dialog, sending the user to the Settings app is the only way your app will
ever get access to that storage volume.
Apps can now help the user enroll a fingerprint, via
The change to yet another APK signing system means that there are new APIs
and deprecations if you check signatures at runtime. The former
PackageInfo is replaced with
signingCertificateHistory, which has
details about signing key revisions.
versionCode is moving from an
int to a
long, as apparently
232 app versions weren’t quite enough.
In addition to regular
KeyEvent processing in a
View, there is now the notion
of a “fallback”, in the form of
If the regular
KeyEvent processing does not consume the event, any fallbacks
are tried, before the
KeyEvent is handed to the window callback. It is not
completely clear where this would be useful, other than serving as a low-priority
handler of some
KeyEvent (i.e., if somebody else wants the event, have it, otherwise
I will use it).
You can call
Context to get an
Executor that will
execute its jobs on the main application thread. There are other ways of accomplishing
Looper and a custom
Executor implementation, but this is simpler.
JobInfo.Builder has a few new options:
setEstimatedNetworkBytes()provides a hint for how much bandwidth should be needed to execute this job. The idea is that jobs needing a lot of bandwidth may be postponed when the device has a lousy network connection, as excessive retries may chew up the battery.
setImportantWhileForeground()is strange. Based on the docs, it appears as though it will relax some of the restrictions imposed by Doze mode, if your app happens to be in the foreground at the time of the job. I guess this includes cases where the screen is off and your app was the last one to be in the foreground. Otherwise, if the screen is on and you are in the foreground, there should be no Doze restrictions in the first place.
setIsPrefetch()indicates that this job is pre-fetching some data for the user.
JobSchedulermay adjust your job’s timing as a result, either to invoke it as part of launching your UI (e.g., if the user clicks on your launcher icon) or if there is a lot of spare bandwidth (even if that bandwidth is metered and you ordinarily try to avoid metered data).
setRequiredNetwork()allows you to spell out the details of what sort of network connection that you need, based on capabilities and transport types, as defined by a
Where I Go From Here
Over the next several days, I will be putting Android P through its paces, in part by testing and re-raising a bunch of issues that probably haven’t been addressed yet.
An update to The Busy Coder’s Guide to Android Development, with coverage of Android P, should be out by the end of the month, if not sooner.