Recently, I've been exploring the deployment part of our build process. I started with automating our deployment to the PlayStore. Then I updated that process to use AABs. Now I am exploring how to deploy to internal app sharing.
Internal app sharing is the latest progression in the PlayStore's developer tools. It allows you to upload an app and in return receive a URL. This URL is sharable and allows you to install the app on your device.
There are a few security measures in place. You can restrict who can upload apps to internal app sharing. You can also limit who can download them.
This system can make sharing apps with your test/QA teams easy. It also stops that app being deployable to production. This can be useful when sharing apps which use a staging server or similar.
As with deployment to the normal PlayStore tracks, Google provides an API for internal app sharing. They offer Java or Python client libraries or you can go through HTTP. The way we wanted to combine deployment with CircleCI meant we chose the HTTP option.
First, you need to get a service account setup which has the permissions to deploy to the PlayStore. Click here, then follow the steps under ‘Using a service account’ to get that setup.
You will need to keep the JSON key you created during this process.
To create an access token you call a separate Google API passing it a JWT token.
To create the JWT:
You will need the following variables from your JSON key:
AUTH_ISS — Field ‘client_email’
AUTH_AUD — Field ‘token_uri’
AUTH_TOKEN — Field ‘private_key’
You can extract these from your JSON with:
Extracting them enables you to set your JSON key as an environment variable. Making your script more reusable across different projects.
Next, we use the JWT to request an access token from Google:
Using the access token you can now upload your app. I will be using the AAB format for my app. APKs are also supported, see the documentation for more details on this.
The LINK variable you result in is the link to your uploaded app.
Since these apps aren't uploaded to the normal PlayStore tracks, testers won't get prompted with an update. Therefore, I decided to use Slack to notify our QA team.
You can configure Slack integration within CircleCi here:
circleci.com/gh/{ORGANISATION}/{PROJECT_NAME}/edit#hooks
This results in a Slack webhook URL which you can use to trigger a message.
This is my finished script. I expect a few variables to be passed in. This is to make the script easier to reuse on different projects.
To call this script from CircleCi:
There are a couple of environment variables to take note of:
COMMAND_CREATE_AABS_DIST_QA - This is the command used to create our AAB. We use an environment variable so that we don’t have to customise our config for different projects (with different flavour configurations). An example might be: ./gradlew bundleLiveApi ; AAB_PATH=$(find . -path “*/outputs/*Release*/*.aab” -print -quit) ;
PLAYSTORE_SERVICE_KEY - This is the service account key used to access the PlayStore.
You will also notice that we extract some information from our AAB, for example the package name. Again this is to enable our script to be more easily reused across different projects. It’s worth noting the impact to build times this has in comparison to using environment variables though.
Hopefully, this helps you to deploy your apps using internal app sharing. Internal app sharing can be a useful tool in your deployment pipeline. Used well, it enables easy and fast deployment to your test/QA teams.
https://android.jlelse.eu/google-playstore-and-automated-deployment-beeef278d345
https://medium.com/@alistairsykes/google-playstore-and-automated-deployment-with-aab-a35eddabf128
https://developers.google.com/identity/protocols/OAuth2ServiceAccount#authorizingrequests
https://developers.google.com/android-publisher/api-ref/internalappsharingartifacts
https://support.google.com/googleplay/android-developer/answer/9303479?hl=en-GB
Search over 400 blog posts from our team
Subscribe to our monthly digest of blogs to stay in the loop and come with us on our journey to make things better!