Mark L. Murphy's Blog, page 24

April 28, 2019

The Death of External Storage: Correcting a Mistake

My post from last Monday
had a significant mistake. I wrote:




You cannot write to the standard directories available from Environment.getExternalStoragePublicDirectory(). So, you cannot write to DIRECTORY_DOWNLOADS or DIRECTORY_MUSIC or places like that.




That is incorrect ��� you can write to these locations��� sort of.



The reason for my mistake and the reason for the ���sort of��� qualification help to
illustrate what is going on with these external storage changes.



You can write to those directories, but the directories may not already exist
for your app��� even if they appear for the user.





If you have been working in Android from the early days, you may recall a time
when emulators (and occasionally devices) would not ship with the common external storage
directories already created. So, if you wanted to use Environment.getExternalStoragePublicDirectory(),
you would need to call mkdirs() on that File to ensure that the directory
existed before using it.



However, that missing-directory problem largely cleared up years ago. In my test
app, I foolishly did not bother trying to create the directories. After all,
I could see the directories when browsing the device. So, when I was getting
FileNotFoundException errors, I assumed it was a permissions thing.



Instead, even though I could see the directory, my app could not. Once I updated
my app to create the directory, those locations worked as expected��� more or less.





The ���more or less��� part is that, like most of external storage, what the app creates
is invisible to the user, whether via the Storage Access Framework
or via a USB cable.



So, it appears that each app has its own independent external storage,
which Google refers to as the ���isolated storage sandbox��� in
the documentation.
Two apps can write the same file to the same path with different contents, because
while each app thinks that it is writing to the one true external storage, instead it is
writing to its own external storage sandbox, which is independent of the external storage
sandbox of other apps.



This explains the problems with the Storage Access Framework and the USB cable.
Effectively, the the Storage Access Framework and the USB cable show what I will
call ���the user���s sandbox���, which is not the same sandbox as
that of any particular app.



The primary exception to this are the Context-supplied locations, like getExternalFilesDir()
and getExternalCacheDir(). There, the user���s sandbox includes
the per-app sandbox for those directories. While I doubt that
it is implemented this way, you can think of this as a symlink: the user���s
sandbox gets symlinks to each app���s sandbox���s entries in Android/data/, so the
user can see what the app sees within those areas.



From a privacy and security standpoint, this is a slick solution.



From a usability standpoint, it���s a problem��� if Google follows through on
its threat
and says that all apps, regardless of targetSdkVersion, will be subject
to these rules on Android R. Many legacy apps put their files on external storage
outside of the Context-supplied areas and expect users to be able to get to those
files. Not only does scoped storage not support this, if my analysis is correct,
scoped storage can���t support this without some substantial change to allow the
user to say ���show me external storage from the perspective of App X���. Since
we cannot do that even with adb shell run-as,
it may not be technically possible. Even if it is, from a UX standpoint, it is
unclear how this would be represented to the user (e.g., one USB volume per app?).



A regular targetSdkVersion solution may be required for usability. In other words,
only apps targeting 29 Q or higher would get
this behavior, with legacy apps writing directly to the user���s sandbox.
Since the Play Store requires an ever-increasing targetSdkVersion, most actively-maintained
apps will get to 29 Q in the not-too-distant future.
Yet the apps that are not being maintained, but still provide value, would still work as
they have.





Regardless of the circumstances, I apologize for my mistake. I should have been
more careful in my earlier tests.

 •  0 comments  •  flag
Share on Twitter
Published on April 28, 2019 06:07

April 25, 2019

The Death of External Storage: Serenity Now

In a rare bit of good news, it appears that Google will
apply normal targetSdkVersion rules to the new ���scoped storage��� in Android Q.



It appears that apps that have targetSdkVersion of 28 or lower will not be affected
by the external storage restrictions that exist on Android Q. Previously, such apps
would be affected if they were newly installed on Android Q devices. Such apps will
have some type of manifest entry to opt into scoped storage, or they will be affected
once their targetSdkVersion reaches 29 Q.



This is huge, for two reasons.



First, as Google points out, this gives active developers more time to update their
apps to deal with these changes.



Second, this will allow legacy apps ��� those not receiving updates ���
to continue working as normal��� at least for a while. Google is threatening that
all apps will need to use scoped storage on Android R, along the lines of what was
threatened with this release. Frankly, unless Google fixes things, that���s ridiculous
too. Right now, users would be unable to get at files saved by legacy apps
using other apps (via the Storage Access Framework)
or even via a USB cable.
Similarly, users cannot provide files to those apps, if those apps are expecting
them in what Google considers to be inappropriate locations (i.e., nearly everywhere).
This would mean that many of those legacy apps would simply no longer be useful.
Perhaps Google will address those limitations in time for Android R.



For actively-maintained apps, though, no matter what happens with Android R, you
still need to adapt to scoped storage. Next year, your targetSdkVersion will need to rise
to 29 Q in order to be distributed through the Play Store, courtesy of
Google���s version ratchet. But, you now have about 15 months in which to make those
changes, instead of 3.



I am grateful that Google is making this change, and I thank the engineers who
advocated for it.

 •  0 comments  •  flag
Share on Twitter
Published on April 25, 2019 13:55

April 22, 2019

The Death of External Storage: More of the Story

A month ago, I wrote a blog post about the changes in external storage on Android Q.



I intentionally skipped one finding, because it really seemed like a bug. However,
apparently, it is working as intended.



So, let���s revisit what you can do with the external storage filesystem in Android Q.



And, as a reminder: unless Google changes things, these rules affect all apps,
regardless of targetSdkVersion (except for apps already installed on a device that
gets the Q upgrade).



Where Can You Write?

You cannot write to the standard directories available from
Environment.getExternalStoragePublicDirectory(). So, you cannot write to DIRECTORY_DOWNLOADS
or DIRECTORY_MUSIC or places like that. Largely, that is because they already
exist and were not created by your app.



However, you can:





Create files in the root of external storage (Environment.getExternalStorageDirectory())




Create directories in the root of external storage




Create files in those directories that you created





Basically, if it already exists ��� such as directories that were created as part of
setting up the device ��� you have no write access. If you create it yourself,
though, you do have write access.



What Can You Read?

If you wrote it, you can read it.



However, that is it. You cannot read the contents of files or directories that
were created by other means, using filesystem APIs.



What Permissions Do You Need?

None.



No, Seriously, What Permissions Do You Need?

None. This was the part that I thought was a security bug. ��\_(���)_/��



If you have targetSdkVersion 'Q', or if you have targetSdkVersion 28, you can
write to the root of external storage and read back what you wrote, without any
permissions. Presumably,
this holds true for at least some older targetSdkVersion values, but I only
tested these two.



The reason why READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE are deprecated
is that all of external storage ��� except for existing files and directories ���
works like getExternalFilesDir():




You do not need any permissions
What you create is removed when the app is uninstalled or if the user clears storage for the app


What Can Other Apps Do With Your Files?

What you create and write in external storage via the filesystem is inaccessible to other apps
via the filesystem, no matter where it is.



What you create in getExternalFilesDir() will be accessible via the Storage
Access Framework, but what you create in the root of external storage is not.
As a result, anything you put in the root of external storage (or custom directories
off of the root) is private to your app, except to the extent that you expose
them via FileProvider or something.



What About the User and a USB Cable?

Similarly, what happens here depends on which portion of the external storage filesystem that you use.



For getExternalFilesDir() and kin:





Files and directories that you create are visible to the user




Files and directories that the user creates are visible to you





For the root of external storage:





Files and directories that you create are not visible to the user (MediaScannerConnection seems to not work for those files, and ACTION_MEDIA_SCANNER_SCAN_FILE
has been deprecated with no stated replacement)




Files and directories that the user creates are not visible to you





Even as a developer, adb does not show app-created files in the external storage root
directory. Nor does Android Studio���s Device File Explorer.



So, What Should I Do Now?

In general, my previous recommendations still hold up:





Use the methods on Context like getExternalFilesDir() to find places to write,
if you need to make the files available to the user via USB




Use the Storage Access Framework




Use the MediaStore for media




Use FileProvider to make your content available to other apps for outbound
requests (e.g., ACTION_VIEW and ACTION_SEND Intents)




If applicable, support ACTION_VIEW and/or ACTION_SEND in your manifest, so other
apps can use those Intent actions to send you content





If you have existing code that writes files to the root of external storage or
some custom directory off of it, that code will continue to run. However, the user
will be unable to access those files, except through your app. In general, it
will be better to migrate those to getExternalFilesDir(), if user access to those
files is important.





It is entirely possible that there are yet other combinations, scenarios, and
mysteries yet to be discovered. The key is that you should test your app early and often
on Android Q.

 •  0 comments  •  flag
Share on Twitter
Published on April 22, 2019 05:17

April 15, 2019

"Elements of Android Q" Version 0.2 Released

Subscribers now have
access to Version 0.2 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!



There are two new chapters, on bubbles
and share targets.



A few new items were added to the chapter on miscellaneous changes.



And everything was brought up to date for Q Beta 2.






The next update to this book should be after Google I
O and the release of Q Beta 3.
 •  0 comments  •  flag
Share on Twitter
Published on April 15, 2019 05:10

April 14, 2019

About Share Targets and Magic Names

If you are trying to use androidx.sharetarget:1.0.0-alpha01 and are wondering
why it���s not working correctly, you may not have used the right magic name.



androidx.sharetarget is a new AndroidX library that offers support for
Android Q-style share targets on older devices. It supplies its own
ChooserTargetService implementation (androidx.sharetarget.ChooserTargetServiceCompat)
that you point to, and that in turn implements the Android 6.0-9.0 Direct Share API.
It builds the ChooserTarget objects based on your Android Q share targets.



Android Q���s share targets are based on a combination of dynamic shortcuts
using ShortcutManager and a new <share-target> element in a static
shortcuts XML resource. Static shortcuts are identified in the manifest by
adding a android.app.shortcuts <meta-data> element to your launcher activity,
pointing to an XML resource.



Normally, you can name that XML resource whatever you want, so long as it is a valid
resource name.



For androidx.sharetarget, at least for 1.0.0-alpha01, you must name that resource shortcuts.xml.



That is because 1.0.0-alpha01 hard-codes that name, with a TODO comment
to fix it:



private static XmlResourceParser getXmlResourceParser(Context context) {
// TODO: Parse the main manifest to find the right Xml resource for share targets
Resources res = context.getResources();
return res.getXml(res.getIdentifier("shortcuts", "xml", context.getPackageName()));
}


So, with luck, this restriction will be lifted in a future update to
the androidx.sharetarget library.



In general, try to avoid magic names (such as shortcuts.xml). And where
you need a magic name, make sure you document it.

 •  0 comments  •  flag
Share on Twitter
Published on April 14, 2019 13:21

April 8, 2019

"Exploring Android" Version 0.5 Released

Subscribers now have
access to an update to Exploring Android,
known as Version 0.5, 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 seven more tutorials, covering things like RecyclerView
and the Navigation component. It also updates the tutorials for Android Studio 3.3.2,
though outside of the Android Gradle Plugin version, there was little to change.






I hope to get another update for this book out before Google I
O.
 •  0 comments  •  flag
Share on Twitter
Published on April 08, 2019 04:49

April 4, 2019

Random Musings on Q Beta 2

Each time Google releases a new developer preview beta, I wander through
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.



And if it feels like you just read one of these, it was
about three weeks ago.
Time flies.



What Got Bigger and Smaller at the Same Time?

Q Beta 1 introduced a ���roles��� system, whereby one app per role type could hold
a role and be granted superpowers. The documentation for roles was a mess, but
roles seemed to work.



In Q Beta 2, things got weird(er).



On the one hand, the RoleManager JavaDocs
show new roles: ROLE_ASSISTANT (presumably for the Assist API), ROLE_CALL_REDIRECTION
(presumably for forwarding all your robocalls to your arch-nemesis), and ROLE_CALL_SCREENING
(presumably for identifying the robocalls to forward to your arch-nemesis).



On the other hand, in the days leading up to Q Beta 2, an eagle-eyed subscriber pointed
out to me that the Q documentation page for roles vanished. Even stranger,
the scoped storage documentation
no longer mentions roles, and you used to need to hold certain roles to have
read-write access to certain content collections.



So, I have no idea what���s going on here. Q Beta 3 is due out around the time
of Google I|O, so perhaps we will get some clarity then.



Speaking of Scoped Storage, WTF?

The biggest change with scoped storage in Q Beta 2 is that it is enabled
by default. Once you flash your device or get your emulator up on Q Beta 2, you
should see that adb shell getprop sys.isolated_storage_snapshot results in
true. Now, more developers will start to encounter the stuff that
I blogged about recently.



However, roles are no longer required. There are now three ���strongly-typed���
permissions for read access to external storage:




READ_MEDIA_AUDIO
READ_MEDIA_IMAGES
READ_MEDIA_VIDEO


These are dangerous permissions, so you will handle them the same as READ_EXTERNAL_STORAGE.
If your app has targetSdkVersion set to Q, you can request those three permissions,
and you get the same level of access that an app targeting API Level 28 or lower
gets from requesting READ_EXTERNAL_STORAGE on a Q device. That is still very limited
access, only through the MediaStore, but it is better than nothing.



The docs now have a section on using content with the NDK,
advising you to use a FileDescriptor. What the docs do not tell you is that
you can only get a FileDescriptor if the content is backed by a file or something
else that can be mapped to a FileDescriptor. Not all content fits that description,
particularly for "rw" modes. Be prepared to gracefully degrade if openFileDescriptor()
returns null or throws a FileNotFoundException.



The recommended way for you to create audio, image, or video content that survives an
app uninstall is to use MediaStore. This gets a bit more complicated due to some
deprecations introduced in Q Beta 2:





getBitmap() is deprecated. Google steers you to ImageDecoder, though
BitmapFactory would also be an option if you wanted code that works on older
devices.




query() is deprecated. Google recommends using query() on ContentResolver,
which hopefully is what you were using already anyway.




insertImage() is deprecated, which surprises me. Google steers you to a new
���pending��� capability in MediaStore, which is almost completely undocumented.





And the security bug that I filed is still present. The bug report itself has
been ignored, outside of a couple of bots.



What Else Is Big?

Q finally got a user-visible feature of note: bubbles.



As a developer, I am grateful that this sort of floating interaction is
being standardized. Having be an add-on for notifications should simplify
development. And the fact that the actual content comes in the form of a
tiny resizeable Activity means developers get another nudge towards
being able to support split-screen and freeform multi-window modes.



As a user, I am grateful that I can turn this thing off.



What Else Do Manufacturers Hope Is Big?

The foldables march continues. The top-line announcement is that the emulator
is supposed to now have the ability to create foldable emulator images.



���Foldable��� is now also a formal system feature, in the form of
PackageManager.FEATURE_FOLDABLE and android.hardware.type.foldable. So,
if you create an app that requires a foldable (???), you can register in the
manifest to say that you need that system feature.



What Else Changed from Q Beta 1?

BiometricPrompt.Builder used to have a setEnableFallback() method, which has
been renamed to setAllowDeviceCredential().
That name is more reflective of
its role: to allow the user to use a PIN or password as an alternative to biometrics.
BiometricPrompt also now has a BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL
error code, which appears to be returned if you called setAllowDeviceCredential(true)
and the user has neither biometrics nor a PIN/password set up.



What Else Seems Intriguing?

ContentResolver now has a getTypeInfo()
method. Given a MIME type, you get back a TypeInfo object that contains
an icon, label, and description of the MIME type. This seems really handy for
lists of content. However, the API returns all non-null values, so it is
unclear what happens if you hand getTypeInfo() an invalid MIME type,
such as rutabaga/marshmallow.



ContentResolver also has a wrap() method.
You pass wrap() an instance of a ContentProvider, and wrap() returns
a ContentResolver that only talks to that provider. I can see this being
useful in testing ContentProvider implementations.



There is a new subtype of NotificationListenerService, called
NotificationAssistantService.
It ���helps the user manage notifications���, whatever that means. It appears
that a NotificationAssistantService has more power to modify the behavior
of a Notification than does an ordinary NotificationListenerService.



There are a handful of new methods, such as getAttributeResolutionStack() on View,
that appear to be here to help you determine how your various
styles and themes are affecting particular widget and attributes of those
widgets.



There is a new LocusId class,
described as an ���identifier for an unique state in the application���. What is
curious is that it is supposed to be a very durable identifier of that state,
not only surviving a reboot but surviving a backup/restore operation. That
pretty much requires it to be a server-side identifier, as nothing local to the
device might survive a restore operation. It is tied to an ACTION_VIEW_LOCUS
Intent. However, it is unclear in what scenarios this will be used.



What Else You Got?

I will be releasing an update to Elements of Android Q
in a couple of weeks. I will update what I have to reflect the changes wrought
in Q Beta 2, and I will add some more chapters, probably on bubbles and the
new share targets implementation.

 •  0 comments  •  flag
Share on Twitter
Published on April 04, 2019 06:43

April 1, 2019

"Elements of Android Q" Version 0.1 Released

Subscribers now have
access to Version 0.1 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!



This will be a small book, focusing on the changes introduced by Android Q.
Right now, it covers some stuff about roles and
the changes in external storage access.
As new beta releases of Q roll out, I will add more chapters plus update the
existing ones to reflect any behavior changes that I see in what I have covered
already.



According to the timeline,
we should be getting Q Beta 2 soon, and I will release a Version 0.2 of
this book in the weeks that follow.

 •  0 comments  •  flag
Share on Twitter
Published on April 01, 2019 06:43

March 29, 2019

The Death of External Storage: Where's Google?

Under the fairly innocuous title of
���scoped storage���,
Google has announced that external storage, as Android developers have used it,
effectively is dead, for Android Q and onwards.



I am going to spend some time on this over the course of the week, as this change
needs some attention:




Monday, I described what has changed and what you are supposed to use.
Tuesday, I covered the limited options for actually getting a file on external or removable storage.
Wednesday, I reviewed how you might still wind up with references to files��� that you cannot access
Yesterday, I offered some guesses as to why all of this is going down


Today, I am going to wonder what might have been.





In truth, I was not terribly surprised to see some changes in external storage in Android Q.
Particularly with Android 7.0���s FileUriExposedException, ���the writing was on the wall���
for the use of files, at least for app-directed content sharing with another
app.



I was surprised at the scope of the changes. That is not because I expected
something more limited, but rather I expected more warning for a change of
this magnitude.



It���s not like on the morning of March 12th, the day before the Android Q release, some manager
woke up and decided to greatly limit the use of external storage. This has been
in the works for months, if not years.



Of course, Google is not one for making statements about future changes. I did not
expect to hear ���oh, in the next version of Android, external storage will be
neutered��� in some conference fireside chat.



However, I would expect Google to be emphasizing heavily the eventual
alternatives: the Storage Access Framework and MediaStore. That way, when Android
Q shipped, they could point to all this prior material on those alternatives as
a way of helping developers move to them. Plus, some developers would already
have taken their advice and started that switchover before Android Q even showed up.



And if the plan for restricting external storage has been in place since
Android 7.0 ��� three years ago ��� I would have expected Google to be consistently promoting
the Storage Access Framework. An old saying in marketing is that it takes
nine ad impressions before the ad even really registers in the mind of the
viewer. While the science behind that is hazy, there is no question that
repetition of a message is important. So, I would expect the proper use of
storage to be a regular theme in presentations and posts.





But, if they did any of that, I���m not aware of it.



I see nothing in the 2017-2019 archives in the Android Developers Medium channel.



(and I sure hope somebody is keeping backups, as those posts seem like one Medium bad financial quarter away from being memory-holed���)



I can find nothing about this in the past few years��� of posts in the Android Developers Blog.



None of that came up at the 2018 Android Dev Summit.



I see no sessions on storage in the Google I/O 2018 agenda
or in the Google I/O 2017 agenda.



I also do not see any sessions on storage on the agenda for
this year���s Google I/O, though
not all sessions have been announced.



So, ��\_(���)_/��.





I really hope that there are two sessions on storage at this year���s I/O:





One would be focused on the Storage Access Framework, how you migrate away
from external storage to it, how you deal with
devices that lack it,
how you deal with buggy implementations, like 2019���s Google Drive,
etc.




The other would spend time on MediaStore and its role in replacing typical
uses of external storage





In addition, some blog posts would be nice.



I and others will do what we can to help developers figure out how to adapt.
However, official stuff from Google is orders of magnitude more valuable,
as it will get orders of magnitude more attention. Plus, I and others can then
point to it as Google���s recommendations.



To be honest, though, I am not hopeful that we will see any of that, unless
some new AndroidX library comes out that will help with the transition.
What we need always seems to be less than what we get.



We���ll muddle along. We always do. It���s just disappointing, that���s all.

 •  0 comments  •  flag
Share on Twitter
Published on March 29, 2019 04:51

March 28, 2019

The Death of External Storage: But Why?

Under the fairly innocuous title of
���scoped storage���,
Google has announced that external storage, as Android developers have used it,
effectively is dead, for Android Q and onwards.



I am going to spend some time on this over the course of the week, as this change
needs some attention:




Monday, I described what has changed and what you are supposed to use.
Tuesday, I covered the limited options for actually getting a file on external or removable storage.
Yesterday, I reviewed how you might still wind up with references to files��� that you cannot access
Today, I���ll offer some guesses as to why all of this is going down




Android 4.4 locked down removable storage and introduced the Storage Access
Framework. Android 7.0 added FileUriExposedException to try to steer developers
away from file:// Uri values. Now, Android Q blocks access to most portions
of external storage.



So, why?



Here are some possible reasons. Note that I have no inside information, and so
these are educated guesses, nothing more��� except for the first one.



The Official Reason: Clutter

Quoting the Q release notes: ���To give users more control over their files and to limit file clutter, Android Q changes how apps can access files on the device���s external storage.���



Perhaps Marie Kondo visited the Googleplex. I hope that the Android statues sparked joy.



Jokes aside, I can see arguments for this reason. I have complained about developers creating
app-specific directories or files at the root of external storage for years.
That behavior is roughly analogous to Windows programs putting stuff in the
root of the C: drive, and Microsoft got developers away from that quite some time
ago, in part due to clutter. So, it is not shocking that Google would make moves
in this area.



However, locking down all of external storage seems excessive to support
this reason. Locking down the root of external storage might have sufficed.



The Preferred Reason: Privacy and Security

Let���s face it: Android���s security reputation is in tatters. If you pay much attention
to the infosec community, you���ll know that Android is not well-regarded.



Part of the problem has been data promiscuity. Even with the advent of runtime
permissions in Android 6.0, lots of apps still requested READ_EXTERNAL_STORAGE
and WRITE_EXTERNAL_STORAGE. Those apps have complete run of external storage,
including examining files created by other apps.



So, for example, without locking down external storage the way they did, Google
had little ability to prevent apps from scanning the user���s photos and looking
for geotags. Coupled with FileObserver, this could serve as a rough-cut way
of occasionally getting the user���s current location. And just examining the
historical photos could be illuminating. If lots of photos are taken over a long
span of time in the same geographic area, it is likely that the user lives
there and is taking pictures of local places and events.



Privacy and security experts have complained for years and years about this
sort of app behavior. Most likely, the external storage lockdown is there in part to address
these concerns.



The ���Google ��ber Alles��� Reason: Promote Cloud Storage

The leading API for accessing external storage now becomes the Storage
Access Framework. One feature of the Storage Access Framework is that it
treats local and remote storage as the same, with a consistent API for both.
Your app does not really care whether the content that it works with is local
or remote ��� your app just cares about reading and writing that content.
With the Storage Access Framework, your app can focus on the content, and
the user can work with documents providers to arrange to get you the desired
content, no matter where it resides.



Of course, Google would like for it to reside on Google Drive.



The Storage Access Framework means that the Google Drive option is presented to
the user on every storage access request, at least for those users who have
set up Google Drive for their device���s Google account.



This is not a Google-exclusive thing. Compared to other things, like push
messaging, offering a cloud-based DocumentsProvider is something anyone can
do. The API is a bit arcane and suffers from limited documentation, but we can
say that about quite a bit of Android. Other cloud storage providers can appear
alongside Google Drive, if those providers choose to implement a DocumentsProvider.
However, outside of some manufacturer-specific deal, the only pre-installed
provider is Google Drive, so it gets a bit of premium placement as a result.



The James Tiberius Kirk Reason: Enterprise Support

(with my hairline, you might have thought this would be the Jean-Luc Picard Reason,
but I���m honoring the classics today���)



Enterprises run on networked file servers. Windows has long had more-or-less
first-class integration of file server-based storage for a very long time.
The most flexible way for Android to support that is through a DocumentsProvider-based
API (as opposed to lower-level Linux-based options). So, it is possible that
closing off of external storage is being done in part to promote Storage Access
Framework adoption, with an eye towards enterprise storage along with cloud storage.



The Current Compatibility Reason: Chrome OS Integration

Chrome OS is locked down tight as a drum. That���s why when Android apps were
added as an option, you had a lot of visible seams in the integration. Perhaps
none were bigger than storage, where the only shared location between Chrome OS
and Android is the Downloads/ directory on external storage. The rest of
Android���s external storage has been inaccessible to Chrome OS.



Perhaps the external storage lockdown in Android Q is to make it easier for
Google to more tightly integrate how Android apps and Chrome OS apps perceive
local device storage.



The Future Compatibility Reason: Fuchsia

Let���s assume for the moment that Fuchsia
is real and it is spectacular.



If Fuchsia represents Google���s longer-term OS, it stands to reason that some
of the recent Android changes ��� such as the external storage lockdown ���
are being made to improve compatibility with Fuchsia. If Fuchsia will run Android apps,
then Google once again has the integration issues that they ran into with
Chrome OS.



Perhaps the external storage lockdown is being done with an eye towards how
Fuchsia apps work with local device storage.





These are mostly speculation. I doubt that we will ever get much more than the
official ���clutter��� reason for this change. But this list shows that Google has
plenty of justification for this move, no matter how painful it may be for
developers (and, to an extent, users) in the near term.



Tomorrow, I will wrap up this blog post series by wondering why this predictable
change still seems to have caught developers by surprise.

 •  0 comments  •  flag
Share on Twitter
Published on March 28, 2019 05:08