appdate contains Appdate, a local-first Android utility prototype for finding disabled apps and routing them to safe update or uninstall flows.
Android does not allow an ordinary third-party app to silently update, uninstall, enable, or disable other apps. Appdate therefore keeps disabled apps disabled by never changing their enabled state. It detects disabled packages with public PackageManager APIs and opens matching Play Store, Galaxy Store, F-Droid, app-info, or Android uninstall screens when available.
app/- native Android app source, written in Kotlin with Jetpack Compose and Material 3.scripts/build-apk.sh- Gradle-backed debug APK builder for local sideload testing.scripts/resolve-play-release.sh- SemVer-to-Play-track resolver used by GitHub Actions.site/- static GitHub Pages-ready website forhttps://droidappdate.com.
The Android application id is com.nikolay.appdate.
From this directory:
./scripts/build-apk.shThe signed debug APK is written to:
build/outputs/apk/appdate-debug.apk
If the site download folder exists, the script also copies the APK to:
site/downloads/appdate-debug.apk
Google Play uploads should use the Gradle Android App Bundle build, not the debug APK:
export JAVA_HOME=/opt/homebrew/Cellar/openjdk@17/17.0.19/libexec/openjdk.jdk/Contents/Home
export ANDROID_HOME=$HOME/Library/Android/sdk
./scripts/build-play-bundle.shRelease signing is configured through these environment variables or Gradle properties:
APPDATE_RELEASE_STORE_FILE
APPDATE_RELEASE_STORE_PASSWORD
APPDATE_RELEASE_KEY_ALIAS
APPDATE_RELEASE_KEY_PASSWORD
See PLAY_STORE.md for signing, upload, and QUERY_ALL_PACKAGES policy notes.
The Android Release workflow publishes tagged builds to Google Play. Push a SemVer tag to choose the Play track:
v1.2.3->productionv1.2.3-rc.1orv1.2.3-beta.1->betav1.2.3-alpha.1->alphav1.2.3-internal.1,v1.2.3-dev.1,v1.2.3-snapshot.1, or any other prerelease label ->internal
The workflow also supports manual dispatch with an explicit track override.
Tag-triggered workflow runs also create a GitHub Release and attach the signed Android App Bundle. The release asset is the Play upload bundle, not a directly installable phone package.
Configure these GitHub repository secrets before publishing:
APPDATE_UPLOAD_KEYSTORE_BASE64
APPDATE_RELEASE_STORE_PASSWORD
APPDATE_RELEASE_KEY_ALIAS
APPDATE_RELEASE_KEY_PASSWORD
APPDATE_UPLOAD_KEYSTORE_BASE64 should be the base64-encoded upload keystore file.
Configure these GitHub repository variables before publishing:
GCP_WORKLOAD_IDENTITY_PROVIDER
GCP_SERVICE_ACCOUNT_EMAIL
The workflow uses Google Cloud Workload Identity Federation, so no long-lived service-account key JSON is stored in GitHub.
The Android app and static site both follow the system light/dark setting.
- Android uses Material 3 dynamic color on supported devices, falls back to light/dark Material color schemes, and keeps package scanning off the UI thread.
- The static site uses
color-scheme: light darkandprefers-color-scheme: darkCSS token overrides.
Install the APK on a connected Android device:
$HOME/Library/Android/sdk/platform-tools/adb install -r build/outputs/apk/appdate-debug.apkOpen the static site directly from site/index.html, or serve it locally:
python3 -m http.server 8080 --directory site- Appdate cannot directly read Google Play or Galaxy Store pending-update queues for arbitrary packages through public Android APIs.
- Play Store, Galaxy Store, and F-Droid actions are shown only when Android reports that source for the app and a matching handoff is available.
- Silent update while disabled requires privileged/system, device-owner, root, or ADB-level authority. This prototype intentionally avoids pretending otherwise.
QUERY_ALL_PACKAGESis included because listing disabled packages requires broad package visibility on modern Android. That permission has Play Store policy implications and must be declared/justified in Play Console.