From d8343d089be4b2b29aab679043068e0d77f4021f Mon Sep 17 00:00:00 2001 From: Max Litruv Boonzaayer Date: Sun, 19 Apr 2026 07:24:38 +1000 Subject: [PATCH] feat: implement Android app signing setup and update .gitignore for keystore files --- android/.gitignore | 8 ++-- android/SIGNING_SETUP.md | 61 +++++++++++++++++++++++++++++ android/app/build.gradle | 22 +++++++++++ android/keystore.properties.example | 14 +++++++ 4 files changed, 101 insertions(+), 4 deletions(-) create mode 100644 android/SIGNING_SETUP.md create mode 100644 android/keystore.properties.example diff --git a/android/.gitignore b/android/.gitignore index 48354a3..4deb69d 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -52,10 +52,10 @@ captures/ # Comment next line if keeping position of elements in Navigation Editor is relevant for you .idea/navEditor.xml -# Keystore files -# Uncomment the following lines if you do not want to check your keystore files in. -#*.jks -#*.keystore +# Keystore files - NEVER commit these! +*.jks +*.keystore +keystore.properties # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild diff --git a/android/SIGNING_SETUP.md b/android/SIGNING_SETUP.md new file mode 100644 index 0000000..bf6a2d0 --- /dev/null +++ b/android/SIGNING_SETUP.md @@ -0,0 +1,61 @@ +# Android App Signing Setup + +## Why This Matters +Android requires apps to be signed with the same key for updates to work. Without proper signing, users cannot update your app - they must uninstall and reinstall, losing all data. + +## Setup Instructions + +### 1. Create a Keystore (if you don't have one) + +Run this command in the `android/` directory: + +```bash +keytool -genkey -v -keystore paarrot-release.keystore -alias paarrot -keyalg RSA -keysize 2048 -validity 10000 +``` + +You'll be asked for: +- Keystore password (remember this!) +- Key password (remember this!) +- Your name, organization, etc. + +**IMPORTANT**: Back up this keystore file and remember the passwords! If you lose either, you cannot update your app. + +### 2. Create keystore.properties + +Copy the example file: + +```bash +cp keystore.properties.example keystore.properties +``` + +Then edit `keystore.properties` and fill in: +- `storeFile`: path to your keystore (e.g., `paarrot-release.keystore`) +- `storePassword`: the keystore password you set +- `keyAlias`: the alias (e.g., `paarrot`) +- `keyPassword`: the key password you set + +### 3. Verify + +The file `keystore.properties` should be gitignored (check `.gitignore`). + +### 4. Build + +Now your release builds will be properly signed: + +```bash +cd android +./gradlew assembleRelease +``` + +The signed APK will be in: `app/build/outputs/apk/release/` + +## Troubleshooting + +### "Updates not installing" +- You're using a different keystore than the original APK +- Solution: Use the same keystore that was used for the first release + +### "keystore.properties not found" +- Normal for debug builds +- Only needed for release builds +- Create the file following step 2 above diff --git a/android/app/build.gradle b/android/app/build.gradle index 466c8db..4e8e01f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,9 +1,28 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +// Load keystore properties +def keystorePropertiesFile = rootProject.file("keystore.properties") +def keystoreProperties = new Properties() +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + android { namespace = "com.paarrot.app" compileSdk = rootProject.ext.compileSdkVersion + + signingConfigs { + release { + if (keystorePropertiesFile.exists()) { + storeFile file(keystoreProperties['storeFile']) + storePassword keystoreProperties['storePassword'] + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + } + } + } + defaultConfig { applicationId "com.paarrot.app" minSdkVersion rootProject.ext.minSdkVersion @@ -21,6 +40,9 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + if (keystorePropertiesFile.exists()) { + signingConfig signingConfigs.release + } } } applicationVariants.all { variant -> diff --git a/android/keystore.properties.example b/android/keystore.properties.example new file mode 100644 index 0000000..33690d3 --- /dev/null +++ b/android/keystore.properties.example @@ -0,0 +1,14 @@ +# Copy this file to keystore.properties and fill in your actual values +# NEVER commit keystore.properties to git! + +# Path to your keystore file (relative to android/ directory) +storeFile=paarrot-release.keystore + +# Keystore password +storePassword=your_keystore_password_here + +# Key alias +keyAlias=paarrot + +# Key password +keyPassword=your_key_password_here