fix : apk internal updater
This commit is contained in:
@@ -19,10 +19,12 @@ import androidx.core.net.toUri
|
|||||||
|
|
||||||
class ApkInstaller(private val context: Context) {
|
class ApkInstaller(private val context: Context) {
|
||||||
|
|
||||||
|
var pendingApkFile: File? = null
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val INSTALL_REQUEST_CODE = 1001
|
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 {
|
when {
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
||||||
// Android 8+ (API 26+) - Use PackageInstaller API
|
// Android 8+ (API 26+) - Use PackageInstaller API
|
||||||
installWithPackageInstaller(apkFile)
|
installWithFileProvider(apkFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> {
|
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 {
|
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) {
|
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)
|
activeSession.commit(pendingIntent.intentSender)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Error installing with PackageInstaller", e)
|
|
||||||
// Fallback to intent method
|
// Fallback to intent method
|
||||||
installWithFileProvider(apkFile)
|
installWithFileProvider(apkFile)
|
||||||
}
|
}
|
||||||
@@ -123,7 +124,7 @@ class ApkInstaller(private val context: Context) {
|
|||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Error installing with FileProvider", e)
|
|
||||||
// Final fallback for Android 7+
|
// Final fallback for Android 7+
|
||||||
installWithFileUri(apkFile)
|
installWithFileUri(apkFile)
|
||||||
}
|
}
|
||||||
@@ -145,7 +146,7 @@ class ApkInstaller(private val context: Context) {
|
|||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} 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
|
* Request permission to install packages
|
||||||
*/
|
*/
|
||||||
fun requestInstallPermission() {
|
fun requestInstallPermission(activity: Activity) {
|
||||||
when {
|
when {
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
|
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 {
|
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply {
|
||||||
data = "package:${context.packageName}".toUri()
|
data = "package:${activity.packageName}".toUri()
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
}
|
}
|
||||||
context.startActivity(intent)
|
activity.startActivityForResult(intent, INSTALL_PERMISSION_REQUEST_CODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 -> {
|
||||||
val intent = Intent(Settings.ACTION_SECURITY_SETTINGS).apply {
|
val intent = Intent(Settings.ACTION_SECURITY_SETTINGS)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
activity.startActivityForResult(intent, INSTALL_PERMISSION_REQUEST_CODE)
|
||||||
}
|
|
||||||
context.startActivity(intent)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class MainActivity : FlutterActivity() {
|
|||||||
|
|
||||||
private val CHANNEL = "apk_installer"
|
private val CHANNEL = "apk_installer"
|
||||||
private val INSTALL_PACKAGES_REQUEST_CODE = 1001
|
private val INSTALL_PACKAGES_REQUEST_CODE = 1001
|
||||||
val installer = ApkInstaller(this)
|
private val installer = ApkInstaller(this)
|
||||||
private val TAG = "cj"
|
private val TAG = "cj"
|
||||||
|
|
||||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||||
@@ -28,17 +28,16 @@ class MainActivity : FlutterActivity() {
|
|||||||
CHANNEL
|
CHANNEL
|
||||||
).setMethodCallHandler { call, result ->
|
).setMethodCallHandler { call, result ->
|
||||||
if (call.method == "apk_installer") {
|
if (call.method == "apk_installer") {
|
||||||
val apkPath = call.argument<String>("appPath") ?: ""
|
val internalFile = File(context.filesDir.parentFile, "app_flutter/app-release.apk")
|
||||||
Log.i(TAG, "configureFlutterEngine: $apkPath")
|
val externalFile = File(context.getExternalFilesDir(null), "app-release.apk")
|
||||||
val apkFile = File(getExternalFilesDir(null), apkPath)
|
|
||||||
Log.i(TAG, "apkFile: $apkFile")
|
internalFile.copyTo(externalFile, overwrite = true)
|
||||||
Log.i(TAG, "externalStorageDirectory: ${getExternalFilesDir(null)}")
|
|
||||||
/*
|
|
||||||
if (!installer.canInstallPackages()) {
|
if (!installer.canInstallPackages()) {
|
||||||
installer.requestInstallPermission()
|
installer.pendingApkFile = externalFile
|
||||||
|
installer.requestInstallPermission(activity)
|
||||||
} else {
|
} else {
|
||||||
installer.installApk(apkFile)
|
installer.installApk(externalFile)
|
||||||
}*/
|
}
|
||||||
result.success(null)
|
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) {
|
if (requestCode == ApkInstaller.INSTALL_PERMISSION_REQUEST_CODE) {
|
||||||
val file = File(path)
|
if (installer.canInstallPackages() && installer.pendingApkFile != null) {
|
||||||
if (!file.exists()) {
|
installer.installApk(installer.pendingApkFile!!)
|
||||||
Log.e("jojo", "APK file does not exist: $path")
|
installer.pendingApkFile = null
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,5 +2,7 @@
|
|||||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<files-path name="app_flutter" path="app_flutter/*" />
|
<files-path name="app_flutter" path="app_flutter/*" />
|
||||||
|
<external-files-path
|
||||||
|
name="external_files"
|
||||||
|
path="." />
|
||||||
</paths>
|
</paths>
|
||||||
|
|||||||
Reference in New Issue
Block a user