From 91551bf4e8de3d359caa60ef44045f8b2eb6b26f Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Wed, 18 Dec 2024 22:23:27 +0100 Subject: [PATCH] Start using flavours Currently, this just allows us to remove the donation button on Google Play without using the deprecated installer APIs. In the future, this should allow us to also release multiple versions of Catima (for example: WearOS is a commonly requested feature, but this needs non-free dependencies, which may not be okay to all users). --- .github/workflows/android.yml | 76 ++++++++++--------- .gitignore | 3 + app/build.gradle.kts | 18 +++++ .../protect/card_locker/AboutActivity.java | 5 +- .../main/java/protect/card_locker/Utils.java | 15 ---- build.sh | 38 +++++++--- docs/RELEASE_STEPS.md | 6 +- 7 files changed, 93 insertions(+), 68 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index f40eb5e0a0..45bbdd79b2 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -30,39 +30,45 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - api-level: [ 21, 34 ] + flavor: [Foss, Gplay] steps: - - uses: actions/checkout@v4.2.2 - - name: Fail on bad translations - run: if grep -ri "<xliff" app/src/main/res/values*/strings.xml; then echo "Invalidly escaped translations found"; exit 1; fi - - uses: gradle/actions/wrapper-validation@v4 - - name: set up OpenJDK 17 - run: | - sudo apt-get update - sudo apt-get install -y openjdk-17-jdk-headless - sudo update-alternatives --auto java - - name: Build - run: ./gradlew assembleRelease - - name: Check lint - run: ./gradlew lintRelease - - name: Run unit tests - run: timeout 5m ./gradlew testReleaseUnitTest || { ./gradlew --stop && timeout 5m ./gradlew testReleaseUnitTest; } - - name: Enable KVM - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - - name: Run instrumented tests - uses: ReactiveCircus/android-emulator-runner@v2 - with: - api-level: ${{ matrix.api-level }} - arch: x86_64 - script: ./gradlew connectedCheck - - name: SpotBugs - run: ./gradlew spotbugsRelease - - name: Archive test results - if: always() - uses: actions/upload-artifact@v4.5.0 - with: - name: test-results-api${{ matrix.api-level }} - path: app/build/reports + - uses: actions/checkout@v4.2.2 + - name: Fail on bad translations + run: if grep -ri "<xliff" app/src/main/res/values*/strings.xml; then echo "Invalidly escaped translations found"; exit 1; fi + - uses: gradle/actions/wrapper-validation@v4 + - name: set up OpenJDK 17 + run: | + sudo apt-get update + sudo apt-get install -y openjdk-17-jdk-headless + sudo update-alternatives --auto java + - name: Build + run: ./gradlew assemble${{ matrix.flavor }}Release + - name: Check lint + run: ./gradlew lint${{ matrix.flavor }}Release + - name: Run unit tests + run: timeout 5m ./gradlew test${{ matrix.flavor }}ReleaseUnitTest || { ./gradlew --stop && timeout 5m ./gradlew test${{ matrix.flavor }}ReleaseUnitTest; } + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - name: Run instrumented tests (API 21) + uses: ReactiveCircus/android-emulator-runner@v2 + with: + api-level: 21 + arch: x86_64 + script: ./gradlew connected${{ matrix.flavor }}DebugAndroidTest + - name: Run instrumented tests (API 34) + uses: ReactiveCircus/android-emulator-runner@v2 + with: + api-level: 34 + arch: x86_64 + script: ./gradlew connected${{ matrix.flavor }}DebugAndroidTest + - name: SpotBugs + run: ./gradlew spotbugs${{ matrix.flavor }}Release + - name: Archive test results + if: always() + uses: actions/upload-artifact@v4.5.0 + with: + name: test-results-flavor${{ matrix.flavor }} + path: app/build/reports diff --git a/.gitignore b/.gitignore index 78b6b76bf3..8250a35279 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ /.bundle/ /vendor/bundle /lib/bundler/man/ + +# Catima-specific +SHA256SUMS diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e20a79a163..515be00c71 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -31,6 +31,9 @@ android { resourceConfigurations += listOf("ar", "bg", "bn", "bn-rIN", "bs", "cs", "da", "de", "el-rGR", "en", "eo", "es", "es-rAR", "et", "fi", "fr", "gl", "he-rIL", "hi", "hr", "hu", "in-rID", "is", "it", "ja", "ko", "lt", "lv", "nb-rNO", "nl", "oc", "pl", "pt-rBR", "pt-rPT", "ro-rRO", "ru", "sk", "sl", "sr", "sv", "ta", "tr", "uk", "vi", "zh-rCN", "zh-rTW") testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + buildConfigField("boolean", "showDonate", "true") + buildConfigField("boolean", "showRateOnGooglePlay", "false") } buildTypes { @@ -51,6 +54,21 @@ android { viewBinding = true } + flavorDimensions.add("type") + productFlavors { + create("foss") { + dimension = "type" + isDefault = true + } + create("gplay") { + dimension = "type" + + // Google doesn't allow donation links + buildConfigField("boolean", "showDonate", "false") + buildConfigField("boolean", "showRateOnGooglePlay", "true") + } + } + bundle { language { enableSplit = false diff --git a/app/src/main/java/protect/card_locker/AboutActivity.java b/app/src/main/java/protect/card_locker/AboutActivity.java index 33929bb58a..01bceab570 100644 --- a/app/src/main/java/protect/card_locker/AboutActivity.java +++ b/app/src/main/java/protect/card_locker/AboutActivity.java @@ -45,11 +45,10 @@ protected void onCreate(Bundle savedInstanceState) { binding.rate.setTag("https://play.google.com/store/apps/details?id=me.hackerchick.catima"); binding.donate.setTag("https://catima.app/donate"); - boolean installedFromGooglePlay = Utils.installedFromGooglePlay(this); // Hide Google Play rate button if not on Google Play - binding.rate.setVisibility(installedFromGooglePlay ? View.VISIBLE : View.GONE); + binding.rate.setVisibility(BuildConfig.showRateOnGooglePlay ? View.VISIBLE : View.GONE); // Hide donate button on Google Play (Google Play doesn't allow donation links) - binding.donate.setVisibility(installedFromGooglePlay ? View.GONE : View.VISIBLE); + binding.donate.setVisibility(BuildConfig.showDonate ? View.VISIBLE : View.GONE); bindClickListeners(); } diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index 473a9da402..280ce209dd 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -1032,21 +1032,6 @@ public static int setIconOrTextWithBackground(Context context, LoyaltyCard loyal return headerColor; } - public static boolean installedFromGooglePlay(Context context) { - try { - String packageName = context.getPackageName(); - String installer; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - installer = context.getPackageManager().getInstallSourceInfo(packageName).getInstallingPackageName(); - } else { - installer = context.getPackageManager().getInstallerPackageName(packageName); - } - return installer.equals("com.android.vending"); - } catch (Throwable ignored) { - return false; - } - } - public static int getHeaderColor(Context context, LoyaltyCard loyaltyCard) { return loyaltyCard.headerColor != null ? loyaltyCard.headerColor : LetterBitmap.getDefaultColor(context, loyaltyCard.store); } diff --git a/build.sh b/build.sh index e6401352e3..8cd9e6b99f 100755 --- a/build.sh +++ b/build.sh @@ -3,7 +3,7 @@ set -euo pipefail IFS=$'\n\t' ### build.sh -### Builds Catima the same way F-Droid does for reproducible builds +### Builds Catima the same way rbtlog/IzzyOnDroid does for reproducible builds if [ -z "${ANDROID_SDK_ROOT:-}" ]; then echo "ANDROID_SDK_ROOT is not set, setting to $HOME/Android/Sdk"; @@ -25,7 +25,11 @@ echo "Starting build" ./gradlew clean assembleRelease echo "Build finished (unsigned)" -echo "Your build is at app/build/outputs/apk/release/app-release-unsigned.apk" +flavourDirs=$(find app/build/outputs/apk/ -mindepth 1 -maxdepth 1 -type d) +for flavourDir in $flavourDirs; do + flavourName="$(basename "$flavourDir")" + echo "Your $flavourName flavour is at $flavourDir/release/app-$flavourName-release-unsigned.apk" +done if [ -z "${KEYSTORE:-}" ]; then echo "KEYSTORE not set, skipping signing..." @@ -36,16 +40,26 @@ else fi apksigner_version="$(ls -1 "$HOME/Android/Sdk/build-tools/" | tail -n 1)" - cp app/build/outputs/apk/release/app-release-unsigned.apk app/build/outputs/apk/release/app-release.apk - "$HOME/Android/Sdk/build-tools/$apksigner_version/apksigner" sign -v --ks "$KEYSTORE" --ks-key-alias "$KEYSTORE_ALIAS" app/build/outputs/apk/release/app-release.apk - echo "Build finished (signed)" - echo "Your build is at app/build/outputs/apk/release/app-release.apk" -fi + for flavourDir in $flavourDirs; do + flavourName="$(basename "$flavourDir")" + echo "Signing $flavourName flavour..." + cp "$flavourDir/release/app-$flavourName-release-unsigned.apk" "$flavourDir/release/app-$flavourName-release.apk" + "$HOME/Android/Sdk/build-tools/$apksigner_version/apksigner" sign -v --ks "$KEYSTORE" --ks-key-alias "$KEYSTORE_ALIAS" "$flavourDir/release/app-$flavourName-release.apk" + + echo "Build finished (signed)" + echo "Your $flavourName flavour is at $flavourDir/release/app-$flavourName-release.apk" + done -pushd app/build/outputs/apk/release/ -sha256sum -- *.apk > SHA256SUMS -popd + shasumPath="$(pwd)/SHA256SUMS" + echo "" > "$shasumPath" -echo "SHA256SUMS generated" -echo "Your SHA256SUMS is at app/build/outputs/apk/release/SHA256SUMS" + for flavourDir in $flavourDirs; do + pushd "$flavourDir/release/" + sha256sum -- *.apk >> "$shasumPath" + popd + done + + echo "SHA256SUMS generated" + echo "Your SHA256SUMS are at SHA256SUMS" +fi diff --git a/docs/RELEASE_STEPS.md b/docs/RELEASE_STEPS.md index 84d4185e23..f8dafccfc2 100644 --- a/docs/RELEASE_STEPS.md +++ b/docs/RELEASE_STEPS.md @@ -6,8 +6,8 @@ 3. Update `CHANGELOG.md` with the new version name and the release date 4. Update `app/build.gradle.kts` with the new `versionCode` and `versionName` 5. Create a commit for the new release: `git add CHANGELOG.md app/build.gradle.kts && git commit -m "Release Catima "` -6. Build a new .apk: `KEYSTORE=/path/to/keystore KEYSTORE_ALIAS=catima ./build.sh` -7. Upload the APK to Google Play Open Testing +6. Build the new .apks: `KEYSTORE=/path/to/keystore KEYSTORE_ALIAS=catima ./build.sh` +7. Upload `app/build/outputs/apk/gplay/release/app-gplay-release.apk` to Google Play Open Testing 8. Push the version update commit: `git push` -9. Create a new release on GitHub and attach the `app-release.apk` and `SHA256SUMS` files +9. Create a new release on GitHub and attach the `app/build/outputs/apk/foss/release/app-foss-release.apk` and `SHA256SUMS` files 10. After the release has been approved on Google Play Production, update the metadata there: `bundle exec fastlane supply --version_code `