aboutsummaryrefslogtreecommitdiffstats
path: root/android/app/src/main/java
diff options
context:
space:
mode:
authorJurjen de Vries <[email protected]>2025-09-11 00:48:15 +0200
committerGitHub <[email protected]>2025-09-11 00:48:15 +0200
commit0c69c9848c6b98c92609d209103efc60003c9723 (patch)
tree445121def885f13d0f80c06864ad2ff4d5ef95a1 /android/app/src/main/java
parent2abcf6e435fca5d86960f3ba4228002bfb0a19e6 (diff)
parent9277b2921e09ee9dd5f39cf4af30a2330f4d95d1 (diff)
downloadcoinos-ui-0c69c9848c6b98c92609d209103efc60003c9723.tar.gz
coinos-ui-0c69c9848c6b98c92609d209103efc60003c9723.zip
Merge branch 'coinos:master' into master
Diffstat (limited to 'android/app/src/main/java')
-rw-r--r--android/app/src/main/java/io/coinos/MainActivity.java208
-rw-r--r--android/app/src/main/java/io/coinos/nfcwriter/NfcWriterPlugin.java62
2 files changed, 209 insertions, 61 deletions
diff --git a/android/app/src/main/java/io/coinos/MainActivity.java b/android/app/src/main/java/io/coinos/MainActivity.java
index 7f710952..271ee363 100644
--- a/android/app/src/main/java/io/coinos/MainActivity.java
+++ b/android/app/src/main/java/io/coinos/MainActivity.java
@@ -1,81 +1,167 @@
package io.coinos;
+import android.os.Build;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import androidx.core.view.ViewCompat;
+
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Bridge;
-import com.getcapacitor.PluginCall;
-import com.getcapacitor.PluginHandle;
+
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Parcelable;
import android.webkit.CookieManager;
import android.webkit.WebView;
+import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
+import android.nfc.NfcAdapter;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+
+import io.coinos.nfcwriter.NfcWriterPlugin;
+
public class MainActivity extends BridgeActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ private NfcAdapter nfcAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ // ✅ Let Capacitor inflate its layout and wire everything
+ super.onCreate(savedInstanceState);
+ registerPlugin(NfcWriterPlugin.class);
+
+ WebView webView = bridge.getWebView(); // This works *after* super.onCreate()
+
+ // ✅ Ensure layout respects system bars
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ }
+
+ // ✅ Apply top inset padding if needed
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ webView.setOnApplyWindowInsetsListener((v, insets) -> {
+ v.setPadding(0, insets.getSystemWindowInsetTop(), 0, 0);
+ return insets.consumeSystemWindowInsets();
+ });
+ }
+
+ // Other app setup
+ CookieManager cookieManager = CookieManager.getInstance();
+ cookieManager.setAcceptCookie(true);
+ webView.getSettings().setJavaScriptEnabled(true);
+ webView.getSettings().setDomStorageEnabled(true);
+
+ handleIntent(getIntent());
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+ handleIntent(intent);
+ }
+
+ private void handleIntent(Intent intent) {
+ if (intent == null) return;
- WebView webView = bridge.getWebView();
- CookieManager cookieManager = CookieManager.getInstance();
- cookieManager.setAcceptCookie(true);
- webView.getSettings().setJavaScriptEnabled(true);
- webView.getSettings().setDomStorageEnabled(true);
+ String action = intent.getAction();
+ Uri data = null;
- Intent intent = getIntent();
- if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
- Uri data = intent.getData();
- if (data != null) {
- String url = data.toString();
- Bridge bridge = getBridge();
-
- if (bridge != null) {
- String encodedUrl = Uri.encode(url);
- String destinationUrl = "https://coinos.io/send/" + encodedUrl;
+ if (Intent.ACTION_VIEW.equals(action)) {
+ data = intent.getData();
+ } else if ("android.nfc.action.NDEF_DISCOVERED".equals(action)) {
+ Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
+ if (rawMsgs != null && rawMsgs.length > 0) {
+ NdefMessage ndefMessage = (NdefMessage) rawMsgs[0];
+ for (NdefRecord record : ndefMessage.getRecords()) {
+ if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN &&
+ Arrays.equals(record.getType(), NdefRecord.RTD_URI)) {
- bridge.getWebView().post(() -> {
- bridge.getWebView().loadUrl(destinationUrl);
- });
- }
- }
- }
- }
+ byte[] payload = record.getPayload();
+ byte prefix = payload[0];
+ String uriPrefix = resolveUriPrefix(prefix);
+ String uriBody = new String(Arrays.copyOfRange(payload, 1, payload.length), Charset.forName("UTF-8"));
+ data = Uri.parse(uriPrefix + uriBody);
+ break;
+ }
+ }
+ }
+ }
- @Override
- public void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- setIntent(intent);
- if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
- Uri data = intent.getData();
- if (data != null) {
- String url = data.toString();
+ if (data != null) {
+ String url = data.toString();
+ Bridge bridge = getBridge();
+ if (bridge != null) {
+ String encodedUrl = Uri.encode(url);
+ String destinationUrl = "https://coinos.io/send/" + encodedUrl;
- // Dispatch deep link when app is already open
- Bridge bridge = getBridge();
- if (bridge != null) {
- String encodedUrl = Uri.encode(url);
- String destinationUrl = "https://coinos.io/send/" + encodedUrl;
+ bridge.getWebView().post(() -> {
+ bridge.getWebView().loadUrl(destinationUrl);
+ });
+ }
+ }
+ }
- bridge.getWebView().post(() -> {
- bridge.getWebView().loadUrl(destinationUrl);
- });
- }
- }
- }
- }
+ private String resolveUriPrefix(byte prefix) {
+ switch (prefix) {
+ case 0x00: return "";
+ case 0x01: return "http://www.";
+ case 0x02: return "https://www.";
+ case 0x03: return "http://";
+ case 0x04: return "https://";
+ case 0x05: return "tel:";
+ case 0x06: return "mailto:";
+ case 0x07: return "ftp://anonymous:anonymous@";
+ case 0x08: return "ftp://ftp.";
+ case 0x09: return "ftps://";
+ case 0x0A: return "sftp://";
+ case 0x0B: return "smb://";
+ case 0x0C: return "nfs://";
+ case 0x0D: return "ftp://";
+ case 0x0E: return "dav://";
+ case 0x0F: return "news:";
+ case 0x10: return "telnet://";
+ case 0x11: return "imap:";
+ case 0x12: return "rtsp://";
+ case 0x13: return "urn:";
+ case 0x14: return "pop:";
+ case 0x15: return "sip:";
+ case 0x16: return "sips:";
+ case 0x17: return "tftp:";
+ case 0x18: return "btspp://";
+ case 0x19: return "btl2cap://";
+ case 0x1A: return "btgoep://";
+ case 0x1B: return "tcpobex://";
+ case 0x1C: return "irdaobex://";
+ case 0x1D: return "file://";
+ case 0x1E: return "urn:epc:id:";
+ case 0x1F: return "urn:epc:tag:";
+ case 0x20: return "urn:epc:pat:";
+ case 0x21: return "urn:epc:raw:";
+ case 0x22: return "urn:epc:";
+ case 0x23: return "urn:nfc:";
+ default: return "";
+ }
+ }
- @Override
- public void onPause() {
- super.onPause();
- CookieManager.getInstance().flush();
- }
+ @Override
+ public void onPause() {
+ super.onPause();
+ CookieManager.getInstance().flush();
+ }
- @Override
- public void onBackPressed() {
- WebView webView = getBridge().getWebView();
- if (webView.canGoBack()) {
- webView.goBack();
- } else {
- super.onBackPressed(); // Default behavior, which minimizes the app
- }
- }
+ @Override
+ public void onBackPressed() {
+ WebView webView = getBridge().getWebView();
+ if (webView.canGoBack()) {
+ webView.goBack();
+ } else {
+ super.onBackPressed();
+ }
+ }
}
diff --git a/android/app/src/main/java/io/coinos/nfcwriter/NfcWriterPlugin.java b/android/app/src/main/java/io/coinos/nfcwriter/NfcWriterPlugin.java
new file mode 100644
index 00000000..d2954e9b
--- /dev/null
+++ b/android/app/src/main/java/io/coinos/nfcwriter/NfcWriterPlugin.java
@@ -0,0 +1,62 @@
+// src/android/NfcWriterPlugin.java
+package io.coinos.nfcwriter;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.nfc.NfcAdapter.ReaderCallback;
+import android.os.Bundle;
+import android.util.Log;
+
+import com.getcapacitor.Plugin;
+import com.getcapacitor.PluginCall;
+import com.getcapacitor.PluginMethod;
+import com.getcapacitor.annotation.CapacitorPlugin;
+
+@CapacitorPlugin(name = "NfcWriter")
+public class NfcWriterPlugin extends Plugin {
+ private NfcAdapter nfcAdapter;
+
+ @Override
+ public void load() {
+ super.load();
+ nfcAdapter = NfcAdapter.getDefaultAdapter(getContext());
+ }
+
+ @PluginMethod
+ public void enableExclusiveNfcMode(PluginCall call) {
+ if (nfcAdapter == null) {
+ call.reject("NFC adapter not available");
+ return;
+ }
+
+ nfcAdapter.enableReaderMode(
+ getActivity(),
+ new ReaderCallback() {
+ @Override
+ public void onTagDiscovered(Tag tag) {
+ Log.d("NfcWriter", "Tag discovered");
+ bridge.getWebView().post(() -> {
+ bridge.getWebView().evaluateJavascript(
+ "window.dispatchEvent(new CustomEvent('nativeNfcTagDiscovered'))",
+ null
+ );
+ });
+ }
+ },
+ NfcAdapter.FLAG_READER_NFC_A |
+ NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK |
+ NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
+ null
+ );
+
+ call.resolve();
+ }
+
+ @PluginMethod
+ public void disableExclusiveNfcMode(PluginCall call) {
+ if (nfcAdapter != null) {
+ nfcAdapter.disableReaderMode(getActivity());
+ }
+ call.resolve();
+ }
+}