Random Musings on the N Developer Preview
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.
N is a bit of an “iceberg” release. What you see in the overviews is interesting, but there appears to be a lot more changing under the covers than may be obvious from those overviews. Partly, that is due to the switch to the OpenJDK, which I mused about previously.
Things To Start Thinking About Now
The multi-window support is going to get a lot of media attention, including in the short term. Moreover, multi-window support is opt-out, insofar as that your app will be resized by the user unless your
targetSdkVersionis N (today, presumably 24 eventually) and you specifically declare that you do not want the activity to be resized. There are some exceptions, notably activities that fix their orientation via
screenOrientation. But on the whole, your activity is getting resized, like it or not. Moreover, users are going to expect to be able to resize your activity. This is the sort of thing that you are going to want to test early and often, on various form factors.
Compounding the above is that Android appears to be coming to the desktop. This has been rumored for a bit. Multi-window support clearly is designed for desktop-style usage. While the media today might focus on split-screen mode, my guess is that come late May, the media will focus on “freeform” mode (“Manufacturers of larger devices can choose to enable freeform mode, in which the user can freely resize each activity.”) What Google calls “freeform” mode sounds a whole lot like windowed desktop applications. But, beyond just the multi-window support, there are other changes that, to me, indicate that Android is coming to the desktop:
We now have dedicated keycodes for cut, copy, and paste, plus
Activity, suggesting greater emphasis on hardware keyboard input
We now have
PointerIconand pointer-capture hooks in
View, suggesting greater emphasis on mouse/trackpad-style input
There is now
FEATURE_ETHERNET, and presumably a corresponding
<uses-feature>option, suggesting greater emphasis on hard-wired network connections
Doze mode was introduced in Android 6.0, to the consternation of some developers. At the time, it was limited to devices that were not moving (e.g., left on the nightstand overnight). As of Android N, Doze mode can kick in at any time if the device is not on a charger, even if it is moving. This will not change your app directly, but it will change how much your app is affected by Doze mode and the frequency of customer support issues that Doze mode may trigger.
One side-effect of the multi-locale support is that resource resolution gets a bit more complex. In particular, you need to put even more emphasis on having complete translations for language families, not partial ones. Right now, if you miss a string for some language family, the user will get whatever string you have in the default resource set (e.g.,
res/values/strings.xml). With N, the user might get a string from a secondary locale. If you have enough holes in your translation set, the user might get a whole bunch of different languages appearing on the screen, assuming that the resource resolution is happening at the per-string level as it has been to date. Make sure that your translations are complete, both when you introduce the translation and when you add new user-facing strings over time.
Also related to the multi-locale support, if you are one of those developers who has been overriding the user’s device locale within your app… test thoroughly on N, please.
The docs for the Data Saver feature state that your app needs to “gracefully handle restrictions to background data usage”. My interpretation is that Data Saver will behave a bit like app standby, insofar as you will have limited ability to access the Internet unless the user is actively using your app. This is another feature that you will want to test thoroughly.
To address Data Saver, you might be tempted to try using
ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGSto lead the user to add your app to the Data Saver whitelist, so you have normal background network access. However, bear in mind that Google has a similar feature for the battery saver whitelist… and trying to use that action got apps banned from the Play Store. At the moment, there is no similar language around the use of the Data Saver whitelist… but, then again, they didn’t tell you they were going to ban you for asking to be on the battery saver whitelist until after Android 6.0 shipped.
Overall, the network security configuration is seriously cool for helping secure your app. One useful side-effect ties into all those emails people have been getting about broken
X509TrustManagerimplementations. Some of those broken
TrustManagerimplementations have been tied to trying to use self-signed certificates. Now, you can use
debug-overridesto allow use of a self-signed certificate in your app, but only for
debugbuilds. If I am understanding the usage correctly, this means that you can transparently use the self-signed certificate when needed (e.g., hitting your test server) without risking supporting that certificate in production releases.
All the classic JUnit test case base classes, like
ActivityTestCase, are officially deprecated. If you have not done so already, budget time in the next year or so to move over to the JUnit4 testing support.
There is a new
FileUriExposedException. It will be thrown if you use a
Urivalue. What is not completely clear is under what circumstances it will be thrown. (UPDATE 2016-03-14: It is thrown pretty much if you try using a
Uri). There is
StrictMode.VmPolicy.Builder, which presumably triggers this exception. However, the vague wording suggests that perhaps N – or future versions of Android – might throw it by default, the way that
NetworkOnMainThreadExceptiongets thrown. To deal with this:
If you receive
Urivalues from third-party apps, please do a decent job of supporting
Urivalues. This includes not being an idiot and thinking that these values all come from
MediaStoreor have file paths that you can derive. Please use
getType(), and the
ContentResolverto consume the content identified by the
If you send
Urivalues to other apps (
ACTION_SEND, etc.), continue moving over to
FileProvider, perhaps supplemented by my
LegacyCompatCursorWrapper(to help deal with the aforementioned idiots). At minimum, isolate your methods that create these
Urivalues into places that may make it easier for you to switch to
Urivalues in the future, in case
FileUriExposedExceptionstarts getting thrown in production.
If you have been using
BitmapFactory.Options, that is now deprecated. The docs state that on N the flag is ignored because “the output will always be high quality”. In related news, all the children in Lake Wobegon are above-average, and Bruce Banner is always angry.
If you look at the N API differences report, you might have a slight panic attack and think that Google removed
Htmlclass. That appears to be a bug in how the API differences report got generated. The methods you are using are still there. However, they have been supplemented by additional methods that take flags as a parameter, offering greater control over how the HTML is interpreted or generated. This, in turn, suggests that this code is getting overhauled, which would be wonderful.
According to the API differences report,
StringBuilder(and the legacy
StringBuffer) no longer implement
Appendable. This appears to be a bug in the report, as the JavaDocs shows they both still implement
Appendable. Since they implement
Appendablein Java 8, one presumes that Android’s edition of these classes will continue to implement
Other Bits of Goodness (For Some Definition of “Goodness”)
- Google continues to pile on more storage options, this time in the
android.os.storage.StorageVolume. Near as I can tell, the idea is to avoid
WRITE_EXTERNAL_STORAGE, and possibly grant direct access to more of removable storage, by means of asking users for long-term fine-grained permission grants. This sounds reasonable. However, far too many developers are still coming up to speed on things like the Storage Access Framework, introduced back in Android 4.4, and the simultaneous restrictions on removable storage. All this will do is add to the confusion. Having the “For more information” link in the preview documentation lead nowhere is not a good start.
android.auditing.SecurityLogseems interesting (logs adb shell commands, etc.).
AlarmManagernow has in-process alarms.
setWindow()have versions that take an
OnAlarmListenerand call a callback method on it when the time arrives.
We now have
commitNow()as an option, for executing a synchronous
commit(), by contrast, is asynchronous.
android.webkitpackage now has
setDisabledActionModeMenuItems(), suggesting that you can block some of the standard cut/copy/paste operations, which is particularly useful if they interfere with the Web content that you are rendering.
WebViewClientis deprecated, replaced with
AbsSeekBarsupports tick marks, mostly for the benefit of
Chronometersupports a countdown mode, including in app widgets via
Intent. It is unclear what “suspended” means in this context. UPDATE 2016-03-14: Andriy Petruk pointed out that this probably ties into Android for Work.
There is an
Intentfor a “quick viewer for a URI or list of URIs”. It is unclear what such a viewer is, whether we can supply a viewer, and so on. But I’m sure that it’s quick.
It is unclear what
AutomaticZenRuleis, but I imagine that Phil Jackson approves.
We have had
isolatedProcessservices for a bit, where they run in a separate permission-less process. N gives us
externalService, which works in conjunction with
isolatedProcessand allows the service to “run in the calling application’s package”. It is unclear whether “run in the calling application’s package” refers to storage, permissions, or something else.
One Scary Thought
Future releases of Android may deprecate additional implicit broadcasts, as well as unbound background services. For this reason, you should avoid or remove dependencies on manifest-declared receivers for implicit broadcasts, as well as on background services.
This comes from the discussion over the changes to
where you can no longer register for it in the manifest.
The fact that Google might move more implicit broadcasts into the
registerReceiver()-only bucket does not surprise me. To some extent,
I am surprised that they haven’t done more of this to date.
What scares me is the suggestion that unbound services might no longer be supported.
If they had said that
FLAG_START_STICKY was deprecated, I could understand.
Or, if they had said that processes with services might be terminated
more quickly, I could understand.
IntentService and other uses of the command pattern with
services seems a bit over the top. Apparently, they are going to try
to have developers shoehorn all background work into discrete supported
categories, with specialized service subclasses (e.g.,
as a way of reining in power and memory consumption.
I have some difficulty believing that this will turn out well.
My guess for a release timeframe on N is August 2016, plus or minus a month. The developer preview came out a couple of months earlier than before; August would be a couple of months earlier than when the new major Android releases have shipped.
I’ll be starting to cover the N Developer Preview in the next book update, due out later this month.
Want an expert opinion on your Android app architecture decisions? Perhaps Mark Murphy can help!