Prerequisites
Before you begin, make sure you have the following:
- macOS or Linux — this guide covers Linux-specific commands where needed
- Node.js installed — verify with
node -v - EAS CLI installed —
npm install -g eas-cli - IDE installed - this guide covers uses VS Code
- An existing Expo project already set up with EAS credentials
- Access to your company's Google Play Console
Step 1 — Download Your EAS Credentials
Open your main Expo project in VS Code. In the terminal, run:
eas credentials
Navigate through the prompts:
- Select Android
- Select production
- Select credentials.json
- Choose Download credentials from EAS to credentials.json
Once done, two things will appear at the root of your main Expo project:
YourMainExpoApp/
├── credentials.json
└── credentials/
└── android/
└── keystore.jks
Step 2 — Create ProofApp and Copy the Credentials
Open a terminal and navigate to the parent folder that contains your main Expo project, then run:
npx create-expo-app@latest ProofApp
This creates ProofApp as a sibling to your main project:
parent-folder/
├── YourMainExpoApp/
│ ├── credentials.json
│ └── credentials/
│ └── android/
│ └── keystore.jks
└── ProofApp/ ← created here, sibling to main app
Now copy the credentials.json file and the entire credentials/ folder from YourMainExpoApp into the root of ProofApp:
parent-folder/
├── YourMainExpoApp/
│ ├── credentials.json
│ └── credentials/
│ └── android/
│ └── keystore.jks
├── ProofApp/
│ ├── credentials.json
│ └── credentials/
│ └── android/
│ └── keystore.jks
Open ProofApp in VS Code and keep credentials.json open — you will be referencing it in the next step.
Step 3 — Register the Existing Keystore in ProofApp
Open the VS Code terminal inside ProofApp and run:
eas credentials
Navigate through the prompts exactly as follows:
- Select Android
- Select production
- Select Keystore: Manage everything needed
- Select Set up a new keystore
- Press Tab to confirm the name for the new build credentials
- When asked to set as default credentials, select Yes
- When asked to generate a new keystore, press N — you are using your existing one
For all remaining questions, use the values from the credentials.json file you have open:
| Prompt | Value from credentials.json |
|---|---|
| Keystore path | credentials/android/keystore.jks |
| Keystore password | your-keystore-password |
| Key alias | your-keystore-alias |
| Key password | your-key-password |
Your
credentials.jsonfile structure will look something like this — use the values underandroid.keystore:
{
"android": {
"keystore": {
"keystorePath": "credentials/android/keystore.jks",
"keystorePassword": "your-keystore-password",
"keyAlias": "your-key-alias",
"keyPassword": "your-key-password"
}
}
}
Step 4 — Generate the Native Android Folder
In the VS Code terminal inside ProofApp, run:
npx expo prebuild
This generates the native android/ and ios/ folders at the root of ProofApp(we're interested in the android folder):
ProofApp/
├── android/
│ └── app/
│ └── ...
├── ios/
├── credentials.json
└── credentials/
└── android/
└── keystore.jks
Note: If you ever run
npx expo prebuild --cleanin the future, it will wipe theandroid/folder. Keep a backup of any files you add to it.
Step 5 — Add the ADI Registration File
Google requires an adi-registration.properties file to be present in two locations of the android/ folder.
Navigate to android/app/ and create the file there. Then navigate to android/app/src/main/assets/ —
if there is no assets/ folder, create it. Then create the same file inside it:
android/app/adi-registration.propertiesandroid/app/src/main/assets/adi-registration.properties
Your structure should now look like this:
ProofApp/
└── android/
└── app/
├── adi-registration.properties
└── src/
└── main/
└── assets/
└── adi-registration.properties
Paste the snippet provided by Google into both files.
Step 6 — Configure the Signing Config in build.gradle
Open android/app/build.gradle and locate the android { } block. Paste the following inside it, replacing the placeholder values with the ones from your credentials.json:
android {
...
signingConfigs {
release {
storeFile file('../../credentials/android/keystore.jks')
storePassword 'your-keystore-password'
keyAlias 'your-key-alias'
keyPassword 'your-key-password'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
The keystore path uses
../../to go up two levels fromandroid/app/to the root of ProofApp where yourcredentials/folder lives. All password values are available in your opencredentials.jsonfile.
Step 7 — Build the Release APK
In the VS Code terminal inside ProofApp, navigate to the android folder and run the build command:
cd android && ./gradlew assembleRelease
If the ./gradlew command fails with a permission denied error, run this first then retry the build:
chmod +x android/gradlew
Once the build completes successfully, your release APK will be generated at:
ProofApp/
└── android/
└── app/
└── build/
└── outputs/
└── apk/
└── release/
└── app-release.apk ← your release APK
Copy the app-release.apk file and head over to Google Play Console to upload it:
- Go to your app on Google Play Console
- Navigate to Internal Testing → Create new release
- Upload the
app-release.apkfile - Complete the release and roll it out
That's it — your APK is now signed with the correct keystore and should upload to Play Console without any signature mismatch errors! 🎉
Conclusion
The signature mismatch error comes down to one thing — Play Console locks your app to the first keystore signature it sees. By downloading your existing EAS credentials and configuring the local Gradle build to use that same keystore, you ensure every APK you build locally matches what Play Console expects. EAS securely manages your keystore for you — however, if you ever need to build locally again,
make sure to re-download your credentials via eas credentials as covered in Step 1.