diff options
| author | Adam Soltys <[email protected]> | 2026-10-13 06:51:13 +0000 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-13 06:51:13 +0000 |
| commit | 90bc4d3d54b91cb9845cda4edc53ed148ae00251 (patch) | |
| tree | cdb1d23efbb37e6e78ed882ad1159da4c956876a /android/app | |
| parent | 8d7620874fe39b7226fb2ccfd4761b0a08b230dd (diff) | |
| download | coinosv3-90bc4d3d54b91cb9845cda4edc53ed148ae00251.tar.gz coinosv3-90bc4d3d54b91cb9845cda4edc53ed148ae00251.zip | |
Android 1.14 (code 15): UnifiedPush only where web push can't reach the app. isolabellart asked why Coinos opens a prompt inside ntfy: every launch of the TWA asked whatever UnifiedPush distributor was installed for an endpoint (and asked for notification permission for it), Play Services or not. UnifiedPush is there for phones without Google Play Services (GrapheneOS and the like); with Play Services, web push reaches Chrome — and so the TWA — through Google already, and asking ntfy too only put up its prompt (and would bring every notification twice). The TWA now asks a distributor only when Play Services isn't installed and enabled (Push.playServices; its package named in the manifest's queries for Android 11+), or when it already holds an endpoint — whoever has one has been through the prompt and may be counting on it. The WebView builds (webview, fdroid) are unchanged: web push never reaches a WebView, so UnifiedPush is their only way in either way.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KPw21NEpWeTGu6swVASmBt
Diffstat (limited to 'android/app')
| -rw-r--r-- | android/app/build.gradle | 4 | ||||
| -rw-r--r-- | android/app/src/main/AndroidManifest.xml | 3 | ||||
| -rw-r--r-- | android/app/src/main/java/io/coinos/app/Push.java | 13 | ||||
| -rw-r--r-- | android/app/src/twa/java/io/coinos/app/LauncherActivity.java | 12 |
4 files changed, 28 insertions, 4 deletions
diff --git a/android/app/build.gradle b/android/app/build.gradle index 381e277..0119e93 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -29,8 +29,8 @@ android { applicationId 'io.coinos.app' minSdk 24 targetSdk 35 - versionCode 14 - versionName '1.13' + versionCode 15 + versionName '1.14' } // Two builds of the same wallet. // diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0444b76..2f0f950 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -14,6 +14,9 @@ <intent> <action android:name="org.unifiedpush.android.distributor.REGISTER" /> </intent> + <!-- whether Google Play Services is here (Push.playServices): with it, the + TWA's web push works and UnifiedPush isn't asked --> + <package android:name="com.google.android.gms" /> </queries> <application android:label="@string/app_name" diff --git a/android/app/src/main/java/io/coinos/app/Push.java b/android/app/src/main/java/io/coinos/app/Push.java index 925693a..932fc11 100644 --- a/android/app/src/main/java/io/coinos/app/Push.java +++ b/android/app/src/main/java/io/coinos/app/Push.java @@ -120,6 +120,19 @@ public final class Push { p.edit().putInt(KEY_TRY, p.getInt(KEY_TRY, 0) + 1).putLong(KEY_TRY_AT, 0).remove(KEY_DIST).apply(); } + /** + * Google Play Services, installed and switched on — what web push on + * Android runs through. (Its package is named in the manifest's queries: + * Android 11+ hides it otherwise.) + */ + static boolean playServices(Context c) { + try { + return c.getPackageManager().getApplicationInfo("com.google.android.gms", 0).enabled; + } catch (Exception e) { + return false; + } + } + static String endpoint(Context c) { return prefs(c).getString(KEY_ENDPOINT, null); } diff --git a/android/app/src/twa/java/io/coinos/app/LauncherActivity.java b/android/app/src/twa/java/io/coinos/app/LauncherActivity.java index bf960e2..6e05403 100644 --- a/android/app/src/twa/java/io/coinos/app/LauncherActivity.java +++ b/android/app/src/twa/java/io/coinos/app/LauncherActivity.java @@ -27,12 +27,20 @@ public class LauncherActivity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // UnifiedPush is for phones without Google Play Services (GrapheneOS and + // the like, without the sandboxed Play): web push reaches Chrome — and so + // this app — through Google, and with it there it already does. Asking + // ntfy as well there only put up its prompt in an app the user hadn't + // asked for anything (and would have brought every notification twice). + // A registration already made is kept: whoever has one has been through + // the prompt, and may be counting on it. + boolean unifiedPush = !Push.playServices(this) || Push.endpoint(this) != null; // Ask the distributor on every launch: it's idempotent, and it's how a // distributor installed after us ever gets noticed. - Push.register(this); + if (unifiedPush) Push.register(this); // Android 13+ won't show our notifications without this, and the TWA's // own permission covers the browser's, not ours. - if (Build.VERSION.SDK_INT >= 33 + if (unifiedPush && Build.VERSION.SDK_INT >= 33 && checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED && Push.distributor(this) != null) { try { requestPermissions(new String[] { Manifest.permission.POST_NOTIFICATIONS }, 1); } catch (Exception ignored) {} |
