[英]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.