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 Changecketti 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 EffectYou 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 ApproachesYou 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.
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!.
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 DevelopersgetExternalStorageDirectory() 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 APIFrankly, 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 SomedayGoogle 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 OnThere 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.
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.
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.
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.
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:
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
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 CommandsLast 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.certYou 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.certIf 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.jksAlternatively, 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.scrapAs before, if you include --transparency-key-certificate, bundletool will checkagainst it; otherwise it will print the SHA-256 fingerprint.
bundletool ImplementationMuch 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.
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.
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.


