Two weeks ago I needed to deploy updates to the Zooniverse mobile app on the Apple app and Google play stores. Based on the response to my supplications on Twitter about the situation, it seems that even full time mobile devs aren’t confident they know how to do this.
So I figured it out myself, and I thought I’d make a step-by-step guide for the next hapless soul who finds themselves in this situation:
SCENE: You have to deploy an update to an existing mobile app, but every single provisioning profile, keystore, everything you ever generated to upload it the first time is somehow missing or expired.
Your mobile app is the jeep scene from Jurassic World. Congrats.
Devs who’ve worked in mobile know why this is more annoying than deploying a brand new app. It’s because, for very good security reasons, Apple and Google want to make sure it’s you pushing updates to your app, and not some poser trying to hijack your loyal constituents. So you can’t just start fresh with all new profiles and keys exactly the way you see in tutorials, because most tutorials assume you’re deploying for the first time.
This is a general problem with tutorials. They tend to assume the simplest scenario, which is rarely realistic.
They also tend to explain the whys and wherefores, which is lovely, but nobody in this situation cares to know what particular species of tree inhabits the thick, haunted woods they find themselves in until they are out of it. So, lemme get you out of the woods. We can learn more about the underlying construction of Android and iOS deployment security another time.
Let’s assume your app is building for both iOS and Android, and we’re at the deployment step.

We begin by deploying it for iOS.
You’re gonna need two things: a Distribution Provisioning Profile and a Distribution Certificate.
First, the Provisioning Profile: it authorizes specific devices to run your app. For development, XCode takes care of this for your simulators, etc. For distribution, XCode uses this to authorize devices that get your app from the app store.
STEPS:
1. If you’re lucky, you can have XCode take care of your profiles and certificates for you by checking this box.
The app I maintain is written with a dual platform framework, kinda old, with a few kludges in it, so we can’t do this. I’ll now explain the somewhat more manual way.
1. Sign into http://developer.apple.com.
2. Click “Certificates, IDs & Profiles.”
You’ll see a list.
3. Hit the ‘+’ to make a new one. If the app is for iPhone & iPad you want ‘App Store’ distribution. NOT ‘iOS’ or ‘Ad Hoc’ (the ’net has a lot of conflicting outdated advice here).
So now You also need a distribution certificate. This is how Apple verifies that you, the developer, are the one uploading a new build of your app for distribution. 85% of web instructions on this are outdated or incorrect. This one is correct:
First of all Create a Certificate Signing Request (CSR)
- Launch Keychain Access located in /Applications/Utilities.
- Go to Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority.
- Fill the form as below:
- User email address: youremail@example.com
- Common name: your name cert
- CA email address: {leave blank}
- Request is: Saved to disk
- Note: If you are using VPN, then turn it off. Otherwise, in some case, the cert will not be generated and saved on disk.
Generate New Certificate
- Login to the apple developer account (developer.apple.com)
- Go to Certificates, Identifiers & Profiles page
- Click the + icon to create a new certificate
- Choose the software type. If you are using Xcode 11 or later, then it’s good to choose “Apple Development” to sign development version. For signing distribution of apps, you can choose “Apple Distribution”. They support all iOS, macOS, tvOS, and watchOS apps.
- Click on “Continue” button
- Choose the cert file you created above (Certificate Signing Request (CSR))
- Click on “Continue” button
- Now the certificate is created
- Download the certificate
Save the certificate to keychain
- Double click on the downloaded certificate
- It will open a window, and when you click the button present there, then the certificate is saved in your keychain.
Check the certificate on keychain
- Open keychain
- On the left hand site, under “Keychains”, click on “login”. And, under “Category”, click on “My Certificates”. This will show you the recently added certificates. You can also sort the certificates by “Expires” date column.
Add the certificates in Xcode
- Go to Xcode > Preferences
- Go to Accounts tab
- Click on your apple id
- Click on the Team name
- Click on the “Manage Certificates” button
- Click on the + icon
- Select “Apple Development” and the apple development certificate will be auto imported.
- Select “Apple Distribution” and the apple distribution certificate will be auto imported.
OK so now in XCode you can select your shiny new Provisioning Profile and Distribution Certificate. See below how that will look. From there, select Product > Archive from the top bar menus. XCode will build and sign your app, and you get a button for ‘Upload to the App Store.’
Archival/upload takes a while, but once it’s done you can hop over to http://appstoreconnect.apple.com, click on your app, go to the ‘TestFlight’ tab, and see your build. Tab back to ‘App Store’ to edit your release page & switch out your old app version for your new one via a dropdown.
That’s iOS. OK. Time for Android.
The #1 thing that online resources seem to get very confused about is the difference between an Android app signing key and an upload key. The app signing key does not change. Google uses it to sign your app for the Play store. It stays the same.
The upload key is, for our purposes, analogous in use case to the iOS Distribution certificate. Android uses java keystore for this instead of (obviously) the Mac-specific keychain process that iOS uses. So, we have to do a new thing here.
Once upon a time, you had to do this manually. As of Android studio 2020.3.1, it sort of tries to help you. Also worth noting that Android’s distribution security dance changed in Aug 2021. I recommend moving to this new app signing key/upload key configuration. Here’s how:
1. Go in Android Studio to Build > Generate Signed Bundle/APK
2. Choose aab or apk. My rule here is ‘do aab unless for some reason you can’t.’
3. You’ll now see a form where you can enter a keystore and key. Choose the ‘Create New’ button there in the middle.
Now it gives you this thing.
1. Give your keystore a name ending in .keystore and a path for where to put it. I keep it in the app dir and .gitignore it. Remember, it’s for local upload authentication.
2. Make up a password.
3. For alias, choose a memorable name.
Ok, so here’s where things get gnarly. For the alias password, all of the internet and your grandma and G*d will tell you to make this password different from the keystore password and they’re right, in theory.
In practice, for some reason (I forget if it’s a Java or an Android Studio limitation), you can’t. So make ’em the same.
So, for the bottom part of this form, fill out name and Organization. You can fill out more. I found that to be the minimum I could fill out.
Click ‘OK.’
So now when you generate your signed APK, you’ll see Gradle hum away until the build succeeds. It should give you a link that says ‘locate my app bundle’ or ‘locate my apk’ and you can click that to see where it is. Example: mine is in android/app/release/.
Now to get your upload key registered with Google Play, you’ll send them a public key (.pem) for your private key. I’ll tell you how to generate that public key and then how to give it to Google.
Navigate to the directory you made the keystore and run this command*, replacing everything in [] with the string it describes (remove the []):
keytool -export -rfc -alias [alias] -file [name-you-want].pem -keystore [name-of-keystore-without-keystore-extension].jks
*In general, do not run CLI commands from strangers on the internet unless you can describe every single keyword and flag and what it does. In this case you can trust me, but I’d also say that even if you couldn’t, right? So I recommend double-checking my command, and any command you get from someone who has zero personal stake in whether you delete your OS or something.
Once you have that, fill out this form. Attach the .pem. You can find your developer account ID on the homepage when logged into the play console. They’ll email you when it’s registered. Turnaround is ~2 days. During holidays, possibly a bit longer.
Go to http://play.google.com/apps/publish and log in.
Click on your app in the list. Under “Releases Overview” on the left, click whichever release you want to do (we start with “Closed Testing”). You can create a new track or push an update to an existing one with “Manage Track” on the right.
Now you fill out the form and there’s essentially a box for uploading a file, and that’s where you put your apk/aab. So, locate the file in your file manager and drag it onto that box. The authentication check should match, and you should be able to create your release!
Congratulations, your Jurassic Park Jeep is cavorting over hill and dale on the internet.
Did you find this post helpful? Come contribute to this mobile app with me! It’s a React Native app for the largest people-powered scientific research platform in the world, The Zooniverse. I promise, you don’t have to do the stuff in this thread. I’ll handle deployment and we’ll find you a nice ticket :).
If you liked this post, you might also like:
My introduction to my Mobile Software Development course