Material Design: Strategic Considerations
There has been a lot of discussion regarding the adoption of Material Design aesthetics in Android apps, with developers breathlessly touting their work in this area. Newcomers to Android might conclude that Material Design must be The Most Important Thing in Android Development and therefore should be pursued immediately at all costs.
Not everybody shares this opinion
Hence, FWIW, here is my take on how you should be thinking about Material Design in the here and now. As usual, imagine a grain of salt approximately 30cm on a side, and take that grain of salt with my thoughts on the subject.
DO start considering the effects of Material Design upon your Android app.
Theme.Material is the dominant theme on Android 5.0 devices, and it should remain the dominant theme on future Android versions, at least for a while. There will be hundreds of millions of these devices in use, eventually, and you will want your app to look like “it belongs” on those devices. On those devices, not only will Google’s apps be employing
Theme.Material, but manufacturer-supplied apps should do so as well. While not everything on the device may necessarily adopt this theme, more than enough will that your app may stand out somewhat if your app does not and the user thinks that it should.
DON’T worry about this right away. Android 4.4 reached 30% of the Android device ecosystem after one year, and we have not seen that rate of adoption since Android 1.0. Odds are that it will be mid-2015 before Android 5.0 crosses the 10% threshold. As such, there just are not that many Android 5.0 devices out there, so worrying about those devices over the next several weeks is serious overkill.
DO plan on including Material Design impacts in your next UI refresh, and you should probably try to budget time for that refresh by the end of 2015 (by which time Android 5.0 might be 20-30% of the ecosystem).
DON’T blindly assume that you should be using a Material-ish look on all versions of Android. Your objective should be having an app that looks like it belongs on the device. Material-themed apps are highly unlikely to achieve majority status, let alone dominance, on pre-Android 5.0 releases. After all, device manufacturers are not going to be shipping Material-themed updates to built-in apps en masse, and there are plenty of apps out there that are still using pre-Holo themes. This is all on top of app that have no identifiable Android theme (e.g., most games). Certainly, there will be Material-themed apps running on Android 4.x devices, courtesy of Google and some other developers. But there will be enough Holo-themed apps that your app will not look out of place on Android 4.x any time soon, if ever. Hence, you have your choice of adopting Material Design across the board or not – user pressure is unlikely to be a major criterion any time soon.
DON’T fall victim to the “our app must look the same across all devices” mindset. Again, your app should look like it belongs on the device, which is why trying to ape an iOS look-and-feel on Android is rarely a good move. Most people do not have two Android devices, and only a small subset of those will have an Android 5.x device and an Android 4.x (or older) device. Hence, most of the people who will care about your app appearing identical on those devices will be in your meeting room discussing the issue. Few of your users will notice – they want an app that works, does what the user wants, and looks like it belongs on their device.
DO consider whether adopting Material Design across the board may offer engineering benefits. For example, if you have been heavily customizing widget colors in a
Holo-based theme, the tinting options provided by
appcompat-v7 may simplify your app a fair bit, reducing APK size, maintenance costs after the Material conversion, etc. Since your users are unlikely to be terribly concerned one way or the other, engineering considerations may help to “tip the scales” in one direction or another.
DON’T blindly assume that
appcompat-v7 will result in a simpler app, or that it should be the basis for all new apps. While the original
appcompat-v7 has now been around for 16 months or so, the new Material
appcompat-v7 is very young, and hence it has bugs, such as requiring extra work to function on Android 4.2.2 Samsung devices. Not all of those bugs are Google’s fault (e.g., the Samsung device issue was really caused by a screwy decision on Samsung’s part), but that comes as cold comfort to developers trying to distribute
appcompat-v7 apps. And, if you are comfortable with using themes based on
Theme.Holo for pre-Android 5.0 devices,
appcompat-v7 may be much more of an impediment than an advance.
appcompat-v7 is a tool, not a religion – use it where it clearly adds value to you and your app.
DO start planning for Google’s next major theme overhaul. Google, of course, is portraying Material Design as being The One True UI Design. Google will probably get irritated when people like me point out that
Theme.Material is the third major theme in the six-year production history of Android, and so assuming that
Theme.Material is “the be-all and end-all” of themes is unrealistic. Whether the next-generation theme is a refinement on Material Design or a larger overhaul remains to be seen. But you should be taking into account that we may well wind up going through this same process in, say, early 2018. The more you can isolate the theme-related changes from the rest of your app, the more likely it is that you will be able to accommodate future theme changes with less work.
—Nov 24, 2014
Android 5.0 Deprecation: splitActionBarWhenNarrow
UPDATE: If your app specifically uses
Theme.Holo (or themes inheriting from it),
splitActionBarWhenNarrow continues to work on Android 5.0. If you are using
Theme.Material — whether explicitly or because you did not specify a theme — then
splitActionBarWhenNarrow no longer works.
Gosh, it would be nice if deprecated features were actually documented as deprecated.
Alas, in the case of
splitActionBarWhenNarrow, this capability was quietly dropped in Android 5.0, but the documentation does not mention this. This goes beyond standard deprecation (“we think that there is a better solution that we would like you to use, but we will support this for the foreseeable future”). This is out-and-out “dead-ification”:
splitActionBarWhenNarrow no longer splits the action bar, on Android 5.0+.
splitActionBarWhenNarrow was never a guarantee, and certain devices and configurations would not split the action bar. For many apps, therefore, the only real impact will be with aesthetics, where now a bunch of action bar items wind up in the overflow in narrow scenarios, instead of being visible on the split action bar.
Where the problem becomes much greater is if you were more significantly relying upon action bar items being directly visible:
actionViewClass for items and do not have a suitable
onOptionsItemSelected() handler for the scenario
You assumed that your action item with the
ProgressBar or the like would always be visible, so users now no longer realize that some background operation is going on
You assumed that your
actionLayout would always be inflated and therefore crash when it is not inflated
And so on
While the official answer appears to be to use a bottom-aligned
Toolbar, getting a look equivalent to
splitActionBarWhenNarrow appears to be tricky, and the
Toolbar approach will not work prior to API Level 21 (unless you’re going the route of using
appcompat_v7, which has its own issues).
Again, Google is welcome to change whatever it wants, whenever it wants in Android. It is Google’s platform. It would just be nice if Google would actually tell people when they deprecate this sort of thing.
—Nov 18, 2014
The Busy Coder's Guide to Android Development Version 6.2 Released
Subscribers now have access to the latest release of The Busy Coder’s Guide to Android Development, known as Version 6.2, in all formats. Just log into your Warescription page and download away, or set up an account and subscribe!
This update is smaller than I would have liked, and I apologize for that. It contains:
Some basic Android 5.0 coverage, including notes about various deprecations
Information on how Android 5.0 changes notifications, including heads-up and lockscreen notifications
A new chapter covering
JobScheduler, the new Android 5.0
AlarmManager-with-more-brains system service
Added some limited material on
batterystats and Battery Historian, the other developer-facing pieces of Project Volta beyond
Rewrote much of the chapter on service binding and remote services, including a fresh set of examples and coverage of Android 5.0’s restriction on the use of implicit
Intents to bind to services
Updated the chapter on the Memory Analysis Tookit (MAT) to include how to use it from Android Studio
Rewrote parts of the first two tutorials to deal with changes introduced by Android Studio 0.8.14
There should be one more update to the book in 2014, probably in mid-December.
—Nov 17, 2014
Samsung/droidcon UK Presentations
I delivered presentations on memory management and Project Volta at the 2014 Samsung Developers Conference yesterday. The Project Volta presentation is one that I had originally delivered at droidcon UK 2014.
You can download the slides from both presentations. The droidcon UK 2014 video is reportedly available, but since Vimeo and I do not get along, I have no idea what it looks like. The Samsung conference sessions were recorded, but I do not know what their plans are with respect to publishing those videos.
—Nov 14, 2014
Random Musings on the Lollipop SDK
With each Android release, Google issues an API differences report, outlining things that were added, changed, or removed in a new API level compared to the previous one. This time around, for Android 5.0 theirs is a diff against the “L” Developer Preview, which is mildly annoying. Ideally, the comparison would be with the last production release.
UPDATE: There is separate differences report for API Level 20 to 21 that is probably a better choice for most people. Hat tip to Mike Evans for pointing it out!
I always review this to see what’s different beyond the sorts of changes that get more disclosure, coverage in Google I|O presentations, etc.
A few months back, I reviewed interesting changes in the “L” Developer Preview. Some of that stuff has stuck around for the Lollipop release, and more stuff has shown up that seem worthy of mentioning.
Here is what I see of interest that is new to 5.0, over “L”, with deprecations marked in bold:
While a compacting garbage collector was one of the hoped-for outcomes from the release of a production-grade ART, it looks that that is still a work in progress.
Somebody is probably already writing malware to make use of the screen capture and screen sharing APIs. If my reading between the lines is accurate, any activity using
FLAG_SECURE will not be captured, just as their thumbnails are not captured for the recent-tasks list. However, this is yet another reason to consider using
FLAG_SECURE, either on your own or at user request via a setting.
Those malware authors not working on the screen capture stuff are probably working on the screen pinning stuff, where apps can prevent the user from leaving their apps. While this, like the screen capture stuff, requires users to agree via a pop-up dialog, way too many users are likely to just say “yeah, um, whatever” and get screwed. And, if the documentation is accurate (and it’s probably not), to escape, the user has to press and hold BACK and RECENTS… but RECENTS is hidden and therefore cannot be pressed. Joy.
Neither the screen capture/sharing stuff nor the screen pinning stuff require any permissions. Nor do they require the double-opt-in pattern we have seen with things like
NotificationListenerService, etc. Instead, they just require tapping on a dialog to accept. As a result, users have no way of knowing, before installing an app, whether the app will try to do any of these things.
Google not only is offering a new Camera2 API, but they deprecated the original Camera API. I have no clue what I am going to do with my CWAC-Camera library…
The API overview says that “a new system-managed processing thread called RenderThread keeps animations smooth even when there are delays in the main UI thread”… with no other obvious documentation on the subject. It would be nice to know how this relates to our ways of checking for and fixing jank.
I’m going to need to run some tests to figure out WTF the
setAlarmClock() method is on
We now have a first-class
PackageInstaller for installing apps. I am not completely clear on whether or not this is a good thing, as I do not see any discussion of security.
Sticky broadcasts are now deprecated. There is no indication if there will be future changes to existing system-sent sticky broadcasts, like
ACTION_BATTERY_CHANGED, but it is something to keep an eye out for in future releases.
Here are items that I reported previously for the “L” Developer Preview that still seem to be applicable to Android 5.0 (with light prose fixups):
Action bar navigation, of all forms, is deprecated. This includes both action bar tabs and drop-down (“list”) navigation. It does not include the “custom view navigation” (e.g., browser address bar).
Part of the reason for this is that the action bar is being pulled out into something more readily manipulable by us developers.
Activity has a
setActionBar() method, taking a
Toolbar basically looks like a simplified action bar and can be placed in arbitrary spots elsewhere in your view hierarchy, in contrast with the locked-to-the-top action bar.
ActivityManager are now deprecated and will return a reduced result set on L and higher devices.
BatteryManager now gives us the ability to directly access battery information, without having to fuss with registering a
null receiver for
ACTION_BATTERY_CHANGED, albeit via a somewhat clunky
getLongProperty() API. Presumably, this is with an eye towards making
ACTION_BATTERY_CHANGED be non-sticky, given the sticky broadcast deprecation mentioned above.
bindService() now requires an explicit
Intent, if your
targetSdkVersion is set to 21 or higher.
We now have
getExternalMediaDirs(), which is a bit like
getExternalFileDirs(), but represent directories that will be scanned by the
A boatload of new stuff has been added to
DevicePolicyManager for those of you using the device admin APIs.
FragmentBreadCrumbs is now deprecated, for the six of you who were using that class. :-)
There is a new
LauncherApps class that helps simplify finding the relevant launchable activities. This is tied into the new managed profiles system.
MediaStore has been augmented with
MediaStore.Audio.Radio. It is largely undocumented, and so it is unclear if this is referring to streaming radio stations, classic broadcast radio (e.g., FM), or something else.
TOP_LEVEL_* patterns in
Patterns are now deprecated, presumably reflecting the fact that the number of top-level domains is expanding rapidly.
Android now has some amount of tracking of “power save mode”, with an
PowerManager and an
ACTION_POWER_SAVE_MODE_CHANGED broadcast. Whether this is for OEM-specific modes or for some new common power save framework in Android, I cannot say.
In what might be a first, something was “undeprecated”, specifically
Settings.Secure, as it was moved back there from
WebSettings now lets you control mixed-content mode, referring to whether
WebView should load insecure content from a secure origin.
—Oct 17, 2014