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
parent
76f8ab18da
commit
06b6169ad8
|
|
@ -141,12 +141,17 @@ class MainActivity : FlutterActivity() {
|
||||||
"installApk" -> try {
|
"installApk" -> try {
|
||||||
installApk(call.argument<String>("path") ?: "")
|
installApk(call.argument<String>("path") ?: "")
|
||||||
result.success(null)
|
result.success(null)
|
||||||
} catch (e: IllegalStateException) {
|
} catch (e: InstallPermissionNeededException) {
|
||||||
// 설치 허용 설정 화면을 열었다: 앱이 받은 파일로 다시 설치하게 따로 알린다
|
// 설치 허용 설정 화면을 열었다: 앱이 받은 파일로 다시 설치하게 따로 알린다
|
||||||
result.error("PERMISSION", e.message ?: e.toString(), null)
|
result.error("PERMISSION", e.message ?: e.toString(), null)
|
||||||
} catch (e: Exception) {
|
} 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") ?: ""))
|
"openFolder" -> result.success(openFolder(call.argument<String>("path") ?: ""))
|
||||||
// 예전 버전으로 되돌리기: Android 는 낮은 버전을 위에 설치하지 못해 앱을 지우는 확인 창을 연다
|
// 예전 버전으로 되돌리기: Android 는 낮은 버전을 위에 설치하지 못해 앱을 지우는 확인 창을 연다
|
||||||
"uninstallSelf" -> {
|
"uninstallSelf" -> {
|
||||||
|
|
@ -205,7 +210,7 @@ class MainActivity : FlutterActivity() {
|
||||||
Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:$packageName"))
|
Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:$packageName"))
|
||||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
)
|
)
|
||||||
throw IllegalStateException("\"이 출처의 앱 설치 허용\" 을 켠 뒤 다시 [업데이트] 를 누르세요")
|
throw InstallPermissionNeededException("\"이 출처의 앱 설치 허용\" 을 켠 뒤 다시 [업데이트] 를 누르세요")
|
||||||
}
|
}
|
||||||
// FileProvider 가 내보내는 폴더 (cache/updates) 로 옮긴다
|
// FileProvider 가 내보내는 폴더 (cache/updates) 로 옮긴다
|
||||||
val dir = File(cacheDir, "updates").apply { mkdirs() }
|
val dir = File(cacheDir, "updates").apply { mkdirs() }
|
||||||
|
|
@ -225,6 +230,9 @@ class MainActivity : FlutterActivity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 170: 설치 허용이 꺼져 있어 설정 화면을 연 경우만 (다른 오류와 구별)
|
||||||
|
class InstallPermissionNeededException(message: String) : Exception(message)
|
||||||
|
|
||||||
/// 앱이 켜져 있을 때 다른 앱에서 동영상을 열면 (launchMode singleTop)
|
/// 앱이 켜져 있을 때 다른 앱에서 동영상을 열면 (launchMode singleTop)
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
|
|
|
||||||
|
|
@ -104,11 +104,25 @@ class AndroidUpdater implements Updater {
|
||||||
/// Android 설치 화면 열기 ([downloaded] 는 APK 파일 경로)
|
/// Android 설치 화면 열기 ([downloaded] 는 APK 파일 경로)
|
||||||
@override
|
@override
|
||||||
Future<void> scheduleInstall(String downloaded) async {
|
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 {
|
try {
|
||||||
await _ch.invokeMethod<void>('installApk', {'path': downloaded});
|
return await _ch.invokeMethod<bool>('canInstallPackages') ?? false;
|
||||||
} on PlatformException catch (e) {
|
} catch (_) {
|
||||||
if (e.code == 'PERMISSION') throw InstallPermissionNeeded(e.message ?? '$e');
|
return false;
|
||||||
throw UpdateException(e.message ?? '$e');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue