diff options
Diffstat (limited to 'android/app/src/twa/java/io')
3 files changed, 110 insertions, 0 deletions
diff --git a/android/app/src/twa/java/io/coinos/app/IntentActivity.java b/android/app/src/twa/java/io/coinos/app/IntentActivity.java new file mode 100644 index 0000000..3de1d62 --- /dev/null +++ b/android/app/src/twa/java/io/coinos/app/IntentActivity.java @@ -0,0 +1,35 @@ +package io.coinos.app; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; + +/** + * Trampoline for scheme + NFC intents. A TWA already on screen ignores a + * new intent delivered to its (still-alive) launcher, so a second + * lightning: tap used to do nothing. This activity exists per-intent: + * it maps the URI to the web app's ?u= form and relaunches LauncherActivity + * with CLEAR_TOP — the Chrome activity above it is cleared, the launcher is + * recreated with the new data, and the TWA navigates. Then it's gone. + */ +public class IntentActivity extends android.app.Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Uri url = Uri.parse("https://v3.coinos.io/"); + Uri data = getIntent().getData(); + if (data != null) { + String scheme = data.getScheme(); + if (scheme != null && !scheme.equals("https") && !scheme.equals("http")) { + url = Uri.parse("https://v3.coinos.io/?u=" + Uri.encode(data.toString())); + } else { + url = data; + } + } + Intent i = new Intent(this, LauncherActivity.class); + i.setData(url); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + startActivity(i); + finish(); + } +} diff --git a/android/app/src/twa/java/io/coinos/app/LauncherActivity.java b/android/app/src/twa/java/io/coinos/app/LauncherActivity.java new file mode 100644 index 0000000..654265b --- /dev/null +++ b/android/app/src/twa/java/io/coinos/app/LauncherActivity.java @@ -0,0 +1,54 @@ +package io.coinos.app; + +import android.Manifest; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; + +import java.net.URLEncoder; + +/** + * The TWA launcher. Scheme/NFC intents arrive via IntentActivity (the + * trampoline that survives the running-TWA case); this activity only needs + * to honor a full URL handed to it, falling back to the site root. + * + * <p>It also carries the UnifiedPush endpoint across: the Android side is + * what a distributor talks to, and the web app is what knows which pubkeys + * to watch, so the endpoint rides into the web app as ?up= exactly the way + * payment intents ride in as ?u=. + */ +public class LauncherActivity + extends com.google.androidbrowserhelper.trusted.LauncherActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Ask the distributor on every launch: it's idempotent, and it's how a + // distributor installed after us ever gets noticed. + 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 + && checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED + && Push.distributor(this) != null) { + try { requestPermissions(new String[] { Manifest.permission.POST_NOTIFICATIONS }, 1); } catch (Exception ignored) {} + } + } + + @Override + protected Uri getLaunchingUrl() { + Uri data = getIntent().getData(); + Uri base = (data != null && "v3.coinos.io".equals(data.getHost())) ? data : super.getLaunchingUrl(); + String endpoint = Push.endpoint(this); + if (endpoint == null || Push.endpointDelivered(this)) return base; + try { + String sep = base.toString().contains("?") ? "&" : "?"; + Uri withEndpoint = Uri.parse(base + sep + "up=" + URLEncoder.encode(endpoint, "UTF-8")); + Push.markEndpointDelivered(this); + return withEndpoint; + } catch (Exception e) { + return base; + } + } +} diff --git a/android/app/src/twa/java/io/coinos/app/Wake.java b/android/app/src/twa/java/io/coinos/app/Wake.java new file mode 100644 index 0000000..558a6f5 --- /dev/null +++ b/android/app/src/twa/java/io/coinos/app/Wake.java @@ -0,0 +1,21 @@ +package io.coinos.app; + +import android.content.Context; + +/** + * Whether this build can wake the wallet itself. + * + * <p>This is the TWA build's answer: no. The wallet lives in Chrome's storage + * for its own origin, and nothing in this app can reach into that, so a push + * can only raise a notification for someone to tap. The WebView build has its + * own version of this class (src/webview) that says yes. One class per + * flavor, so the shared receiver needs no flavor checks. + */ +final class Wake { + private Wake() {} + + /** @return true when the wallet was woken and the notification isn't needed. */ + static boolean start(Context context, String payload) { + return false; + } +} |
