Android 업데이트 설치: 첫 시도가 다른 오류로 실패하면 1초 뒤 한 번 더 · 원문은 작업 기록에 (170 보충)

폴드에서 첫 시도만 실패하고 두 번째에 바로 된 일 (접은 화면 · 화면 전환 중으로 보임) - 사용자가 두 번 누르지 않아도 되게.
화면에 보이지 않는 첫 시도의 실패 원문 · "허용 필요로 왔지만 허용돼 있음" 은 app.log 에 남겨 다음에 진짜 원인을 볼 수 있게.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
묶음4
RyuJongJin 2026-10-10 03:30:27 +09:00
parent bf72557fc3
commit b1f2b1aef4
5 changed files with 26 additions and 2 deletions

View File

@ -1210,7 +1210,9 @@
"업데이트": "Update", "업데이트": "Update",
"업데이트 · 버전 고르기": "Update · choose version", "업데이트 · 버전 고르기": "Update · choose version",
"업데이트 · 설치하고 남은 파일": "Update · install leftovers", "업데이트 · 설치하고 남은 파일": "Update · install leftovers",
"업데이트 설치 화면 열기 첫 시도 실패 (1초 뒤 다시): {0}": "Update: first attempt to open the installer failed (retrying in 1 s): {0}",
"업데이트 실패: {0}": "Update failed: {0}", "업데이트 실패: {0}": "Update failed: {0}",
"업데이트: 설치 허용 필요로 왔지만 허용돼 있어 다시 엽니다: {0}": "Update: reported 'install permission needed' but it is allowed, opening again: {0}",
"업데이트로 바뀐 기본값 알림": "Notify about defaults changed by updates", "업데이트로 바뀐 기본값 알림": "Notify about defaults changed by updates",
"없는 경로": "path not found", "없는 경로": "path not found",
"없는 경로: {0}": "path not found: {0}", "없는 경로: {0}": "path not found: {0}",

View File

@ -1210,7 +1210,9 @@
"업데이트": "更新", "업데이트": "更新",
"업데이트 · 버전 고르기": "更新 · バージョンを選ぶ", "업데이트 · 버전 고르기": "更新 · バージョンを選ぶ",
"업데이트 · 설치하고 남은 파일": "更新・インストールの残り", "업데이트 · 설치하고 남은 파일": "更新・インストールの残り",
"업데이트 설치 화면 열기 첫 시도 실패 (1초 뒤 다시): {0}": "アップデート: インストール画面を開く最初の試行が失敗 (1 秒後に再試行): {0}",
"업데이트 실패: {0}": "更新失敗: {0}", "업데이트 실패: {0}": "更新失敗: {0}",
"업데이트: 설치 허용 필요로 왔지만 허용돼 있어 다시 엽니다: {0}": "アップデート: インストール許可が必要と返されたが許可済みのため再度開きます: {0}",
"업데이트로 바뀐 기본값 알림": "アップデートで変わった既定値の通知", "업데이트로 바뀐 기본값 알림": "アップデートで変わった既定値の通知",
"없는 경로": "存在しないパス", "없는 경로": "存在しないパス",
"없는 경로: {0}": "存在しないパス: {0}", "없는 경로: {0}": "存在しないパス: {0}",

View File

@ -1210,7 +1210,9 @@
"업데이트": "更新", "업데이트": "更新",
"업데이트 · 버전 고르기": "更新 · 选择版本", "업데이트 · 버전 고르기": "更新 · 选择版本",
"업데이트 · 설치하고 남은 파일": "更新 · 安装残留", "업데이트 · 설치하고 남은 파일": "更新 · 安装残留",
"업데이트 설치 화면 열기 첫 시도 실패 (1초 뒤 다시): {0}": "更新:首次打开安装界面失败(1 秒后重试):{0}",
"업데이트 실패: {0}": "更新失败: {0}", "업데이트 실패: {0}": "更新失败: {0}",
"업데이트: 설치 허용 필요로 왔지만 허용돼 있어 다시 엽니다: {0}": "更新:返回需要安装权限,但已允许,重新打开:{0}",
"업데이트로 바뀐 기본값 알림": "更新所更改默认值的通知", "업데이트로 바뀐 기본값 알림": "更新所更改默认值的通知",
"없는 경로": "路径不存在", "없는 경로": "路径不存在",
"없는 경로: {0}": "路径不存在: {0}", "없는 경로: {0}": "路径不存在: {0}",

View File

@ -62,6 +62,7 @@ import 'ui/theme.dart';
import 'ui/work_panel.dart'; import 'ui/work_panel.dart';
import 'l10n/tr.dart'; import 'l10n/tr.dart';
import 'app/i18n_controller.dart'; import 'app/i18n_controller.dart';
import 'platform/android/android_updater.dart';
/// 제목 표시줄 글: "JJ_MKVMaker v1.2.3" /// 제목 표시줄 글: "JJ_MKVMaker v1.2.3"
String appTitle = 'JJ_MKVMaker'; String appTitle = 'JJ_MKVMaker';
@ -528,6 +529,9 @@ Future<void> runAndroid(String dataDir) async {
downloads.log = controller.note; downloads.log = controller.note;
// 진행 중인 일이 있으면 화면에서 내려가도 계속 (알림에 진행 상황) // 진행 중인 일이 있으면 화면에서 내려가도 계속 (알림에 진행 상황)
AndroidKeepAlive(controller, downloads); AndroidKeepAlive(controller, downloads);
// 170: 업데이트 설치의 첫 시도 실패 원문을 작업 기록에
final updater = services.updater;
if (updater is AndroidUpdater) updater.log = controller.note;
// 백그라운드로 실행: 화면 (Activity) 을 닫아도 엔진은 살아 있다가 다시 열면 새 화면에 붙는다 → 화면 방향을 다시 적용 // 백그라운드로 실행: 화면 (Activity) 을 닫아도 엔진은 살아 있다가 다시 열면 새 화면에 붙는다 → 화면 방향을 다시 적용
// (웹뷰는 텍스처로 그려 새 화면에 붙어도 그대로 보인다: browser_page _webSettings) // (웹뷰는 텍스처로 그려 새 화면에 붙어도 그대로 보인다: browser_page _webSettings)
// 116: 권한 ("모든 파일에 대한 접근") 이 없어 분석에 실패한 동영상은 허용하고 돌아오면 저절로 다시 분석 // 116: 권한 ("모든 파일에 대한 접근") 이 없어 분석에 실패한 동영상은 허용하고 돌아오면 저절로 다시 분석

View File

@ -21,6 +21,9 @@ class AndroidUpdater implements Updater {
final String apiBase; final String apiBase;
final StorageService storage; final StorageService storage;
/// 작업 기록 (app.log) 에 남길 곳 - 앱이 시작할 때 넣는다 (170: 화면에 안 보인 첫 시도의 오류 원문)
void Function(String msg)? log;
final HttpClient _http = HttpClient() final HttpClient _http = HttpClient()
..userAgent = 'JJ_MKVMaker-updater' ..userAgent = 'JJ_MKVMaker-updater'
..connectionTimeout = const Duration(seconds: 20); ..connectionTimeout = const Duration(seconds: 20);
@ -109,9 +112,20 @@ class AndroidUpdater implements Updater {
await _ch.invokeMethod<void>('installApk', {'path': downloaded}); await _ch.invokeMethod<void>('installApk', {'path': downloaded});
return; return;
} on PlatformException catch (e) { } on PlatformException catch (e) {
if (e.code != 'PERMISSION') throw UpdateException(e.message ?? '$e'); if (e.code != 'PERMISSION') {
// 170: 폴드에서 첫 시도만 다른 오류로 실패하고 두 번째에 된 일 (접은 화면 · 화면 전환 중으로 보임) - 1초 뒤 한 번 더
if (attempt == 0) {
log?.call(trf('업데이트 설치 화면 열기 첫 시도 실패 (1초 뒤 다시): {0}', [e.message ?? '$e']));
await Future<void>.delayed(const Duration(seconds: 1));
continue;
}
throw UpdateException(e.message ?? '$e');
}
// 170: 허용돼 있는데도 "설치 허용 필요" 창이 뜬 일 (폴드) - 한 번 더 물어 허용돼 있으면 창 없이 다시 연다 // 170: 허용돼 있는데도 "설치 허용 필요" 창이 뜬 일 (폴드) - 한 번 더 물어 허용돼 있으면 창 없이 다시 연다
if (attempt == 0 && await canInstallPackages()) continue; if (attempt == 0 && await canInstallPackages()) {
log?.call(trf('업데이트: 설치 허용 필요로 왔지만 허용돼 있어 다시 엽니다: {0}', [e.message ?? '$e']));
continue;
}
throw InstallPermissionNeeded(e.message ?? '$e'); throw InstallPermissionNeeded(e.message ?? '$e');
} }
} }