title: What is the right way to install APK for each Android version?
body: <p>I'm making an APK Install app and I've been through a lot. Especially, versioning.
  to do that, i looked up some posting and StackOverFlow. but All the postings make me more confused now. So, What is the right way?</p>
  <p>first of all, please check my code below about installing for each version. and Let's talk about what's the right way.</p>
  <p><strong>KitKat(API 19), Lollipop(API 21), MashMellow(API 23)</strong></p>
  <pre><code>fun installApkBelowNougat(apkFile: File) {
    val apkUri = Uri.fromFile(apkFile)
    val intent = Intent(Intent.ACTION_VIEW).apply {
      setDataAndType(apkUri, &quot;application/vnd.android.package-archive&quot;)
      flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
    }
  }
  </code></pre>
  <p>in this case, all solutions are same and we have to use <code>Uri.fromFile(file)</code> to get a <code>Uri</code>.</p>
  <p><strong>Nougat(API 24)</strong></p>
  <pre><code>fun installApkInNougat(apkFile: File) {
    val apkUri = FileProvider.getUriForFile(applicationContext, applicationContext.packageName + &quot;.fileProvider&quot;, apkFile)
    val intent = Intent(Intent.ACTION_VIEW).apply {
      setDataAndType(apkUri, &quot;application/vnd.android.package-archive&quot;)
      flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
      addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
    }
  }
  </code></pre>
  <p>in this case, we can't use <code>Uri.fromFile(file)</code> anymore. So instead of it, We have to use <code>FileProvider</code> since Nougat. and We also have to write <code>&lt;proivder/&gt;</code> in AndroidManifest.xml like this.</p>
  <pre><code>...
  &lt;provider
    android:name=&quot;androidx.core.content.FileProvider&quot;
    android:authorities=&quot;${applicationId}.fileProvider&quot;
    android:exported=&quot;false&quot;
    android:grantUriPermissions=&quot;true&quot;&gt;
       &lt;meta-data
          android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
          android:resource=&quot;@xml/filepath&quot; /&gt;
       &lt;/provider&gt;
  ...
  </code></pre>
  <p>Someone say we don't need to use <code>setDataAndType()</code>. instead of it they just use <code>setData()</code> in Android7(Nougat).
  which one is right way? are both of those fine? and we need to set a Flag <code>Intent.FLAG_GRANT_READ_URI_PERMISSION</code>.</p>
  <p><strong>Oreo(API 26), Pie(API 28), Q(API 29), R(API 30)</strong></p>
  <pre><code>fun installApkMoreThanO(apkFile: File) {
    f (!this.packageManager.canRequestPackageInstalls()) {
              val unknownIntent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).setData(
                  Uri.parse(String.format(&quot;package:%s&quot;, this.packageName))
              )
              resultLauncher.launch(unknownIntent)
          } else {
              val apkUri = FileProvider.getUriForFile(applicationContext, applicationContext.packageName + &quot;.fileProvider&quot;, apkFile)
              val intent = Intent(Intent.ACTION_VIEW, apkUri).apply {
                  putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
                  setDataAndType(apkUri, &quot;application/vnd.android.package-archive&quot;)
                  flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
                  addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
              }
              startActivity(intent)
              finish()
          }
  }
  </code></pre>
  <p>in this case, from Oreo, We have to add this permission <code>&lt;uses-permission android:name=&quot;android.permission.REQUEST_INSTALL_PACKAGES&quot; /&gt;</code> to install APK file.
  if don't, the app will just crash without any sign. and we have to use <code>Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES</code> because The way in which permission is granted has changed since Android8(Oreo). before Oreo we can grant permission for all apps at once. but since Oreo, we have to grant permission for each apps individually.</p>
  <p>and we can use <code>registerActivitResult</code> for the result of permission. it means If you have never allowed permission of the app so far, you must allow permission, and after you allow it, the system returns Activity.RESULT_OK, or Activity.RESULT_CANCELED. and then you can do what you want.</p>
  <p><strong>S(API 31)</strong></p>
  <pre><code>fun installApkMoreThanR(apkFile: File) {
   val apkUri = FileProvider.getUriForFile(applicationContext, applicationContext.packageName + &quot;.fileProvider&quot;, apkFile)
   val intent = Intent(Intent.ACTION_VIEW, apkUri).apply {
       putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false)
       setDataAndType(apkUri, &quot;application/vnd.android.package-archive&quot;)
       flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
       addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
     }
  }
  </code></pre>
  <p>in this case, it looks that i go back to a little bit old way but it really works and it's fine.
  and it makes the same result as the Android 8 ~ 10's way. the reason why i don't use <code>Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)</code> is that we can only receive <code>RESULT_CANCELED</code> even if we grant a permission of the app. it always return <code>Activity.RESULT_CANCELED</code> in Android12. i don't know why. and some people say we have to use <code>PackageInstaller</code> API because <code>ACTION_VIEW</code> and <code>ACTION_INSTALL_PACKAGE</code> are deprecated in Android 10. but i tested it and <code>ACTION_VIEW</code> is not deprecated.
  But which way is better?? we have to use <code>PackageInstaller</code> API since Android 10?</p>