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 toImageDecoder
, thoughBitmapFactory
would also be an option if you wanted code that works on older devices. -
query()
is deprecated. Google recommends usingquery()
onContentResolver
, which hopefully is what you were using already anyway. -
insertImage()
is deprecated, which surprises me. Google steers you to a new “pending” capability inMediaStore
, 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.