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 targetSdkVersion is 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 onProvideKeyboardShortcuts() in Activity, suggesting greater emphasis on hardware keyboard input

    • We now have PointerIcon and 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_SETTINGS to 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 X509TrustManager implementations. Some of those broken TrustManager implementations have been tied to trying to use self-signed certificates. Now, you can use debug-overrides to allow use of a self-signed certificate in your app, but only for debug builds. 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 ActivityInstrumentationTestCase2 and 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 file: Uri value. 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 file: Uri). There is penaltyDeathOnFileUriExposure() on 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 NetworkOnMainThreadException gets thrown. To deal with this:

    • If you receive Uri values from third-party apps, please do a decent job of supporting content: Uri values. This includes not being an idiot and thinking that these values all come from MediaStore or have file paths that you can derive. Please use openInputStream(), getType(), and the OpenableColumns with a ContentResolver to consume the content identified by the Uri.

    • If you send Uri values to other apps (ACTION_VIEW, ACTION_SEND, etc.), continue moving over to content: Uri values. Use FileProvider, perhaps supplemented by my LegacyCompatCursorWrapper (to help deal with the aforementioned idiots). At minimum, isolate your methods that create these Uri values into places that may make it easier for you to switch to content: Uri values in the future, in case FileUriExposedException starts getting thrown in production.

  • If you have been using inPreferQualityOverSpeed on 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 fromHtml() and toHtml() on the Html class. 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 Appendable in Java 8, one presumes that Android’s edition of these classes will continue to implement Appendable as well.

Other Bits of Goodness (For Some Definition of “Goodness”)

  • Google continues to pile on more storage options, this time in the form of ACTION_OPEN_EXTERNAL_DIRECTORY and android.os.storage.StorageVolume. Near as I can tell, the idea is to avoid READ_EXTERNAL_STORAGE and 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.

2016-03-10 UPDATE: Ian Lake pointed out that the “scoped directory access” documentation is now live.

  • android.auditing.SecurityLog seems interesting (logs adb shell commands, etc.).

  • AlarmManager now has in-process alarms. set(), setExact(), and setWindow() have versions that take an OnAlarmListener and call a callback method on it when the time arrives.

  • We now have commitNow() as an option, for executing a synchronous FragmentTransaction. commit(), by contrast, is asynchronous.

  • The android.webkit package now has ServiceWorker-related classes.

  • WebSettings has a 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.

  • shouldOverrideUrlLoading(WebView, String) on WebViewClient is deprecated, replaced with shouldOverrideUrlLoading(WebView, WebResourceRequest).

  • AbsSeekBar supports tick marks, mostly for the benefit of SeekBar, presumably.

  • Chronometer supports a countdown mode, including in app widgets via RemoteViews.

Unsolved Mysteries

  • There are ACTION_PACKAGES_SUSPENDED and ACTION_PACKAGES_UNSUSPENDED actions on 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 ACTION_QUICK_VIEW defined on Intent for 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 AutomaticZenRule is, but I imagine that Phil Jackson approves.

  • We have had isolatedProcess services for a bit, where they run in a separate permission-less process. N gives us externalService, which works in conjunction with isolatedProcess and 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 CONNECTIVITY_ACTION, 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.

Wiping out 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., JobScheduler), as a way of reining in power and memory consumption.

I have some difficulty believing that this will turn out well.

What Now?

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.