Mark L. Murphy's Blog, page 10

October 31, 2021

Android 12 Wallpaper Changes Recreate Your Activities

Following up on my previous post,and thanks to a crucial tip from cketti,it now appears that we know more about what is going on with wallpaper changeson Android 12: your activities will get recreated, akin to a normal configuration change,but without an opt-out mechanism.

The Original Change

cketti pointed me to this AOSP commit.It provides the engine for what I described above: it forces activities to berecreated:

Activities will be scheduled for restart via the regular life-cycle.This is similar to a configuration change but since ApplicationInfochanges are too low-level we don���t permit apps to opt out.


The catch is those last seven words: ���we don���t permit apps to opt out���. This isnot an actual configuration change that you can opt out of via android:configChanges.

The original rationale for this was for ���runtime resource overlays andsplit APKs���. I am not 100% certain how split APKs come into play here, butruntime resource overlays (RROs)represent a mechanism for system-wide theme changes. So itis not surprising that Google hooked into that mechanism for Android 12 wallpaper changes.

Confirming the Wallpaper Effect

You can determine after the fact that this has occurred by comparing Configurationobjects from before and after the activity recreation. We do not get an onConfigurationChanged()callback in the Activity, because we are not opting out of this recreation process. However, theConfiguration object used by our previous activity instance will differ in one keyway from the Configuration object used by the replacement activity instance.

For example, here is a trivial ViewModel that holds a Configuration?object:

class MainViewModel : ViewModel() { var originalConfiguration: Configuration? = null}

In this activity, I save off the original Configuration object in the viewmodelif originalConfiguration is null. Otherwise, I use diff() on Configurationto examine the difference between the original Configuration and the now-current one:

class MainActivity : AppCompatActivity() { private val vm: MainViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // other good stuff goes here if (vm.originalConfiguration == null) { vm.originalConfiguration = resources.configuration } else { val diff = resources.configuration.diff(vm.originalConfiguration) Log.d("WallpaperCCTest", "matches CONFIG_ASSETS_PATHS? ${(diff.toLong() and 0x80000000) != 0L}") } }}

diff() returns a bitmask of the elements of the configuration that differ betweentwo Configuration objects. The magic 0x80000000 comes fromthe Android source code��� it is ActivityInfo.CONFIG_ASSETS_PATHS, a constant that is marked with @hide:

/** * Bit in {@link #configChanges} that indicates that the activity * can itself handle asset path changes. Set from the {@link android.R.attr#configChanges} * attribute. This is not a core resource configuration, but a higher-level value, so its * constant starts at the high bits. * @hide We do not want apps handling this yet, but we do need some kind of bit for diffs. */ public static final int CONFIG_ASSETS_PATHS = 0x80000000;

On Android 12, after a wallpaper change, usually the else block is run and the bitmask testcomes out true. I say ���usually��� because in my testing, it seems like there is anoccasional hiccup where the wallpaper changes and the activity is left alone and not recreated ��� I havebeen getting this perhaps one time in ten, and I have not identified the pattern.

My code shown above compares the current Configuration with the original one ��� forproduction use, you probably should track the last-seen Configuration and compareit with the current one.

UPDATE: Based on this comment by Nguy���n Ho��i Nam,you can detect this via onConfigurationChanged() in a custom Applicationsubclass. However, that will get called for every configuration change; you would still needto use diff() or similar techniques to determine if the configuration change came fromthis sort of scenario.

Mitigation Approaches

You could use the above diff() approach to detect that your activity was recreateddue to something like a wallpaper change. There are other things thatwill trigger the same effect, as the RRO system was contributedby Sonyback in 2017. Android 12 wallpaper changes may increase the frequency of this occurrence somewhat.

However, there is no obvious way to prevent this destroy-and-recreate cyclefrom occurring. If anything, the various code comments suggest that Google + Sonyspecifically precluded the possibility of apps blocking it. That may be whyGoogle elected to go this route rather than introduce a new configuration change type.

Even if your app tries to opt out of all configuration changes ��� something the Jetpack Composeteam at Google has been espousing ��� your activity can still be destroyed and recreatedwithout process termination. Ideally your app handles that case, even thoughnot all apps do, apparently.

 •  0 comments  •  flag
Share on Twitter
Published on October 31, 2021 06:27

October 30, 2021

Wallpaper Changes = Configuration Changes?

This Stack Overflow question pointed outan interesting problem with the shipping Android 12 release: changing wallpaper resultsin an effect that feels a lot like a configuration change.

Specifically:

Start an app

Use system HOME navigation to return to the home screen

Change your wallpaper

Return to the app��� and the activity will be destroyed and recreated

As the person who asked the SO question suggests, this feels like it is tied to Material You.I can see perhaps having a configuration change for this scenario, for apps that wantto react to the new colors stemming from the new wallpaper.

However, at the same time, this does not seem to respect any android:configChangevalues, even the undocumented ones.

����

I can see a few possibilities for what is going on:

This is a configuration change, and there is an android:configChanges valuethat we can use, but that value did not make it into the documentation or thespots in the source code that I checked

This is a configuration change, but Google elected not to have an android:configChangesvalue for it

This is not a configuration change, but something that behaves a bit like one

For apps that rely upon avoiding the automatic destroy/recreate cycle of configurationchanges, whatever this is can cause some serious problems.

If you have some insights as to what is going on here, post an answer,add a useful comment, orjust reach out!.

 •  0 comments  •  flag
Share on Twitter
Published on October 30, 2021 13:25

October 27, 2021

Random Musings on the Android 12L Developer Preview

Each time Google releases a new developer preview, I rummage throughthe API differences reportthe 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 developermight reasonably use, along with things that may notget quite as much attention, because they are buried in the JavaDocs.

But, let���s face it: this is just really weird.

We have not had a point releasesince 8.1, and the ���12L��� naming convention isn���t exactly semantic.Plus, ���12L��� isn���t the only name ��� in other places, it is referred to as���Sv2���, presumably short for ���version 2 of the ���S��� name that we stopped using a fewmonths ago���.

What Stands As the Biggest Change For Most Developers

getExternalStorageDirectory() and getExternalStoragePublicDirectory()on Environment are now undeprecated. DATA in MediaStore.MediaColumnsis also undeprecated.

I don���t know what to make of this.

What Changed Elsewhere in the API

Frankly, not much. There is a new Spatializer class, related to sound spatialization:

Sound spatialization simulates sounds originating around the listener as if they were coming from virtual speakers placed around the listener.


There are a handful of other related audio changes.

Beyond that, we have:

Some accessibility changes related to drag and drop

New support for system and pre-installed apps related to two-panebehavior in the Settings app

Some tweaks to wallpaper behavior, particular pertaining to foldables

Some changes to VoiceInteractionSession

���and that���s really about it.

What Would Be Nice If Google Really Documented Someday

Google changed some of the behavior of media projection. Theirexplanation of what changedis opaque, but it does link to a new pagewith a few sections that briefly explain what media projection is.

IOW, I still suspect that I have written more about media projectionthan has all of Google combined, which is sad.

What You Should Focus On

There is a very good chance that your app only supports portrait mode.If so, and if your app might run on tabletsor foldables, pay attention tothe letterboxing effectsthat now get applied if the manufacturer so chooses.

If you had been trying to avoid split-screen mode,you are out of luck on larger-screen devices ���instead, you may be letterboxed.

If you would prefer to more actively attempt to support larger screens,activity embeddingappears to make it simpler for you to show more than one activity on a largerscreen at a time. The API support for this must be in Android 12, though, giventhe limited changes in 12L/Sv2/whatever this is.

On the whole, though, the average developer does not seem to care much about tablets, letalone foldables or Chromebooks. If you do, then 12L is important to you, and you shouldstart experimenting with the emulator��� since it is unclear when there will be hardwaresupport for 12L. Presumably Google���s foldable will ship in the coming months, andapparently 12L will come quickly to the Lenovo P12 Pro,but is unclear how soon other manufacturers will ship 12L to anything of relevance.

 •  0 comments  •  flag
Share on Twitter
Published on October 27, 2021 16:44

October 11, 2021

���Elements of Android Jetpack��� Version 2.2 Released

Subscribers now haveaccess to an update to Elements of Android Jetpack,known as Version 2.2, in PDF, EPUB, and MOBI/Kindle formats, in addition to theonline reader. Just log intoyour Warescription page and downloadaway, or set up an account and subscribe!

This is a minor update, primarily to support Android Studio 2020.3.1 Arctic Fox.

This update adds coverage of using StateFlow as an alternative to using LiveDatain Kotlin-based Android projects. It also replaces BroadcastChannel with SharedFlowin the one Kotlin sample that used SharedFlow.

And, in addition to all of that, there are the usual roster of bug fixes, to the prose andto the sample code.

 •  0 comments  •  flag
Share on Twitter
Published on October 11, 2021 06:35

September 25, 2021

Turning the Page

The Warescription program will be ending at the end of 2021.All subscribers will get book updates and access to the other Warescription benefitsthrough then. I am expecting to put out one more update to Elements of Android Jetpackand one or two more of Elements of Android Room.

And, by the end of the year, I plan to release the final editions of all of my booksunder a Creative Commons license.

Three years ago, I had a choice:

I could put my first generation books, headlined by The Busy Coder���s Guide to Android Development,on a shelf and start over from scratch to cover Kotlin and the Jetpack libraries

I could shut down the Warescription

I took the first option, because I am stubborn and did not want the Warescriptionto end that way.

Earlier this year, I had a similar choice:

I could plan to write 1-3 books on Jetpack Compose and rewrite around 2,000 pages of second-generationmaterial to use Compose UI

I could shut down the Warescription

This time, I am taking the second option. I have few readers now, and Compose-ifiying my bookswould be a lot of work benefiting fairly few people.

Besides, after over 13 years of writing and updating books about Android, I���d like to try some other approaches.I���d like to do more with this blog, for example. I will still curate the jetc.dev newsletter for Jetpack Compose development.I���d like to get back into my workwith code transparency.And I have a few more things in mind beyond that.

So, this isn���t goodbye ��� it is just hello to different stuff, perhaps for different people.

 •  0 comments  •  flag
Share on Twitter
Published on September 25, 2021 06:53

September 14, 2021

���Exploring Android��� Version 2.2 Released

Subscribers now haveaccess to an update to Exploring Android,known as Version 2.2, in PDF, EPUB, and MOBI/Kindle formats, in addition to theonline reader. Just log intoyour Warescription page and downloadaway, or set up an account and subscribe!

The book is now up to date for Android Studio Arctic Fox and newer versions of allthe dependencies.

The biggest change, in terms of the actual content, is switching to use StateFlowand SharedFlow instead of LiveData and BroadcastChannel. There were some otherminor tweaks to view binding behavior in fragments, and the newer Koin requiredremoval of annotations added in the previous release.

A corresponding update to Elements of Android Jetpack should be out in October.

 •  0 comments  •  flag
Share on Twitter
Published on September 14, 2021 05:08

August 9, 2021

���Elements of Android Room��� Version 0.6 Released

Subscribers now haveaccess to Version 0.6 of Elements of Android Room,in PDF, EPUB, and MOBI/Kindle formats. Just log intoyour Warescription page to download it,or set up an account and subscribe!

This update adds two more chapters, covering:

Creating database views

What���s new in Room 2.3.0

Also, the chapter on paging was updated to Paging 3.

In addition:

A bunch of dependencies were updated, notably Room itself

Various bugs were fixed

 •  0 comments  •  flag
Share on Twitter
Published on August 09, 2021 04:56

July 18, 2021

Inside Code Transparency: The Verification Process

A week ago, I looked at the contents of the JWT filecreated by the code transparency process. Today, let���s peek at how that getsverified.

bundletool Commands

Last week, when I showed you a bundletool command to add code transparency, I useda command that used a Java keystore directly. That does not seem to be an option forthe verification step. For that (or for adding code transparency), you need anactual certificate file. You can obtain one from your keystore using keytool:

keytool -export \ -alias WhateverAliasYouUsed \ -keystore /path/to/your/keystore.jks \ -rfc \ -file /path/to/your/exported.cert

You can then use the check-transparency command to verify the contents of��� something.The --mode option indicates what the ���something��� is. --mode=bundle says that youare verifying an App Bundle, such as one created by you or your CI server:

bundletool check-transparency \ --mode=bundle \ --bundle=/path/to/your/AppBundleWithCT.aab \ --transparency-key-certificate=/path/to/your/exported.cert

If you leave off the --transparency-key-certificate option, bundletool willprint the SHA-256 fingerprint of the certificate:

No APK present. APK signature was not checked.Code transparency signature is valid. SHA-256 fingerprint of the code transparency key certificate (must be compared with the developer's public key manually): 25 98 AA 59 62 BA 4C C0 7B 40 74 F4 19 09 02 A0 2A CD F1 1B 1F 42 84 92 93 23 8B 6F 87 E5 42 B4Code transparency verified: code related file contents match the code transparency file.

This should match the one you get from keytool:

keytool -list \ -alias WhateverAliasYouUsed \ -keystore /path/to/your/keystore.jks

Alternatively, you can have bundletool verify the code transparency for an installed app,via --mode=connected_device:

bundletool check-transparency \ --mode=connected_device \ --package-name=com.commonsware.scrap

As before, if you include --transparency-key-certificate, bundletool will checkagainst it; otherwise it will print the SHA-256 fingerprint.

bundletool Implementation

Much of the code for code transparency support in bundletool resides inthe com.android.tools.build.bundletool.transparency package.

The core ���driver��� of the verification resides in a set of static methodson ApkTransparencyCheckUtils. This code works off of a list of filesystem pathsto the APKs to check. Where those APKs come from depends on your --mode. Ofparticular note, for --mode=connected_device, bundletool uses adb shell commandsto copy the APKs to a temporary directory for analysis ��� the verification isnot performed in situ on the device.

The code uses this JSON Web Toolkit library,which seems to be actively maintained, which is nice.

Unfortunately, the code for bundletool seems to be fairly monolithic. It does not appear to be organizedas a library with a first-class API that also happens to have a CLI ��� it looks like it isjust a CLI. And, since bundletool historically has only been needed for developmentmachines and CI servers, in many places it seems to assume that environment. Getting verification logicthat can run on-device will require reverse-engineering a spec from the implementation and creating a separatelibrary, unless Google has interest in a significant reworking of bundletool.

 •  0 comments  •  flag
Share on Twitter
Published on July 18, 2021 12:54

July 15, 2021

Random Musings on the Android 12 Beta 3

Android 12 Beta 3 is out! And, as one would expect from a late beta, not much has changed.

The good news is that we can use 31 for compileSdkVersion and targetSdkVersion. That meansthat we should have reached API stability.

Of the stuff that was announced:

App Search: you saw it here first!

The permission group lookup APIsare nice, but I seem to recall Google getting rather testy about apps trying to determine the relationshipbetween permissions and groups. I wonder what changed��� ����

Beyond that:

We lost some things from previous editions of Android 12, such assetShowForegroundImmediately() on Notification.Builder.

getAllNetworks() on ConnectivityManager is deprecated.There is an alternative involving registerNetworkCallback() and the awkwardly-namedsetIncludeOtherUidNetworks().

REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUNDis why we need auto-complete.

Strangely, TranslationManager and the rest of android.view.translationremain unannounced. They showed up in Beta 1,and Google hasn���t said anything about them AFAICT. More stuff to ����

This should wrap up the 2021 edition of the ���Random Musings��� posts ��� if we havereached API stability, there should be nothing more for me to muse about.

 •  0 comments  •  flag
Share on Twitter
Published on July 15, 2021 15:49

July 12, 2021

���Elements of Android Jetpack��� Version 2.1 Released

Subscribers now haveaccess to an update to Elements of Android Jetpack,known as Version 2.1, in PDF, EPUB, and MOBI/Kindle formats, in addition to theonline reader. Just log intoyour Warescription page and downloadaway, or set up an account and subscribe!

OK, this took a lot longer to be released than I had expected, in part because Android Studio 4.2took a lot longer to be released than I had expected.

There are a lot of changes in this update:

There is a new chapter, focusing on app widgets, those interactivehome screen elements that apps can contribute

There is also a new chapter onusing library modules,plus a new section on creating library modules

The chapter on dependency inversion was moved up one in the chapter sequence,and the chapter on Room was updated to use Koin���s DI implementationfor the Kotlin sample

The chapter on Jetpack Navigation now also covers the Kotlin DSL

The various uses of startActivityForResult() were replaced by registerForActivityResult()and ActivityResultContracts

Everything was updated for Android Studio 4.2.2, the current shipping version

And, in addition to all of that, there are the usual suite of bug fixes, to the prose andto the sample code.

There should be one more update in 2021, after Android Studio 2020.3.1 Arctic Foxships in stable form. That is in a beta right now, so it is likely to be at leasta month or two before the stable release.

 •  0 comments  •  flag
Share on Twitter
Published on July 12, 2021 04:35