diff --git a/.github/workflows/build-phone-app.yml b/.github/workflows/build-phone-app.yml index b920b31..04c4d39 100644 --- a/.github/workflows/build-phone-app.yml +++ b/.github/workflows/build-phone-app.yml @@ -248,6 +248,8 @@ jobs: - name: Upload to Google Play if: env.AAB_NAME != '' && env.TRACK != 'none' run: | + # The script's exit code, not tee's: a rejected upload must fail the run. + set -o pipefail tools=$(ls -d "$ANDROID_HOME"/build-tools/* | sort -V | tail -1) package=$("$tools/aapt2" dump badging "$RUNNER_TEMP/$APK_NAME" | sed -n "s/^package: name='\([^']*\)'.*/\1/p") node scripts/play-upload.mjs --bundle "$RUNNER_TEMP/$AAB_NAME" --package "$package" --track "$TRACK" \ diff --git a/apps/mobile/app.config.ts b/apps/mobile/app.config.ts index 416ccf8..9b255b9 100644 --- a/apps/mobile/app.config.ts +++ b/apps/mobile/app.config.ts @@ -1,5 +1,5 @@ import type { ConfigContext, ExpoConfig } from "expo/config"; -import { withAppBuildGradle } from "expo/config-plugins"; +import { withAndroidManifest, withAppBuildGradle } from "expo/config-plugins"; import { version } from "../../package.json"; /** @@ -59,6 +59,25 @@ const withReleaseSigning = (config: ExpoConfig): ExpoConfig => return c; }) as ExpoConfig; +/** + * The Bluetooth plugin (react-native-ble-plx, lights #208) with `neverForLocation` declares the location + * permissions again as `uses-permission-sdk-23` capped at Android 11 (maxSdkVersion 30). The app needs + * them on every version for GPS (app.json, expo-location), and Google Play rejects a permission declared + * twice with different maxSdkVersions. So the capped copies go; Bluetooth scanning keeps its + * `neverForLocation` flag. + */ +const LOCATION = new Set(["android.permission.ACCESS_COARSE_LOCATION", "android.permission.ACCESS_FINE_LOCATION"]); +const withUncappedLocation = (config: ExpoConfig): ExpoConfig => + withAndroidManifest(config, (c) => { + const m = c.modResults.manifest as { "uses-permission-sdk-23"?: { $: Record }[] }; + const sdk23 = m["uses-permission-sdk-23"]; + if (sdk23) m["uses-permission-sdk-23"] = sdk23.filter((p) => !(LOCATION.has(p.$["android:name"]) && p.$["android:maxSdkVersion"])); + return c; + }) as ExpoConfig; + +/** Every build's config plugins of our own. */ +const withOwnPlugins = (config: ExpoConfig): ExpoConfig => withUncappedLocation(withReleaseSigning(config)); + /** * The builds besides production (app.json), by APP_VARIANT. Each has its own package id, so it sits next * to the production app with its own storage instead of replacing it, and its own icon colour tells them @@ -88,12 +107,12 @@ export default ({ config }: ConfigContext): ExpoConfig => { extra: { ...base.extra, commit: process.env.GIT_COMMIT ?? "" }, }; const name = process.env.APP_VARIANT; - if (!name) return withReleaseSigning(app); + if (!name) return withOwnPlugins(app); const v = VARIANTS[name]; // A typo must not silently build the production app. if (!v) throw new Error(`APP_VARIANT=${name}: expected one of ${Object.keys(VARIANTS).join(", ")}, or unset for production`); const icons = `./assets/icons/${v.icons}`; - return withReleaseSigning({ + return withOwnPlugins({ ...app, name: v.name, scheme: `openclapper-${v.slug}`, diff --git a/docs/known-issues.md b/docs/known-issues.md index 7776045..6b47a6c 100644 --- a/docs/known-issues.md +++ b/docs/known-issues.md @@ -51,3 +51,7 @@ The task view draws each workspace's windows as outlined boxes with the app's ic ## Vignetting is a rough indication, and a native dependency (issue #266) A rig's vignetting (Library › Rigs) is three numbers per focal length, interpolated between them: it ignores the aperture and the real falloff curve of the lens, so the darkened corners in the viewfinder and on photos are a hint of what the rig will show, not a measurement. On the phone the layer is an SVG radial gradient (`react-native-svg`, a native module): an installed app needs a new dev build or APK before it shows. A step of a sequence shows the vignette of its framing (or of the frame its overlay was drawn for). + +## The Bluetooth plugin's location permissions are removed (lights #208) + +`@sfourdrinier/react-native-ble-plx` with `neverForLocation` declares the location permissions a second time, capped at Android 11. Google Play rejects a permission declared twice with different `maxSdkVersion`s, so `withUncappedLocation` in `apps/mobile/app.config.ts` removes the capped copies; the app keeps them uncapped for GPS. A plugin update that declares them another way would bring the rejection back: Build phone app now fails when an upload is rejected (it used to pass, because the step piped into `tee`).