每个Android版本安装APK的正确方法是什么?

问题描述 投票:0回答:0

我正在制作一个 APK 安装应用程序,我经历了很多。特别是版本控制。 为此,我查阅了一些帖子和 StackOverFlow。但是所有的帖子现在让我更加困惑。那么,正确的方法是什么?

首先,请检查我下面关于为每个版本安装的代码。让我们谈谈什么是正确的方法。

KitKat(API 19)、Lollipop(API 21)、MashMellow(API 23)

fun installApkBelowNougat(apkFile: File) {
  val apkUri = Uri.fromFile(apkFile)
  val intent = Intent(Intent.ACTION_VIEW).apply {
    setDataAndType(apkUri, "application/vnd.android.package-archive")
    flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
  }
}

在这种情况下,所有解决方案都是相同的,我们必须使用

Uri.fromFile(file)
来获得
Uri
.

牛轧糖(API 24)

fun installApkInNougat(apkFile: File) {
  val apkUri = FileProvider.getUriForFile(applicationContext, applicationContext.packageName + ".fileProvider", apkFile)
  val intent = Intent(Intent.ACTION_VIEW).apply {
    setDataAndType(apkUri, "application/vnd.android.package-archive")
    flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
  }
}

在这种情况下,我们不能再使用

Uri.fromFile(file)
了。所以代替它,我们必须使用
FileProvider
因为牛轧糖。我们还必须像这样在 AndroidManifest.xml 中编写
<proivder/>

...
<provider
  android:name="androidx.core.content.FileProvider"
  android:authorities="${applicationId}.fileProvider"
  android:exported="false"
  android:grantUriPermissions="true">
     <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/filepath" />
     </provider>
...

有人说我们不需要用

setDataAndType()
。相反,他们只是在 Android7(牛轧糖)中使用
setData()
。 哪一个是正确的方法?两个都好吗?我们需要设置一个标志
Intent.FLAG_GRANT_READ_URI_PERMISSION

编辑: 您可以在使用
setDataAndType()
或两者之一here 时找到。

奥利奥(API 26)、派(API 28)、Q(API 29)、R(API 30)

fun installApkMoreThanO(apkFile: File) {
  f (!this.packageManager.canRequestPackageInstalls()) {
            val unknownIntent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).setData(
                Uri.parse(String.format("package:%s", this.packageName))
            )
            resultLauncher.launch(unknownIntent)
        } else {
            val apkUri = FileProvider.getUriForFile(applicationContext, applicationContext.packageName + ".fileProvider", apkFile)
            val intent = Intent(Intent.ACTION_VIEW, apkUri).apply {
                putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
                setDataAndType(apkUri, "application/vnd.android.package-archive")
                flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
                addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            }
            startActivity(intent)
            finish()
        }
}

在这种情况下,从奥利奥,我们必须添加此权限

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
以安装APK文件。 如果不这样做,该应用程序将在没有任何迹象的情况下崩溃。我们必须使用
Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES
,因为自Android8(Oreo)以来授予权限的方式已经改变。在奥利奥之前,我们可以一次授予所有应用程序的权限。但自从奥利奥以来,我们必须单独授予每个应用程序的权限。

我们可以使用

registerActivitResult
作为许可的结果。意思是如果你至今没有允许过app的权限,你必须允许权限,允许后系统返回Activity.RESULT_OK,或者Activity.RESULT_CANCELED。然后你可以做你想做的事。

S(API 31)

fun installApkMoreThanR(apkFile: File) {
 val apkUri = FileProvider.getUriForFile(applicationContext, applicationContext.packageName + ".fileProvider", apkFile)
 val intent = Intent(Intent.ACTION_VIEW, apkUri).apply {
     putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false)
     setDataAndType(apkUri, "application/vnd.android.package-archive")
     flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
     addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
   }
}

在这种情况下,看起来我回到了有点旧的方式,但它确实有效而且很好。 和Android 8~10的方式一样。我不使用

Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
的原因是即使我们授予该应用程序的权限,我们也只能接收
RESULT_CANCELED
。它总是在 Android12 中返回
Activity.RESULT_CANCELED
。我不知道为什么。有人说我们必须使用
PackageInstaller
API,因为
ACTION_VIEW
ACTION_INSTALL_PACKAGE
在 Android 10 中已被弃用。但我测试了它,
ACTION_VIEW
没有被弃用。 但是哪种方式更好?我们必须使用
PackageInstaller
API 从 Android 10 开始?

android apk android-fileprovider android-package-managers
© www.soinside.com 2019 - 2024. All rights reserved.