简体   繁体   English

以编程方式安装 APK (Android 12)

[英]Installing an APK Programmatically (Android 12)

I'm attempting to install an APK programmatically on Android 12 but seem to be running into unknown issues at this point.我正在尝试以编程方式在 Android 12 上安装 APK,但此时似乎遇到了未知问题。 All advice I've found regarding installing an APK programmatically seem to be deprecated.我发现的所有关于以编程方式安装 APK 的建议似乎都已被弃用。

Currently, I'm able to save my file but whenever I attempt to install it using PackageManager.PackageInstaller, it fails silently and I'm unable to find anything in the logs suggesting what the failure might've been.目前,我可以保存我的文件,但每当我尝试使用 PackageManager.PackageInstaller 安装它时,它都会静默失败,并且我无法在日志中找到任何提示可能出现故障的内容。

Here's my package installer object.这是我的 package 安装程序 object。

object PackageInstaller {
    @SuppressLint("WrongConstant")
    @Throws(IOException::class)
    fun installPackage(
        context: Context,
        installSessionId: String?,
        packageName: String?,
        apkStream: InputStream?
    ) {
        val packageManger = context.packageManager
        val packageInstaller = packageManger.packageInstaller
        val params = android.content.pm.PackageInstaller.SessionParams(
            android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL
        )
        params.setAppPackageName(packageName)
        var session: android.content.pm.PackageInstaller.Session? = null
        try {
            val sessionId = packageInstaller.createSession(params)
            session = packageInstaller.openSession(sessionId)
            val out = session.openWrite(installSessionId!!, 0, -1)
            val buffer = ByteArray(1024)
            var length: Int
            var count = 0
            if (apkStream != null) {
                while (apkStream.read(buffer).also { length = it } != -1) {
                    out.write(buffer, 0, length)
                    count += length
                }
            }
            session.fsync(out)
            out.close()
            val intent = Intent
            intent.addFlags(Intent.ACTION_PACKAGE_ADDED)
            Log.v("installer", "Installing..?")
            session.commit(
                PendingIntent.getBroadcast(
                    context, sessionId,
                    intent, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
                    } else {
                        PendingIntent.FLAG_UPDATE_CURRENT
                    }

                ).intentSender
            )
        }finally {
            session?.close()
        }
    }
}

At this point I'm pretty lost as to where to look next.在这一点上,我很迷茫,不知道下一步该往哪里看。 Does anyone even know if this is still possible?有谁知道这是否仍然可行? Or a solution to this issue?或者这个问题的解决方案?

You can try with this it is working with android 12您可以尝试使用它与 android 12 一起使用

class DownloadApk(private var context: WeakReference<Context>) {

@JvmOverloads
fun startDownloadingApk(url: String, fileName: String = "App Update") {
    if (URLUtil.isValidUrl(url)) {
        DownloadNewVersion(context, url, fileName).execute()
    }
}

@Suppress("DEPRECATION")
private class DownloadNewVersion(
    private val context: WeakReference<Context>,
    val downloadUrl: String,
    val fileName: String
) : AsyncTask<String, Int, Boolean>() {

    private lateinit var bar: ProgressDialog

    override fun onPreExecute() {
        super.onPreExecute()
        bar = ProgressDialog(context.get()).apply {
            setCancelable(false)
            setMessage("Downloading...")
            isIndeterminate = true
            setCanceledOnTouchOutside(false)
            show()
        }
    }

    override fun onProgressUpdate(vararg values: Int?) {
        super.onProgressUpdate(*values)
        var msg = ""
        val progress = values[0]
        if (progress != null) {
            bar.progress = progress
            msg = if (progress > 99) "Finishing... " else "Downloading... $progress%"
        }

        bar.apply {
            isIndeterminate = false
            max = 100
            setMessage(msg)
        }
    }

    override fun onPostExecute(result: Boolean?) {
        super.onPostExecute(result)
        bar.dismiss()
        if (result != null && result) {
            context.get()?.let {
                Toast.makeText(it, "Update Done", Toast.LENGTH_SHORT).show()
            }

        } else {
            context.get()?.let {
                Toast.makeText(it, "Error: Try Again", Toast.LENGTH_SHORT).show()
            }

        }
    }

    override fun doInBackground(vararg p0: String?): Boolean {
        var flag = false

        try {
            val path =
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
                    .toString() + "/"
            var outputFile = File("$path$fileName.apk")
            var repetition = 1
            while (outputFile.exists()) {
                outputFile = File("$path$fileName ($repetition).apk")
                repetition++
            }

            val directory = File(path)
            if (!directory.exists()) {
                directory.mkdirs()
            }

            val url = URL(downloadUrl)
            val c = url.openConnection() as HttpURLConnection
            c.requestMethod = "GET"
            c.connect()

            val fos = FileOutputStream(outputFile)
            val inputStream = c.inputStream
            val totalSize = c.contentLength.toFloat() //size of apk

            val buffer = ByteArray(1024)
            var len1: Int
            var per: Float
            var downloaded = 0f
            while (inputStream.read(buffer).also { len1 = it } != -1) {
                fos.write(buffer, 0, len1)
                downloaded += len1
                per = (downloaded * 100 / totalSize)
                publishProgress(per.toInt())
            }
            fos.close()
            inputStream.close()
            openNewVersion(outputFile.path)
            flag = true
        } catch (e: MalformedURLException) {
            Log.e("DownloadApk", "Update Error: " + e.message)
            flag = false
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return flag
    }

    private fun openNewVersion(location: String) {
        val intent = Intent(Intent.ACTION_VIEW)
        intent.setDataAndType(
            getUriFromFile(location),
            "application/vnd.android.package-archive"
        )
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        context.get()?.startActivity(intent)
    }

    private fun getUriFromFile(filePath: String): Uri? {
        return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            Uri.fromFile(File(filePath))
        } else {
            context.get()?.let {
                FileProvider.getUriForFile(
                    it,
                    it.packageName + ".provider",
                    File(filePath)
                )    
            }
        }
    }
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM