feat(wallet-android): camera + notification permissions, prompted at launch
The APK had neither declared, so Settings → Apps → Deviant → Permissions was effectively empty. First-time users would hit a dead end on "Scan QR" and never receive a system notification for incoming WalletConnect / WizardConnect sign requests. Manifest additions: - android.permission.CAMERA (for @capacitor-mlkit/barcode-scanning) - android.hardware.camera + .front as uses-feature required=false (declares front-camera support without blocking cameraless installs) - android.permission.POST_NOTIFICATIONS (required API 33+) App.tsx: new one-shot startup effect on native platforms that calls BarcodeScanner.requestPermissions() + Notification.requestPermission() once per install (tracked via localStorage key `deviant.native-perms.requested`). Android requires user consent via the system dialog — this triggers both dialogs on first launch so Settings shows them as granted from the start, instead of the user hitting the dead-end later. capacitor.build.gradle + capacitor.settings.gradle regenerated by cap sync alongside this change. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
0a0ee52750
commit
a7c0a0eea5
4 changed files with 39 additions and 8 deletions
|
|
@ -9,6 +9,7 @@ android {
|
|||
|
||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
implementation project(':capacitor-mlkit-barcode-scanning')
|
||||
implementation project(':capgo-capacitor-native-biometric')
|
||||
implementation project(':capacitor-secure-storage-plugin')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
|
|
@ -8,7 +7,6 @@
|
|||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
|
||||
android:name=".MainActivity"
|
||||
|
|
@ -16,12 +14,10 @@
|
|||
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||
android:launchMode="singleTask"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
|
|
@ -29,9 +25,7 @@
|
|||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths"></meta-data>
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
|
|
@ -43,4 +37,15 @@
|
|||
USE_FINGERPRINT covers API 23–27. -->
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
|
||||
<!-- QR scanner (@capacitor-mlkit/barcode-scanning for WalletConnect pairings,
|
||||
addresses, BIP-21 URIs). CAMERA covers all cameras; the two uses-feature
|
||||
hints are optional so the APK still installs on cameraless devices. -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
|
||||
|
||||
<!-- Push + in-app notifications (incoming WC/WZ sign requests, confirmed txs).
|
||||
POST_NOTIFICATIONS is required for API 33+ to show any notification. -->
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
</manifest>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||
|
||||
include ':capacitor-mlkit-barcode-scanning'
|
||||
project(':capacitor-mlkit-barcode-scanning').projectDir = new File('../node_modules/@capacitor-mlkit/barcode-scanning/android')
|
||||
|
||||
include ':capgo-capacitor-native-biometric'
|
||||
project(':capgo-capacitor-native-biometric').projectDir = new File('../node_modules/@capgo/capacitor-native-biometric/android')
|
||||
|
||||
|
|
|
|||
|
|
@ -155,6 +155,28 @@ export function App() {
|
|||
// The CosmoGenesis loading splash (index.html) stays up until the user taps it —
|
||||
// it dismisses itself on that gesture, so the shell does not auto-dismiss it here.
|
||||
|
||||
// Native: proactively request camera + notifications on first launch so they
|
||||
// show up in Settings as "allowed" and the user doesn't hit a dead-end the
|
||||
// first time they tap "Scan QR" or expect an incoming sign-request push.
|
||||
// Android requires user consent for both — the dialog fires once per install.
|
||||
useEffect(() => {
|
||||
if (!Capacitor.isNativePlatform()) return;
|
||||
const KEY = 'deviant.native-perms.requested';
|
||||
try { if (localStorage.getItem(KEY)) return; } catch { /* private mode */ }
|
||||
(async () => {
|
||||
try {
|
||||
const { BarcodeScanner } = await import('@capacitor-mlkit/barcode-scanning');
|
||||
await BarcodeScanner.requestPermissions();
|
||||
} catch { /* plugin missing or declined — Settings still carries the entry */ }
|
||||
try {
|
||||
if (typeof Notification !== 'undefined' && Notification.permission === 'default') {
|
||||
await Notification.requestPermission();
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
try { localStorage.setItem(KEY, '1'); } catch { /* ignore */ }
|
||||
})();
|
||||
}, []);
|
||||
|
||||
// Boot: dev-wallet shortcut first (chipnet-only escape hatch), then KeyStore.
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue