Mark L. Murphy's Blog, page 23
June 4, 2019
Jetpack Compose: Optimism and Opportunity
When Google announced Jetpack Compose at Google I|O, I held out modest hope
that it might come to fruition. A re-envisioning of the Android UI rendering
system, with an eye towards React/Redux-style composable functions, sounded
promising. On the other hand, not everything that gets announced at Google I|O
winds up actually being released and having an impact. Last year���s excitement
surrounding slices would be a recent example.
(for those of you who spent time reading my stuff on slices��� um, sorry!)
However, yesterday, Apple announced their own take on this same sort of UI
construction system, called SwiftUI.
Now, I feel much more optimistic that Jetpack Compose will be ���for realz���.
There is nothing like a bit of competitive pressure to help spur things along.
My hope now is that Jetpack Compose, and the overall environment around it,
will not only update the UI rendering at the widget level, but will also help
us get broader adoption of ���encouraged��� UI modes.
At Google I|O, developers were ���encouraged��� to support dark mode and ���strongly encouraged���
to implement immersive or edge-to-edge designs, in support of new Android Q stuff.
Meanwhile, in the real world, we have difficulty getting designers and developers
to support landscape mode, which has been around since Android 1.0.
At our
current pace, widespread support for dark mode will come when the Sun goes out.
At that point dark mode will become rather important.
The lineup of UI things that we are ���encouraged��� to support overall is rather extensive:
Landscape mode
The full range of screen sizes, from tiny phones to large tablets/Chrome OS devices
Split-screen mode and freeform multi-window mode
Hardware keyboard/mouse input, including support for things like keyboard-based focus changes
Dark mode
Edge-to-edge designs (while still somehow not conflicting with the back gesture, which is something I may rant on some other time���)
And so on
That���s not even including substantially different form factors, like Android TV,
Android Auto, or WearOS.
Some of this is on developers. While a lot of these UI things come ���for free���
in part, some require some amount of opt-in from developers and most require some
amount of manual adjustment. Not everybody does that.
Some of this is on designers and the creators of design tools (e.g., Zeplin).
One way or another, designs need to take these things into account, so that the
developers know what is expected. If, instead, designs are based around a single
screen size in a single orientation in a single theme, either developers have to
make educated guesses about how to handle other scenarios, or developers have to take
steps to explicitly ignore those other scenarios. That���s why we wind up with
lots of apps whose activities are locked to portrait, which do not scale on
tablets especially well, which shine brightly in a dark room, etc.
Jetpack Compose and SwiftUI will change mobile UI development significantly.
This is a golden opportunity for us to try to get better adoption of these
other UI modes. Some of that might come from even more of it being handled ���for free���.
Some of that might come from just simpler APIs ��� for example, tying hot-key
sequences to particular UI elements. And some of that will (hopefully) come from
developers of design tools taking this opportunity to steer designers towards
designing around these various options.
I may be pinning too many hopes on Jetpack Compose. However, we only get this sort
of ���sea change��� every so often. Big shifts in technology are our best opportunity to
get big shifts in design and development processes.
In the meantime, perhaps the wizards of Cupertino could get Google doing more in
other areas. After all, you would think that Apple slices would be a thing.
June 3, 2019
"Exploring Android" Version 0.7 Released
Subscribers now have
access to an update to Exploring Android,
known as Version 0.7, in PDF, EPUB, and MOBI/Kindle formats, in addition to the
online reader. Just log into
your Warescription page and download
away, or set up an account and subscribe!
This update adds four more tutorials:
Generating a ���report��� and saving it to a location specified by the user using
the Storage Access Framework
Sharing that ���report��� using ACTION_SEND and FileProvider
Collecting a preference from the user
Downloading to-do items from a (fake) Web service using OkHttp and Moshi
Also, some dependencies were updated to newer versions.
In addition, the usual round of bugs were fixed.
At this point, I do not expect that I will add more tutorials. I do have some improvements
to make to the existing set, and I am waiting on some Jetpack releases before doing
that, so I am not in control over the timing.
Hopefully, there will be another update to this book in a month or two.
May 28, 2019
A Huawei Update
A week ago we heard about the impacts of the US trade ban affecting Huawei.
Since then, there has been quite a bit of reporting on it, including excellent
work by XDA Developers and
Ars Technica���s Ron Amadeo.
Here are some quick thoughts on what has transpired:
There is an argument going around that
US developers cannot allow Huawei to distribute their apps.
That is certainly true for any sort of bundled app distribution, as that would
require a contract between Huawei and the developer, and US developers will be precluded
from entering into such agreements. Similarly, US developers presumably are blocked
from listing their apps directly in Huawei���s own ���AppGallery��� channel.
However, the story gets a lot murkier for
app distribution channels ��� if the channel is outside the US (and therefore not
under US jurisdiction), can a US developer post apps there, and can Huawei deliver
apps from that channel? We may find out in the coming months, if
Huawei and Aptoide strike an arrangement.
Huawei seems to be moving forward with their own mobile OS.
Reportedly, it has Android app compatibility, which I imagine would work a bit
like how Chrome OS and Fuchsia run Android apps.
The US Department of Commerce has exempted Android security updates
from the ban for 90 days. It remains to be seen if this exemption will be
renewed.
One XDA author argues that Huawei cannot use the AOSP.
The argument is that Huawei cannot enter into contracts, and so Huawei cannot
agree to open source licenses. However, the extent to which an open source
license is a contract is up for debate
and would depend a lot on the venue of any copyright violation trial. From
a practical standpoint, nobody can really stop Huawei from using the AOSP without
such a trial, and that might take years to litigate. So, I am not worried about
this aspect very much.
While I focused on the software side, the hardware side has been a mess,
as many firms and organizations have indicated that they cannot continue
to have Huawei as a partner or customer. This includes non-US entities like
ARM. While Huawei
appears to have some mitigation plans, their crumbling relationships would seem
like they will be a major impediment for Huawei���s next generation of products,
if not the current generation.
On the whole, this still feels like it is a negotiating tactic as part of US-China
trade discussions. As such, while there will be short-term panic, over a bit
longer time horizon this all might get cleared up��� until the next trade dispute.
Huawei, and perhaps others, may try to find ways to loosen their dependency on Android
proper while still courting app developers. That will open up opportunities for
some and will cause problems for others. Time will tell.
May 22, 2019
DevFest DC!
On June 14th, I will be speaking at
DevFest DC on
the changes to storage in Android Q.
Though by then, my guess is that the presentation will be about the changes to storage in Android 10.
In reality, since many of the changes are opt-in right now, the presentation probably
will be about the changes to storage in Android 10 and next year���s Android R.
In other words, I���ll talk about something. Rakes, maybe.
For those of you who can attend live, I look forward to seeing you there! For
everyone else, I���ll attempt to screencast my presentation and will publish it if
I am successful.
May 20, 2019
Huawei, the Trade Ban, and Developers
Last week, the US government enacted some level of a trade ban affecting Huawei. 
The exact ramifications are still being deciphered, but
Reuters is reporting
that Google has elected to no longer ship the Play Store and the commercial
Google apps (Gmail, YouTube, etc.) to Huawei for future devices.
The Verge
and Bloomberg
offer their own confirmation of this, with elaborations that Intel, Qualcomm, and
other chipset manufacturers are also discontinuing sales to Huawei.
Google���s tweet, with its
emphasis on ���existing��� devices, lends credence to this reporting. And
XDA Developers
points to a statement from Huawei further suggesting that Google���s ban is in place.
Assuming that all of this is indeed what is going on,
here are some thoughts on this situation, with an eye towards how it affects you as a developer.
Right now, it appears that there will be no immediate effect on existing Huawei
devices and users. All phrasing suggests that the Play Store and related Google
proprietary tech will continue to be supported on Huawei���s past and current
devices. Google���s decision will impact future devices the most. It also means that
current devices may wind up not getting upgrades to Android Q or beyond��� but developers
are used to devices not getting Android OS upgrades. So, for
developers currently serving Huawei users, nothing should change in the immediate term.
The net effect would be that all Huawei devices would work like those that Huawei
distributes within China. Google does not license their suite for such devices.
Huawei has lots of experience in distributing devices outside of the Google Play ecosystem,
and so from a technical standpoint, this will be a significant headache but
should not be a show-stopper for Huawei.
The biggest Huawei software challenge is in figuring out how users will get their apps.
There are countless app stores in China, including Huawei���s own, filling the gap that the Play Store
left. Huawei may be able to use their own app store or tap on existing partners that have relationships with
major Western app brands to keep ���big name��� apps available on Play Store-less
Huawei devices. As Ron Amadeo notes,
the Amazon AppStore for Android likely is not an option, even if Huawei wanted
it, as Amazon is a US company.
If Huawei does go this route and distributes non-Google Play devices outside
of China, developers should pay attention to what app store(s) are included on those devices. They
may be an interesting distribution channel for your apps, supplementing the Play Store,
as Huawei is a major brand in many markets. With luck, those app stores will try
to make it easier for developers who have Play Store listings to cross-list in these
other stores.
This helps illustrate the problems that arise when developers focus exclusively
on the Play Store. While this is the first loss that the Play Store has suffered
since Google left China, it might not be the last, given the renewed interest
in antitrust/anti-competitive behaviors in recent years. Off and on for the past decade,
I have been all but begging developers to diversify their distribution options,
so that a problem with one channel (e.g., a Play Store ban) does not derail their
entire business. Perhaps Huawei will wind up helping to establish a clear alternative
to the Play Store, or at least highlighting the opportunities for developers with
other distribution channels.
This also helps to illustrate why I try to avoid relying upon the Play Services Framework.
Apps that are inextricably tied to Play Services can only be distributed through the
Play Store. That may make sense tactically but IMHO is a dreadful strategic decision
for developers. If you use Play Services, have two product flavors: the Play Services
one and other. Make sure that the other flavor can ���gracefully degrade��� your
app experience if Play Services becomes unavailable to you, for some of your users,
for whatever reason.
And, of course, this also points out the problems with app bundles, Google���s app
signing service, instant apps, and anything else that locks you into the Play Store.
If your app can conditionally use those things but can survive without them,
great! If your app cannot function without the Play Store��� again, IMHO, that was
not a wise strategic choice.
In terms of the OS itself, from a practical standpoint, this trade ban cannot block Huawei from working
with Android via the Android Open Source Project (AOSP). Even if the US government tried
to declare that Huawei cannot work with US-developed open source software, there
is no good way to stop it. Also, as with the previous ZTE ban, it is quite possible
that the ban will be lifted in the not-too-distant future, as a settlement in
the ongoing trade negotiations between the US and China.
However, from a strategic standpoint, this has the potential to push Huawei
into a long-term ���anything but Android��� approach, to go along with their past work
to help isolate themselves from dependence on US chips. Samsung has long been
trying to diversify its OS portfolio, with Tizen being the result. Huawei itself
has toyed with building another OS.
I can see Samsung, Huawei, and perhaps others (HMD?) forming a consortium to work on some
next-generation mobile OS. Samsung and
Huawei alone make up a third of the smartphone market, so if they ���teamed up���,
whatever OS they support would be very interesting.
Should Huawei ��� with or without other manufacturers ��� start pushing a
new mobile OS, the key will be getting apps for it. Users expect to be able to
install all sorts of different apps. Huawei may be able to convince developers
that they have the device distribution numbers to make it worthwhile. However,
it still has to be relatively easy to do. That could be through some sort of
Android compatibility layer, as BlackBerry tried. That could be through some
sort of Android runtime, akin to how Chrome OS works. That could be through
focusing on getting existing cross-platform toolkits (Flutter, React Native, etc.)
to support their new OS. That could be through ensuring that a Kotlin Multiplatform
approach would be a reasonable to support both Android and the new OS.
It could be through some combination of these, or
other similar solutions. But it has to exist ��� telling developers that they
have to start over from scratch will make it a tough sell outside of China.
TL;DR: In the short term, you may want
to use Huawei as a reason to make your Android app a bit less Google-dependent
in terms of tech (Play Services) and distribution (Play Store).
And in the medium term, consider what steps you might want to take to make it easier
to support some new OS ��� whether it is from Huawei, Google (Fuchsia), or whoever ���
when an opportunity arises.
May 16, 2019
"Elements of Android Q" Version 0.3 Released
Subscribers now have
access to Version 0.3 of Elements of Android Q,
in PDF, EPUB, and MOBI/Kindle formats. Just log into
your Warescription page to download it,
or set up an account and subscribe!
The chapter on scoped storage was completely overhauled, owing to the substantial
changes that showed up in Q Beta 3. Also, the material on MediaStore was pulled
out into its own chapter.
A new chapter was added on new limits on getting location data.
The chapter on RoleManager was downgraded to a section in
the ���Other Changes of Note��� chapter, given that it is unclear
if it will have any, er, role in Android Q.
Similarly, the chapter on bubbles was downgraded to a section in
the ���Other Changes of Note��� chapter, since it will not be
accessible to ordinary users in Android Q.
A few other sections were added in the ���Other Changes of Note��� chapter,
mostly as placeholders for future chapters on dark mode, gesture navigation,
and audio capture.
And everything was brought up to date for Q Beta 3.
The next update will be after the release of Q Beta 4. So far, Google has stuck
to their timeline, and Q Beta 4 is slated for early June.
May 15, 2019
The Death of External Storage: App Installer Bugs
The changes from Q Beta 1 to Q Beta 3 for how ���scoped storage��� behaves
have been stunning. I cannot remember a prior case where the behavior
between beta releases has changed quite so much. My guess (hope?) is that
this reflects a lot of rapid re-engineering work being done by Google developers,
and given where Q Beta 3 is right now I am grateful for that work.
However, whenever there is rapid re-engineering work being done, bugs have a tendency
to arise.
Braden Farmer pointed out one odd behavior
that highlighted three separate-but-related bugs.
App Installers Are Sandboxed
In theory, in Q Beta 3, android:allowExternalStorageSandbox="false" says ���give me
the classic view of external storage, please���. And, in general, it works. However,
there is at least one case where the system will override your override: if your
app gains the right to install other apps.
Specifically, if an app requests REQUEST_INSTALL_PACKAGES in the manifest, and
the user eventually grants that permission, at that point, the app gets a sandboxed
view of external storage, regardless of android:allowExternalStorageSandbox="false".
One moment you can view all of external storage, and the next moment you can���t.
My guess is that this is semi-intended behavior that is simply undocumented and will
remain around. I filed an issue to
try to get clarity around this.
App Privilege Downgrades Don���t Always Trigger Process Terminations
When the user revokes a runtime permission (e.g., READ_CONTACTS) that had been
previously granted to your app, Android terminates your app���s process. This forces
your app to go through the whole ���do we have permission?��� logic, so you find out
about the permission loss and can re-request it from the user if appropriate.
However, when the system overrides your override and forces your app to have a sandboxed
view of external storage, your app���s process is not terminated.
Literally, one moment you can view all of external storage, and the next moment you can���t,
without any warning.
IMHO, this is a bug, and having the sandbox forced upon your app should result in
process termination.
isExternalStorageSandboxed() Is Unreliable
For runtime permissions, we have checkSelfPermission() as a way to find out if
we hold the permission or not. For sandboxed external storage, we are supposed
to use Environment.isExternalStorageSandboxed() to detect whether we have a sandboxed
view of external storage or not.
This method works well��� except in the case where the system overrides your override.
Then, Environment.isExternalStorageSandboxed() will still report false,
even though your app was forced into a sandboxed view of external storage.
IMHO, this is a bug: Environment.isExternalStorageSandboxed() needs to be able
to take into account all reasons why your process may be forced into the sandbox.
While I hope there will not be any more edge cases like this, I would not be surprised
if more show up. In the meantime, we will need to just keep trying ���scoped storage���
and seeing its impacts. And, if your app has the ability to install other apps,
keep an eye on these issues and make adjustments as needed.
Many thanks to Braden for pointing this out!
May 13, 2019
The Death of External Storage: The Beta 3 Status
Last week brought us the Q Beta 3 release and Google I|O, and the
changes that Google promised
have largely come to pass. The Q Beta 3 documentation for 
scoped storage is a
substantial improvement, and the Google I|O presentation on it
was very welcome.
By default, apps with a targetSdkVersion of 29 Q
will have ���sandboxed��� external storage: an independent location from the external
storage from any other app. When sandboxed, your app has no ability to work with
sandboxes of other apps via the filesystem, and your app has no ability to work
with the ���real��� external storage that the user sees (again, via the filesystem).
Instead, you are steered to the Storage Access Framework and possibly MediaStore
for working with common content.
Users can get to an app���s
sandbox via Android/sandbox/, though it is unclear how many users will discover this.
And the contents of the sandbox are removed when the app is uninstalled, just as with
internal storage.
However:
Apps with a targetSdkVersion of 28 or lower will have normal external storage
access by default
Apps can add android:allowExternalStorageSandbox="false" to the <application>
element to opt out of the sandbox, ideally only while the app���s developers are making
changes to deal with the sandbox (note: this attribute name might change in Q Beta 4)
This gives developers a more reasonable timeframe for adjusting to these changes.
While Android R is likely to force the sandbox ��� at least on apps with newer
targetSdkVersion values ��� that means we have closer to 15 months to make
changes, not just 3.
As a community, we will need to work out the details for how to adapt everything.
For example, there is confusion over updating the MediaStore for metadata changes.
But now we have the time to do that.
This does not give you the luxury of sleeping on this work, though:
Apply android:allowExternalStorageSandbox="false" ASAP, lest your app ship
to Android Q users before you have the time to test the sandbox behavior
Once Android Q ships ��� or using the Q Beta releases if you wish ���
budget the time to play with your app with
android:allowExternalStorageSandbox="true" (opting into the sandbox) to see
what all breaks and needs to get rebuilt
However, I am very grateful that Google elected to slow down this change and give
us a clearer implementation for the near term.
May 7, 2019
Random Musings on Q Beta 3
Each time Google releases a new developer preview beta, I putter around
the API differences report
the high-level overviews,
and even the release blog post,
to see if there are things that developers should pay more attention to.
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 are now up to Beta 3, so this extends upon my notes for
Beta 1
and Beta 2.
So, while keeping one eye on the Google I|O keynotes and stuff, I took a look
at Beta 3.
So, What���s Up With Scoped Storage?
I���ll blog more about this later in the week, as I���m still sifting through what changed.
What���s Scary?
The next-generation gesture-based navigation scares me, as it does not work the
way that I had been expecting. I thought that this was just going to be an extension
of the 9.0 ���pill���, where a particular swipe on the pill would represent back
navigation. Instead, back navigation comes from an edge swipe, from either edge
of the screen, for the full screen height. And, if last year is any indication,
all Pixel 4 users may be forced to use this system.
If your app uses horizontal swipe gestures, this is going to suck for you and 
your users. Now, whether your gesture or the system back gesture gets triggered
will be based on fairly subtle distinctions of where the finger started the gesture.
You should start thinking about what you are going to do, should Google go ahead
with this plan. Do you:
Eliminate your horizontal swipe gestures?
Do something to visually distinguish where your horizontal swipe gesture works,
to help distinguish it from the invisible edge swipe area?
Override onBackPressed() and prompt the user ���did you really want to leave
this screen?���, if leaving the screen accidentally might make the user unhappy?
Leave it alone and hope for the best?
And, of course, if your app relies upon edge swipes ��� such as those
drawer apps that were all the rage a few years ago ��� you are in trouble.
Of course, those drawer apps are in trouble due to the apparent impending
deprecation of SYSTEM_ALERT_WINDOW.
If this will purely be an opt-in option for users for Q devices, then this is fine,
though developers should plan ahead for this perhaps being mandatory in R. If
this is mandatory for some device users for Q, as the 9.0 gesture navigation was
for Pixel 3 users��� we really should have received more warning about this.
What Was New Before And Is Now Newer?
Here are some changes to things that debuted in previous Q betas:
Background activity starts are really blocked now. Prior betas would
still launch the activity from the background but show a Toast indicating
that this would eventually be blocked. Now, the Toast is there (with an updated
message), and the activity is not displayed. Presumably, that Toast will
go away in a future beta. There is also a warning message (not an error) in
Logcat from ActivityTaskManager referring to Background activity start.
There are minor tweaks to the Bubbles API, removing the title and adding
a requested height option.
Similarly, there are minor tweaks to the BiometricPrompt.Builder API,
with a couple of methods renamed (e.g., setRequireConfirmation() is now
setConfirmationRequired()).
Along the same lines, some WebView-related classes and methods were renamed,
where ���renderer��� (e.g., WebViewRenderer) is now ���render process��� (e.g., WebViewRenderProcess).
RoleManager remains largely undocumented. However, it lost ROLE_GALLERY and
ROLE_MUSIC.
FEATURE_FOLDABLE was removed from PackageManager, indicating that we will
not have runtime ability to distinguish a foldable device.
NotificationAssistantService and NotificationStats were removed from the SDK.
The former surprises me, as I thought this was how Android was supporting adding
replies and actions automatically to notifications.
What Is Newly New In Beta 3?
For a third beta, there is more new than I would have expected.
Of particular interest:
The new audio capture API is a nice addition, particularly for screen recording
apps. Hopefully it will be easy for those apps to blend the video with the
audio, as those are captured separately. The audio capture APIs are an add-on
to the media projection APIs from Android 5.0 and will require user acceptance.
By default, apps with a targetSdkVersion of 29
Q will allow their audio to be recorded, though there are opt-out options if
this concerns you.
Notification.Builder now has setAllowGeneratedReplies() and
setAllowSystemGeneratedContextualActions() for controlling whether Google can
add replies and actions automatically to your notification. If I understood
correctly, these are by default set to true for MessagingStyle and false for
other types.
We now have a bit more information about dark mode
and how it affects apps. The automatic android:forceDarkAllowed="true" is
amusing but you would really want to test your app thoroughly, rather than assume
that this switch will yield perfect results. Their preferred approach is to use
DayNight themes, except that implies that most Android developers actually grok
the theme system, rather than simply cope with it.
bindService() now has a new four-parameter version that takes an Executor
as a parameter, where that Executor is used for the ServiceConnection callbacks.
By default, those callbacks occur on the main application thread, and this gives
you flexibility to move those to background threads.
Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS lets you bring up a screen
to let the user control your bubbles, if your app uses them.
Settings.Panel.ACTION_WIFI brings us another settings panel to display.
It is not completely clear what the decision criteria would be for showing this
instead of Settings.Panel.ACTION_INTERNET_CONNECTIVITY.
What Is Mystifying?
There are a set of methods around a ���synthetic app details activity��� in PackageManager.
It is not completely clear what this is referring to.
Similarly, there are methods and constants about ���whitelist restricted permissions���;
the documentation for these is rather confusing.
What Else Was Eyebrow-Raising From Day 1 of Google I|O?
I thought that the point of Jetpack was to streamline the number of recommended options
for various app development topics. So, I was surprised to hear about Jetpack Compose
and Jetpack ViewBindings. Partly, that is because they seem to be mutually contradictory:
ViewBindings is for layout resources, and Jetpack Compose seems to aim to eliminate
layout resources. Partly, that is because they both seem to step on data binding���s
toes, and data binding is part of Jetpack. I can see where ViewBindings and data binding
might coexist: use ViewBindings when all you want is generated
widget references, but use data binding when you want that plus binding expressions.
I hope that Google delivers a consistent and coherent story about when you use which
of these technologies��� and whether data binding is headed for the chopping block.
Otherwise, the major presentations (Google keynote, developer keynote, and Android
keynote) seemed to hold few surprises for Android developers.
Now What?
I plan to release another update to Elements of Android Q next week, to
update what I have for Beta 3 and to add more coverage of the changes to location
access.
And, as I mentioned earlier, I will write more about the scoped storage changes
later this week.
May 6, 2019
"Exploring Android" Version 0.6 Released
Subscribers now have
access to an update to Exploring Android,
known as Version 0.6, in PDF, EPUB, and MOBI/Kindle formats, in addition to the
online reader. Just log into
your Warescription page and download
away, or set up an account and subscribe!
14 more tutorials were added. This brings the book back up to where it was back
in Version 0.3, just updated for Kotlin, Android Jetpack, etc.
These tutorials:
Add dependency injection
Convert our UI over to a unidirectional data flow architecture, including
integrating ViewModel and LiveData
Implement persistence using Room
Integrate Kotlin coroutines for doing modifying the Room database contents
Add unit and instrumented tests
Along the way, the book was updated for Android Studio 3.4.
I have a few more tutorials that I want to add, so there will be another update
to the book in a few weeks. The exact timing will depend on if anything unexpected
is announced at Google I|O this week.



