feat(mobile): self-update dialog with verified APK download and install (M5)
ci / ts / ts (packages + web) (push) Successful in 1m0s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 57s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m33s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 35s

Checks the server for a newer release at most every 6 hours and on
demand in Profile, shows release notes, downloads the APK with progress,
verifies SHA-256 in 1 MB chunks and hands it to the system installer.
Updates below min_supported cannot be dismissed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Opus 5.5 committed 2026-10-20 12:55:34 +03:00
1 parent 6a67c27f50
commit 765345e0f4
10 files changed
+663 -78

No files matched your search

+7 -3
View File
@@ -75,13 +75,17 @@
2. Если `version_code` новее — диалог с changelog (Markdown из релиза), кнопки «Обновить» / «Позже».
Если текущая версия ниже `min_supported` — обновление обязательно.
3. Загрузка APK через `expo-file-system` в `cacheDirectory` с прогрессом; проверка **SHA-256** (значение из релиза).
4. Установка: `Intent.ACTION_VIEW` с `content://` URI через `FileProvider` и флагом `FLAG_GRANT_READ_URI_PERMISSION`
(небольшой локальный Expo-модуль `modules/apk-installer` на Kotlin; при необходимости — `PackageInstaller` session API).
Хэш считается кусками по 1 МБ (`js-sha256`), APK целиком в память JS не читается. Загрузка идёт с `Bearer`,
сервер отдаёт файл с поддержкой `Range` и сам сверяет SHA-256 при кэшировании из Gitea.
4. Установка: `Intent.ACTION_VIEW` с `content://` URI (`FileSystem.getContentUriAsync` — FileProvider expo-file-system)
и флагом `FLAG_GRANT_READ_URI_PERMISSION` через `expo-intent-launcher` (`src/lib/update.ts`).
5. Если нет разрешения «установка из неизвестных источников» — открываем `Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES`
для нашего пакета с пояснением.
**Требования:**
- В манифесте: `REQUEST_INSTALL_PACKAGES`, `FileProvider`.
- В манифесте: `REQUEST_INSTALL_PACKAGES` (FileProvider добавляет expo-file-system).
- Сервер: `GITEA_URL`, `GITEA_REPO`, `GITEA_TOKEN`, кэш APK — `UPDATES_DIR` (`/updates`). Без них — `404 app.update_unavailable`,
приложение молча пропускает проверку.
- Все релизы подписываются **одним и тем же ключом** (keystore в секретах CI) — иначе Android откажет в обновлении.
- `versionCode` монотонно растёт: `major·1 000 000 + minor·10 000 + patch·100 + (99 | rc)` (см. [ci-cd.md](ci-cd.md#версионирование)).
- Ассеты релиза: `pipu-music-<version>.apk`, `pipu-music-<version>.apk.sha256`.