Android 업데이트: 설치가 허용돼 있는데 "설치 허용 필요" 창이 뜨던 것 (170)

폴드 (Android 16 · 허용 allow) 에서 첫 설치 시도에 앱의 "설치 허용 필요" 창이 떴다 (Android 설정 화면은 열리지 않음 -
허용 문제가 아니라 다른 오류). Kotlin 이 installApk 안의 IllegalStateException 을 모두 "허용 필요" 로 보냈기 때문.
- Kotlin: 허용이 꺼져 설정 화면을 연 경우만 InstallPermissionNeededException → PERMISSION, 다른 오류는 "예외 이름: 원문" (INSTALL).
- 채널 canInstallPackages. Dart: PERMISSION 이 와도 허용돼 있으면 창 없이 다시 연다 (한 번).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
묶음4
RyuJongJin 2026-10-10 03:22:51 +09:00
parent 76f8ab18da
commit 06b6169ad8
2 changed files with 29 additions and 7 deletions

View File

@ -141,12 +141,17 @@ class MainActivity : FlutterActivity() {
"installApk" -> try {
installApk(call.argument<String>("path") ?: "")
result.success(null)
} catch (e: IllegalStateException) {
} catch (e: InstallPermissionNeededException) {
// 설치 허용 설정 화면을 열었다: 앱이 받은 파일로 다시 설치하게 따로 알린다
result.error("PERMISSION", e.message ?: e.toString(), null)
} catch (e: Exception) {
result.error("INSTALL", e.message ?: e.toString(), null)
// 170: 다른 오류를 "설치 허용 필요" 로 오해하지 않게 (예전에는 IllegalStateException 이면 모두 허용 필요로 보았다)
result.error("INSTALL", "${e.javaClass.simpleName}: ${e.message ?: ""}", null)
}
// 170: 지금 이 앱이 다른 앱 (APK) 을 설치할 수 있는지
"canInstallPackages" -> result.success(
Build.VERSION.SDK_INT < Build.VERSION_CODES.O || packageManager.canRequestPackageInstalls()
)
"openFolder" -> result.success(openFolder(call.argument<String>("path") ?: ""))
// 예전 버전으로 되돌리기: Android 는 낮은 버전을 위에 설치하지 못해 앱을 지우는 확인 창을 연다
"uninstallSelf" -> {
@ -205,7 +210,7 @@ class MainActivity : FlutterActivity() {
Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:$packageName"))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
)
throw IllegalStateException("\"이 출처의 앱 설치 허용\" 을 켠 뒤 다시 [업데이트] 를 누르세요")
throw InstallPermissionNeededException("\"이 출처의 앱 설치 허용\" 을 켠 뒤 다시 [업데이트] 를 누르세요")
}
// FileProvider 가 내보내는 폴더 (cache/updates) 로 옮긴다
val dir = File(cacheDir, "updates").apply { mkdirs() }
@ -225,6 +230,9 @@ class MainActivity : FlutterActivity() {
)
}
/// 170: 설치 허용이 꺼져 있어 설정 화면을 연 경우만 (다른 오류와 구별)
class InstallPermissionNeededException(message: String) : Exception(message)
/// 앱이 켜져 있을 때 다른 앱에서 동영상을 열면 (launchMode singleTop)
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)

View File

@ -104,11 +104,25 @@ class AndroidUpdater implements Updater {
/// Android 설치 화면 열기 ([downloaded] 는 APK 파일 경로)
@override
Future<void> scheduleInstall(String downloaded) async {
for (var attempt = 0;; attempt++) {
try {
await _ch.invokeMethod<void>('installApk', {'path': downloaded});
return;
} on PlatformException catch (e) {
if (e.code != 'PERMISSION') throw UpdateException(e.message ?? '$e');
// 170: 허용돼 있는데도 "설치 허용 필요" 창이 뜬 일 (폴드) - 한 번 더 물어 허용돼 있으면 창 없이 다시 연다
if (attempt == 0 && await canInstallPackages()) continue;
throw InstallPermissionNeeded(e.message ?? '$e');
}
}
}
/// 170: 이 앱이 APK 를 설치할 수 있는지 (Android 의 "이 출처의 앱 설치 허용"). 모르면 false
Future<bool> canInstallPackages() async {
try {
await _ch.invokeMethod<void>('installApk', {'path': downloaded});
} on PlatformException catch (e) {
if (e.code == 'PERMISSION') throw InstallPermissionNeeded(e.message ?? '$e');
throw UpdateException(e.message ?? '$e');
return await _ch.invokeMethod<bool>('canInstallPackages') ?? false;
} catch (_) {
return false;
}
}