The CommonsBlog
Requiem for a Ranch
While elements will still remain, to an extent it appears that
Big Nerd Ranch is locking up the corral for good.
A long long time ago, I was their original Android app development trainer. Working on a contract
basis, I delivered training in Historic Banning Mills
(“come for the training, stay for the zipline!”) on many occasions. That included leading some
nature walks during breaks, helping folks figure out how to get cell service (tip: walk up a steep
hill to get out of the valley), and wrangling the occasional piece of luggage. Banning Mills was an
unexpectedly delightful spot to deliver training, one of the most entertaining locations that I
ever used.
Eventually, Big Nerd Ranch concluded that this Android thing might pan out, so they hired dedicated
staff and I moved on to deliver training through a series of other firms. Over time, they wrote
their own set of books, and you’ll probably recognize a few of
the authors for their contributions to the Android development community.
I remain grateful to Aaron Hillegass for taking a chance on me and giving me the opportunity to
deliver Big Nerd Ranch training. That played a significant role in my overall success with CommonsWare.
I even wound up doing some more contract work for them in 2018-19, albeit not in the form of
delivering training.
As their announcement post puts it, “The landscape of tech education has evolved significantly since our inception”.
That’s putting it mildly. Discontinuing their public bootcamps and their series of books is not surprising —
after all, I did much the same thing. Still, it’s tough to see and makes for a somber end to the day.
That said… maybe I’ll pick up a Stetson and put a propeller on the top, for old times’ sake. 🤠
—Jun 11, 2024
Random Musings on the Android 15 Beta 2
When Google releases a new beta, I rummage through
the API differences report,
the high-level overviews,
and even the release blog post,
to see if there are things that warrant more attention from
developers. 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.
This update contained a surprising amount of stuff for a second beta release. Usually by
now I have no more random musings, because there is little to review. Technically, though,
the first “platform stability” release is June’s, so Google just has some late-breaking changes.
What Might Break You
All apps ought to get private spaces,
though most should not have an issue. If you deal with work profiles, are a launcher, or are an
app store, you may have additional work to do. You might be interested in the new
ACTION_PROFILE_AVAILABLE
and ACTION_PROFILE_UNAVAILABLE
broadcasts.
If you use NDK code (yourself or via libraries), the 16KB page size
support needs to be investigated.
There is a new restriction on activity launches from back in a task’s stack.
This appears to be opt-in via android:allowCrossUidActivitySwitchFromBelow
. While it is
in the “only affects you if you target Android 15” documentation, it is unclear if that affects
the app doing the blocking, the app that might be blocked, both, or none (i.e., the docs are in
the wrong spot). There are a variety of other restrictions on semi-background activity starts
that hopefully won’t affect you.
screenWidthDp
and screenHeightDp
on Configuration
now include the depth of the system bars.
What Might Break You Next Year
The 6-hour-maximum foreground service
status for dataSync
and mediaProcessing
services
will only kick in once you target Android 15 or higher.
Similarly, the boot-time restrictions on what foreground services you can start
only appear when you target Android 15 or higher.
Your TextViews
may add more end padding
once you target Android 15, to better accommodate varying fonts and languages.
What Makes Me Go 🤨
They tightened some unsafe Intent
structures, but made it opt in via StrictMode
and possibly targeting Android 15.
There is a new contentSensitivity
attribute for View
,
though it is unclear what it controls.
There is a new shouldDefaultToObserveMode
attribute,
probably for <service>
… but we are not told what “observe mode” is.
There is a new systemUserOnly
attribute
for all components (activities, services, etc.). This feels like it is tied to private spaces,
to have some component be ineligible for use in a private space, but that’s just a guess,
because it is poorly documented.
There is a new form of requestPermissions()
that takes a device ID, and it is unclear what the “device” is in this context.
There is a new registerResourcePaths()
method on Resources
,
which seems like it allows for dynamically adding new resources, such as from some sort of
library.
PowerMonitor
“represents either an ODPM rail (on-device power rail monitor) or a modeled energy consumer”,
which I am certain makes some sense to somebody.
There is a new form of RemoteViews
that works off of DrawInstructions
,
but it is completely non-obvious how you create those instructions.
What Else Helps with Security
You can place an android:requireContentUriPermissionFromCaller
attribute on your
<activity>
element to enforce that the activity that starts yours and passes a Uri
has certain permissions with respect to that Uri
. Similarly, you can use
checkContentUriPermissionFull()
on Context
to see if some other app and/or user has
rights to a particular Uri
.
What Seems Nice
You can positively state what language your plain res/values/strings.xml
file is in via
a defaultLocale
attribute.
Presumably this goes on <application>
given its scope, but as is all too typical, that is
undocumented.
You now finally can find out what activity created yours, via getInitialCaller()
.
There is also getCurrentCaller()
,
which handles both onNewIntent()
and onActivityResult()
cases. Finally, there
is a getCaller()
method,
but it is unclear how that differs from getInitialCaller()
.
You can create customized previews for your app widgets via methods like
setWidgetPreview()
on AppWidgetManager
.
You can opt into custom vibration effects on a NotificationChannel
.
You can add up to 32 “debug tags” to a JobScheduler
job.
What Is Back From the Dead, Only To Die Again
Slices – a new UI option added several years ago that nobody every really seemed to use –
got some API changes! Alas, those changes are deprecation notices. I once again apologize to
those who attended a conference presentation on slices that I delivered years ago.
What Else Caught My Eye
There are a bunch of new permissions related to device policy controllers, such as
MANAGE_DEVICE_POLICY_BLOCK_UNINSTALL
.
There are new options on WindowManager
for “small cover screen” UIs.
—May 18, 2024
Random Musings on the Android 15 Beta 1
When Google releases a new beta, I rummage through
the API differences report,
the high-level overviews,
and even the release blog post,
to see if there are things that warrant more attention from
developers. 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.
As often happens with the first beta, we had a bunch of stuff deleted, meaning
it shipped in a developer preview then was removed. My assumption is that these
represent things that did not quite “make the cut” and are going to be revisited.
That said, we did get a decent bunch of new things as well.
What Might Break You Next Year
Edge-to-edge will be enabled by default on Android 15,
for apps that target Android 15. This means that new apps should be built from the ground up to
be edge-to-edge. Ideally, existing apps that do not fully support edge-to-edge should
take the next 1.5 years to adopt an edge-to-edge presentation. There is a new
android:windowOptOutEdgeToEdgeEnforcement
attribute,
probably for <activity>
, that you can set to true
to perhaps buy more time.
However, the docs for that attribute say that it will be deprecated and disabled
“in a future SDK level”. If they do that in next year’s Android 16, the attribute
will not buy you any meaningful time. Frankly, Google’s penchant for mandating their
particular preferred aesthetics is annoying — as somebody told me on Stack Overflow
over a decade ago, if I wanted somebody forcing their designs on me, I’d be programming
for iOS.
What Makes Me Go 🤨
They added E2eeContactKeysManager
.
On the one hand, it provides first-class support
for end-to-end encryption keys. On the other hand, it is tied to the user’s contacts
app, which seems rather limiting.
They added cover screen support
in an earlier developer preview, and the docs still refer to it. But
they removed the actual property (COMPAT_SMALL_COVER_SCREEN_OPT_IN
) from the SDK.
My guess is that the docs are wrong and this
feature was removed.
WindowManager
now has the concept of “trusted presentations”.
Basically, you can find out if your window is only partially shown or is being
shown mostly translucent. For a multi-window environment, I can see the value in
knowing these things, as it might impact how often you update your UI, or you might
pause media playback. The “trusted”, though, makes me wonder if there is a security
aspect.
They re-added FINGERPRINT_SERVICE
.
The blog post’s section on “Secured background activity launches” doesn’t seem to
point to anything new to Beta 1, so I am uncertain what they are referring to.
What Has Nothing to Do With Police Procedural Dramas
We now have access to a ProfilingManager
system service
for requesting certain types of profiling, including heap dumps and system traces.
What Else Is Interesting
ACTION_CHOOSER
, which powers the “share sheet”, now supports
EXTRA_CHOOSER_CONTENT_TYPE_HINT
.
The one documented value for this hint is
CHOOSER_CONTENT_TYPE_ALBUM
,
to hint that the content being shared represents an “album”.
There is a new SecurityStateManager
system service,
which can return the system patch level and kernel version.
A View
can now have an associated “credential request”
tied to CredentialManager
.
Wallet apps can now be set as the default recipient of NFC contactless payments via
a new wallet role.
The concept of parent and child activities is being unwound:
getParent()
and isChild()
on Activity
are deprecated.
There are better solutions for this nowadays, as multi-activity UIs slowly fade
from existence.
—Apr 13, 2024
Random Musings on the Android 15 Developer Preview 2
When Google releases a new developer preview, I rummage through
the API differences report
(even when Google does not seem to link to them 🙃),
the high-level overviews,
and even the release blog post,
to see if there are things that warrant more attention from
developers. 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.
This release is much larger than was the previous developer preview. It feels
like Developer Preview 1 was “low-hanging fruit”, to give developers an additional month
or so on the major changes for Android 15.
What Might Break You This Year
If your app is force-stopped, all pending intents are cancelled.
This change affects all apps, not just those targeting Android 15. I thought this
was already the behavior, but apparently it is not. For some devices that ship
with “task managers” that apply force-stop logic instead of only terminating app
processes, this change may really impact your users. Fortunately, at least,
you will now get ACTION_BOOT_COMPLETED
broadcast to your app so you can re-establish
anything that was canceled. However, there also is a new
ACTION_PACKAGE_UNSTOPPED
broadcast that you might consider. PackageManager
also now has an isPackageStopped()
function, so external parties can see if your app was force-stopped.
FINGERPRINT_SERVICE
was removed from Context
,
further impacting the already-deprecated FingerprintManager
.
What Might Break You Next Year
Once you target Android 15, you will
not be allowed to start some types of foreground services at boot time.
I can see this causing problems for a fair number of apps.
Also, once you target Android 15, if your app supports Arabic, Lao, Myanmar, Tamil, Gujarati, Kannada, Malayalam, Odia, Telugu or Thai,
then Android will use a taller font by default.
This may cause UI glitches, such as text being cut off due to lack of sufficient
vertical space.
What I Like of the Prominent Changes
Google taking PDF rendering seriously
is a nice improvement. PdfRenderer
was designed
for use in print previews, but developers have been trying to use it for arbitrary PDFs,
with varying results. And since many developers really do not want to use the user’s
preferred PDF reader, we were stuck with various workarounds.
The fact that the improved PdfRenderer
is being backported and apparently will be
wrapped in a Jetpack library also helps a great deal.
Support for deeplink filtering on query parameters and fragments
is something that developers have been requesting for several years, so it is good
that we are getting it, even if that is not something that can be backported.
Granular line-break controls,
so we can keep titles contiguous, is a long-awaited text rendering improvement.
Similarly, developers have been asking for how to find out
why the app was started for
quite some time.
Screen recording detection
provides a nice middle ground between being oblivious to screen recording and using
FLAG_SECURE
to block it entirely. Note that you need
a new normal
permission
to enable this capability.
What Makes Me Go “Hmmmmm…”
Resources
now has a registerResourcePaths()
method.
“This will collect the package resources’ paths from its ApplicationInfo and add them to all existing and future contexts while the application is running”.
Getting and setting the system bar colors is now deprecated.
What Else You Might Have Missed
Your manifest components (activities, services, receivers, and providers) can be
protected with android:systemUserOnly="true"
.
This is supposed to limit that component to at most one instance, and that instance
can only be interacted with by the system user. My hope is that we can use this for
specific places where we want to plug into the framework but want to preclude arbitrary
other apps from trying to use the component.
Through DevicePolicyManager
, eligible apps can mandate “content protection”
or can allow user choice.
In this case, “content protection” means “scanning for deceptive apps”. Similarly,
a device owner or policy owner can block NFC for certain users.
For app stores, ACTION_UNARCHIVE_PACKAGE
might prove interesting. Also, PackageInstaller
now has
a new set of APIs related to archiving apps.
There are new KeyEvent
key code values
for dedicated emoji picker and screenshot keys.
We can now limit drag-and-drop to be just within our app, even if we have multiple windows.
We can also specify an activity IntentSender
to use for unhandled drops.
—Mar 23, 2024
Random Musings on the Android 15 Developer Preview 1
Wow, it’s February again already?
When Google releases a new developer preview, I rummage through
the API differences report,
the high-level overviews,
and even the release blog post,
to see if there are things that warrant more attention from
developers. 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.
Last year, a common complaint was how small Android 14 felt. This year, Android 14
seems huge by comparison. Android 15 DP1 is so small, Google did not bother writing
a high-level overview of the changes, or at least it has not been published in an obvious
location. Google usually does a bit of “sandbagging” in early developer previews,
preferring to talk about changes one release later than when they are introduced.
Still, this total lack of docs is rather stunning.
What Gives Me Security Concerns
AccessibilityService
has long been used for things other than accessibility. Google
tried for a while to enforce this at the Play Store level, but if I recall correctly
they backed off.
AccessibilityService
now offers the ability to attach overlays to displays
(and to windows).
These are designed for UI that controls the accessibility itself, apparently.
I worry a bit that users will enable accessibility for an app for other reasons (e.g.,
help with playing some game), then get bitten by tapjacking attacks initiated by these
overlays. Hopefully, these overlays have system-supplied “chrome” that helps prevent
this.
See also getOverlaySupport()
on Display
.
What Claims to Have Integrity
FileIntegrityManager
has been
around for a few years, but without a lot of functionality. Now we can call
setupFsVerity()
for a File
,
enabling some amount of tampering detection.
However, the documentation for applying it (in setupFsVerity()
) is seriously confusing.
What We Also Got In Android 14, Sorta
Android 14’s QPR2 added support for partial screen sharing,
powered by MediaProjection
. This change is also folded into Android 15 DP1.
What Else Is Interesting
PackageManager
offers parseAndroidManifest()
.
This is designed for APKs that perhaps have not yet been installed. You get an XmlResourceParser
back, letting you traverse the manifest akin to using XmlPullParser
.
SystemClock
now offers uptimeNanos()
, the time since last boot, measured in nanoseconds.
JobManager
, via JobInfo
, now offers debug tags
and trace tags
for help with logging and traces.
MediaRoute2Info
now supports a bunch of additional remote media routes: to cars, computers,
game consoles, other phones, watches, tablets, or docked tablets.
We can now create notifications that have TV extensions,
presumably for cases where a phone is tied to an Android TV device.
The parade of screen densities continues, as there is now support for a 390-dpi density.
—Feb 17, 2024
Older Posts