diff --git a/.ci/android/build.sh b/.ci/android/build.sh
index 3c1e2f240..727f855d3 100755
--- a/.ci/android/build.sh
+++ b/.ci/android/build.sh
@@ -1,12 +1,15 @@
 #!/bin/bash -ex
 
 export NDK_CCACHE=$(which ccache)
+[ "$GITHUB_REPOSITORY" = "citra-emu/citra-canary" ] &&
+   BUILD_FLAVOR=canary ||
+   BUILD_FLAVOR=nightly
 
 ccache -s
 
 cd src/android
 chmod +x ./gradlew
-./gradlew bundleRelease
-./gradlew assembleRelease
+./gradlew assemble${BUILD_FLAVOR}Release
+./gradlew bundle${BUILD_FLAVOR}Release
 
 ccache -s
diff --git a/.ci/android/upload.sh b/.ci/android/upload.sh
index 64258dfd5..1b777d069 100755
--- a/.ci/android/upload.sh
+++ b/.ci/android/upload.sh
@@ -3,8 +3,21 @@
 . ./.ci/common/pre-upload.sh
 
 REV_NAME="citra-${GITDATE}-${GITREV}"
+[ "${GITHUB_REPOSITORY}" = "citra-emu/citra-canary" ] &&
+   BUILD_FLAVOR=canary ||
+   BUILD_FLAVOR=nightly
 
-cp src/android/app/build/outputs/apk/release/app-release.apk \
+cp src/android/app/build/outputs/apk/${BUILD_FLAVOR}/release/app-${BUILD_FLAVOR}-release.apk \
   "artifacts/${REV_NAME}.apk"
-cp src/android/app/build/outputs/bundle/release/app-release.aab \
+cp src/android/app/build/outputs/bundle/${BUILD_FLAVOR}Release/app-${BUILD_FLAVOR}-release.aab \
   "artifacts/${REV_NAME}.aab"
+
+if [ ! -z "${ANDROID_KEYSTORE_B64}" ]
+then
+  echo "Signing apk..."
+  base64 --decode <<< "${ANDROID_KEYSTORE_B64}" > ks.jks
+
+  java -jar $(which apksigner) sign --ks ks.jks \
+    --ks-key-alias "${ANDROID_KEY_ALIAS}" \
+    --ks-pass env:ANDROID_KEYSTORE_PASS "artifacts/${REV_NAME}.apk"
+fi
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3203e62bf..c08acff38 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -129,10 +129,14 @@ jobs:
       - name: Deps
         run: |
           sudo apt-get update
-          sudo apt-get install ccache -y
+          sudo apt-get install ccache apksigner -y
       - name: Build
         run: ./.ci/android/build.sh
-      - name: Copy artifacts
+      - name: Copy and sign artifacts
+        env:
+          ANDROID_KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
+          ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
+          ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
         run: ./.ci/android/upload.sh
       - name: Upload
         uses: actions/upload-artifact@v3
@@ -153,7 +157,7 @@ jobs:
           TRANSIFEX_API_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }}
   release:
     runs-on: ubuntu-latest
-    needs: [build, macos]
+    needs: [build, macos, android]
     if: ${{ startsWith(github.ref, 'refs/tags/') }}
     steps:
       - uses: actions/download-artifact@v3
@@ -174,4 +178,4 @@ jobs:
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         with:
-          asset_paths: '["./**/*.tar.*","./**/*.7z","./**/*.zip"]'
+          asset_paths: '["./**/*.tar.*","./**/*.7z","./**/*.zip","./**/*.apk","./**/*.aab"]'
diff --git a/src/android/app/build.gradle b/src/android/app/build.gradle
index 1e70d8d99..a3ea30ffb 100644
--- a/src/android/app/build.gradle
+++ b/src/android/app/build.gradle
@@ -83,6 +83,17 @@ android {
         }
     }
 
+    flavorDimensions "version"
+    productFlavors {
+        canary {
+            dimension "version"
+            applicationIdSuffix ".canary"
+        }
+        nightly {
+            dimension "version"
+        }
+    }
+
     externalNativeBuild {
         cmake {
             version "3.18.1"
@@ -140,5 +151,10 @@ def getVersion() {
         logger.error('Cannot find git, defaulting to dummy version number')
     }
 
+    if (System.getenv("GITHUB_ACTIONS") != null) {
+        def gitTag = System.getenv("GIT_TAG_NAME")
+        versionName = gitTag ?: versionName
+    }
+
     return versionName
 }