Add self-hosted update system via Forgejo releases

The app now checks for new APK releases on a Forgejo instance and can
download and install them without leaving the app.

Settings:
- New "Update repository URL" field (e.g. https://git.example.com/user/fabled_app)
- "App version" tile with a manual "Check" button and live status display
- Download progress bar and "Install" button appear when update is found

Startup:
- Shell runs a silent background check on first load when a repo URL is set
- A dialog appears automatically if a newer release is found

Provider (update_provider.dart):
- UpdateNotifier: idle → checking → available → downloading → available
- Hits Forgejo /api/v1/repos/{owner}/{repo}/releases/latest
- Parses semver tag, finds .apk asset, downloads with progress via Dio
- Opens the APK with open_file to trigger the system package installer

Android:
- REQUEST_INSTALL_PACKAGES permission
- FileProvider configured for open_file (shares APK URI with installer)
- res/xml/file_paths.xml covers external-files and cache directories

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 14:08:17 -05:00
parent 6e996d9d2e
commit ad3b317115
11 changed files with 533 additions and 2 deletions
+14
View File
@@ -1,4 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:label="fabled_app"
android:name="${applicationName}"
@@ -38,6 +40,18 @@
android:resource="@xml/chat_widget_info" />
</receiver>
<!-- FileProvider — required by open_file to share the APK URI
with the system package installer on Android 7+ -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<!-- App-specific external storage: getExternalStorageDirectory() -->
<external-files-path name="apk_download" path="." />
<!-- Fallback: getTemporaryDirectory() -->
<cache-path name="apk_cache" path="." />
</paths>