When Google announced that Play Store apps must target SDK 30 by August, our team started investigating what it would take to meet this requirement. Now, with our migration to SDK 30 complete, we’d like to detail the changes our team made. This is not meant to be an exhaustive migration guide – but hopefully you will find parts of it useful!
Limiting usage of Intent#ResolveActivity
Android 30 introduces security restrictions around Package Visibility. You have a couple of options for migrating existing
resolveActivity calls: 1.) using a
try-catch block around
startActivity calls or 2.) keeping your
startActivity code as-is, while declaring whatever queries you intend to run in your application manifest.
Mostly, we migrated to try-catch blocks. The process was simple – just move the handling code previously run when
myIntent.resolveActivity(context.getPackageManager()) == null into a
catch block. Here’s an example of how to launch the Play Store app, with a fallback of opening a web browser:
However, we still had to declare Intent queries in our manifest, due to one use-case requiring a
resolveActivity call. In certain document-gathering flows, we launch a “Chooser” Intent with various options for gathering content. Users can choose to provide the document from an existing local file (e.g. a JPEG or PDF), or from a freshly taken camera photo.
To support the case where users don’t have a valid camera application installed, and prevent that option from appearing in the Chooser, we need to check whether
ACTION_IMAGE_CAPTURE intents can be resolved by the system. Therefore we added the following to our manifest:
Camera2 deprecations – less is more
Wealthfront’s app uses the device camera for capturing documents in certain flows – for example, users can photograph a driver’s license to verify their identity before opening an account.
In developing these flows we first attempted writing our own camera interface, resulting in a library of Camera2 code for previewing and capturing from the device camera feed. While we ultimately decided to integrate with a third-party camera library instead of building our own, the remains of our Camera2 project became riddled with deprecations after targeting SDK 30. As the CameraView library was performing very satisfactorily, our solution to these deprecations was straightforward: delete our Camera2 code.
Compliance with the scoped-storage framework is enforced starting with Android 30. For us, this meant verifying that
ACTION_GET_CONTENT works as intended. Interestingly we found that, because these intents are satisfied by the system’s Storage Access Framework, and not our application, our manifest should no longer require the
As part of this exploration we also re-evaluated whether we should change
ACTION_GET_CONTENT intents to
ACTION_OPEN_DOCUMENT ones. We learned that there are significant use-case differences between the two, and that the relatively restricted (i.e. limited-term content access)
ACTION_GET_CONTENT worked just fine for our purposes.
Specifying root View in Espresso tests
With the code changes in place, it was time to verify them by running our integration tests on Android 10 devices. Tests largely executed as before, with one exception: we noticed occasional timeouts in our tests, coupled with failures of Espresso’s matchers being unable to locate the correct root View.
When Espresso runs a View matcher, it does so against a particular root View. Practical examples of differing root Views on Android include the main Activity window, or an AlertDialog window layered on top. Espresso’s root-matching process is typically transparent to developers, as it does some guessing about which root View to target by default.
While Espresso’s guessing works most of the time, we found that by explicitly specifying a root View, we could get affected matchers working 100% of the time. Below is code from our approach that specifies custom Espresso entry points, as replacements for
In addition to adding the above, we added a custom Lint rule to prevent the use of the default View-matching entry point,
If you are an app developer in the process of targeting Android 10, I hope you found this post helpful. And more importantly, if you are someone who would like to help Wealthfront build amazing financial products, take a look at our careers page!
The information contained in this communication is provided for general informational purposes only, and should not be construed as investment or tax advice. Nothing in this communication should be construed as a solicitation or offer, or recommendation, to buy or sell any security. Any links provided to other server sites are offered as a matter of convenience and are not intended to imply that Wealthfront Advisers or its affiliates endorses, sponsors, promotes and/or is affiliated with the owners of or participants in those sites, or endorses any information contained on those sites, unless expressly stated otherwise.
All investing involves risk, including the possible loss of money you invest, and past performance does not guarantee future performance. Please see our Full Disclosure for important details.
Wealthfront offers a free software-based financial advice engine that delivers automated financial planning tools to help users achieve better outcomes. Investment management and advisory services are provided by Wealthfront Advisers LLC, an SEC registered investment adviser, and brokerage related products are provided by Wealthfront Brokerage LLC, a member of FINRA/SIPC.
Wealthfront, Wealthfront Advisers and Wealthfront Brokerage are wholly owned subsidiaries of Wealthfront Corporation.
© 2021 Wealthfront Corporation. All rights reserved.