The Android app kept a pending browser sign-in in a thread inside the login screen. Android often kills the process while the browser is in front, so the approval reached the server but nothing collected it, and the app came back signed out with nothing saved. The pending device code is now kept in Prefs and collected whenever the login screen resumes. The app passes return_url=keeporg://device-approved when it starts the sign-in, and the server's approval page, after a password or single sign-on, links back to it. Only the keeporg: scheme is accepted. Against a server older than 0.9, which rejects the field, the app retries without it. Verified on an Android 15 emulator: approval collected after the process was killed, and the fallback against the 0.8 server. Server 0.9.0, Android 0.3.0 (versionCode 3). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
66 lines
2.8 KiB
XML
66 lines
2.8 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
|
|
<uses-permission android:name="android.permission.INTERNET" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
|
|
<application
|
|
android:allowBackup="false"
|
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
|
android:fullBackupContent="@xml/backup_rules"
|
|
android:icon="@mipmap/ic_launcher"
|
|
android:label="@string/app_name"
|
|
android:theme="@style/AppTheme">
|
|
|
|
<activity
|
|
android:name=".MainActivity"
|
|
android:exported="true">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN" />
|
|
<category android:name="android.intent.category.LAUNCHER" />
|
|
</intent-filter>
|
|
</activity>
|
|
|
|
<!-- Exported for one link: the server's device-approval page offers
|
|
keeporg://device-approved to bring the user back from the
|
|
browser. Opening it only makes this screen collect the sign-in
|
|
it already started; it carries no data. singleTask brings back
|
|
the waiting instance instead of stacking a new one on the
|
|
browser. -->
|
|
<activity
|
|
android:name=".LoginActivity"
|
|
android:exported="true"
|
|
android:label="@string/sign_in"
|
|
android:launchMode="singleTask">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.VIEW" />
|
|
<category android:name="android.intent.category.DEFAULT" />
|
|
<category android:name="android.intent.category.BROWSABLE" />
|
|
<data
|
|
android:host="device-approved"
|
|
android:scheme="keeporg" />
|
|
</intent-filter>
|
|
</activity>
|
|
|
|
<service
|
|
android:name=".SyncService"
|
|
android:exported="false"
|
|
android:foregroundServiceType="dataSync" />
|
|
|
|
<!-- The databases appear in every file picker as a storage provider,
|
|
so KeePassDX or Keepass2Android opens them like any other file. -->
|
|
<provider
|
|
android:name=".KeepOrgProvider"
|
|
android:authorities="cc.tiredsysadmin.android.keeporg.documents"
|
|
android:exported="true"
|
|
android:grantUriPermissions="true"
|
|
android:permission="android.permission.MANAGE_DOCUMENTS">
|
|
<intent-filter>
|
|
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
|
</intent-filter>
|
|
</provider>
|
|
</application>
|
|
</manifest>
|