From 1cfc6e2dbd7d234cc2be3ce1b5e9e480b758b54c Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Sun, 20 Jul 2025 09:40:41 +0330 Subject: [PATCH] fix : apk internal updater --- .../kotlin/ir/mnpc/rasadyar/ApkInstaller.kt | 46 ++++-------- .../kotlin/ir/mnpc/rasadyar/MainActivity.kt | 71 ++++--------------- android/app/src/main/res/xml/file_paths.xml | 4 +- 3 files changed, 31 insertions(+), 90 deletions(-) diff --git a/android/app/src/main/kotlin/ir/mnpc/rasadyar/ApkInstaller.kt b/android/app/src/main/kotlin/ir/mnpc/rasadyar/ApkInstaller.kt index 3fb5dbe..aa64136 100644 --- a/android/app/src/main/kotlin/ir/mnpc/rasadyar/ApkInstaller.kt +++ b/android/app/src/main/kotlin/ir/mnpc/rasadyar/ApkInstaller.kt @@ -19,10 +19,12 @@ import androidx.core.net.toUri class ApkInstaller(private val context: Context) { + var pendingApkFile: File? = null companion object { const val INSTALL_REQUEST_CODE = 1001 - private const val TAG = "ApkInstaller" + const val INSTALL_PERMISSION_REQUEST_CODE =2001 + } /** @@ -32,7 +34,7 @@ class ApkInstaller(private val context: Context) { when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> { // Android 8+ (API 26+) - Use PackageInstaller API - installWithPackageInstaller(apkFile) + installWithFileProvider(apkFile) } Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> { @@ -74,7 +76,7 @@ class ApkInstaller(private val context: Context) { } val intent = Intent(context, InstallResultReceiver::class.java).apply { - action = "com.yourpackage.INSTALL_RESULT" + action = "${context.packageName}.INSTALL_RESULT" } val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { @@ -90,7 +92,6 @@ class ApkInstaller(private val context: Context) { activeSession.commit(pendingIntent.intentSender) } } catch (e: Exception) { - Log.e(TAG, "Error installing with PackageInstaller", e) // Fallback to intent method installWithFileProvider(apkFile) } @@ -123,7 +124,7 @@ class ApkInstaller(private val context: Context) { context.startActivity(intent) } } catch (e: Exception) { - Log.e(TAG, "Error installing with FileProvider", e) + // Final fallback for Android 7+ installWithFileUri(apkFile) } @@ -145,7 +146,7 @@ class ApkInstaller(private val context: Context) { context.startActivity(intent) } } catch (e: Exception) { - Log.e(TAG, "Error installing with file URI", e) + } } @@ -194,46 +195,25 @@ class ApkInstaller(private val context: Context) { /** * Request permission to install packages */ - fun requestInstallPermission() { + fun requestInstallPermission(activity: Activity) { when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> { - if (!context.packageManager.canRequestPackageInstalls()) { + if (!activity.packageManager.canRequestPackageInstalls()) { val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply { - data = "package:${context.packageName}".toUri() - flags = Intent.FLAG_ACTIVITY_NEW_TASK + data = "package:${activity.packageName}".toUri() } - context.startActivity(intent) + activity.startActivityForResult(intent, INSTALL_PERMISSION_REQUEST_CODE) } } Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> { - val intent = Intent(Settings.ACTION_SECURITY_SETTINGS).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK - } - context.startActivity(intent) + val intent = Intent(Settings.ACTION_SECURITY_SETTINGS) + activity.startActivityForResult(intent, INSTALL_PERMISSION_REQUEST_CODE) } } } - /** - * Check if APK file is valid - */ - fun isValidApkFile(apkFile: File): Boolean { - if (!apkFile.exists() || !apkFile.canRead()) { - return false - } - return try { - val packageInfo = context.packageManager.getPackageArchiveInfo( - apkFile.absolutePath, - PackageManager.GET_ACTIVITIES - ) - packageInfo != null - } catch (e: Exception) { - Log.e(TAG, "Error validating APK file", e) - false - } - } } diff --git a/android/app/src/main/kotlin/ir/mnpc/rasadyar/MainActivity.kt b/android/app/src/main/kotlin/ir/mnpc/rasadyar/MainActivity.kt index 33565df..077f851 100644 --- a/android/app/src/main/kotlin/ir/mnpc/rasadyar/MainActivity.kt +++ b/android/app/src/main/kotlin/ir/mnpc/rasadyar/MainActivity.kt @@ -17,7 +17,7 @@ class MainActivity : FlutterActivity() { private val CHANNEL = "apk_installer" private val INSTALL_PACKAGES_REQUEST_CODE = 1001 - val installer = ApkInstaller(this) + private val installer = ApkInstaller(this) private val TAG = "cj" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { @@ -28,17 +28,16 @@ class MainActivity : FlutterActivity() { CHANNEL ).setMethodCallHandler { call, result -> if (call.method == "apk_installer") { - val apkPath = call.argument("appPath") ?: "" - Log.i(TAG, "configureFlutterEngine: $apkPath") - val apkFile = File(getExternalFilesDir(null), apkPath) - Log.i(TAG, "apkFile: $apkFile") - Log.i(TAG, "externalStorageDirectory: ${getExternalFilesDir(null)}") - /* + val internalFile = File(context.filesDir.parentFile, "app_flutter/app-release.apk") + val externalFile = File(context.getExternalFilesDir(null), "app-release.apk") + + internalFile.copyTo(externalFile, overwrite = true) if (!installer.canInstallPackages()) { - installer.requestInstallPermission() + installer.pendingApkFile = externalFile + installer.requestInstallPermission(activity) } else { - installer.installApk(apkFile) - }*/ + installer.installApk(externalFile) + } result.success(null) } } @@ -46,54 +45,14 @@ class MainActivity : FlutterActivity() { } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) - private fun installApk(path: String) { - val file = File(path) - if (!file.exists()) { - Log.e("jojo", "APK file does not exist: $path") - return - } - - // Check if we can install unknown apps (Android 8.0+) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - if (!packageManager.canRequestPackageInstalls()) { - requestInstallPermission() - return + if (requestCode == ApkInstaller.INSTALL_PERMISSION_REQUEST_CODE) { + if (installer.canInstallPackages() && installer.pendingApkFile != null) { + installer.installApk(installer.pendingApkFile!!) + installer.pendingApkFile = null } } - - val intent = Intent(Intent.ACTION_VIEW).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK - } - - try { - val apkUri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - FileProvider.getUriForFile( - context, - "${context.packageName}.fileprovider", - file - ).also { - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - } - } else { - Uri.fromFile(file) - } - - intent.setDataAndType(apkUri, "application/vnd.android.package-archive") - context.startActivity(intent) - - } catch (e: Exception) { - Log.e("jojo", "installApk error: ${e.message}", e) - } } - - @RequiresApi(Build.VERSION_CODES.O) - private fun requestInstallPermission() { - val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply { - data = "package:$packageName".toUri() - } - startActivityForResult(intent, INSTALL_PACKAGES_REQUEST_CODE) - } - - } diff --git a/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml index fa0400e..ad6701e 100644 --- a/android/app/src/main/res/xml/file_paths.xml +++ b/android/app/src/main/res/xml/file_paths.xml @@ -2,5 +2,7 @@ - +