当前位置: 首页 > 知识库问答 >
问题:

如何在Android 10中以编程方式安装任何Android应用程序

周作人
2023-03-14

在Android 9中

java prettyprint-override">Intent intent = new Intent("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.parse("content://"+Environment.getExternalStorageDirectory() + "/download/" + "app-release.apk"), "application/vnd.android.package-archive");
startActivity(intent);

我还在清单文件中添加了必需的权限。

当我运行这个程序时,它告诉我解析包错误时出现了问题。

共有2个答案

慎俊雄
2023-03-14

首先,你的Uri在Android的每个版本上都是无效的,除了一些设备制造商为你侵入的设备之外。

其次,默认情况下,您和软件包安装程序进程都无法访问Android 10上的外部存储。

第三,在Android 10上,不推荐通过ACTION\u VIEWACTION\u INSTALL\u PACKAGE安装应用程序。

Android 10及更高版本的解决方案(同样适用于Android 5.0及更高版本)是使用PackageInstaller

这个示例应用程序演示了如何使用它。关键部分在Main Motor中:

/*
  Copyright (c) 2019 CommonsWare, LLC

  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  use this file except in compliance with the License. You may obtain   a copy
  of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
  by applicable law or agreed to in writing, software distributed under the
  License is distributed on an "AS IS" BASIS,   WITHOUT WARRANTIES OR CONDITIONS
  OF ANY KIND, either express or implied. See the License for the specific
  language governing permissions and limitations under the License.

  Covered in detail in the book _Elements of Android Q

  https://commonsware.com/AndroidQ
*/

package com.commonsware.q.appinstaller

import android.app.Application
import android.app.PendingIntent
import android.content.Intent
import android.content.pm.PackageInstaller
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

private const val NAME = "mostly-unused"
private const val PI_INSTALL = 3439

class MainMotor(app: Application) : AndroidViewModel(app) {
  private val installer = app.packageManager.packageInstaller
  private val resolver = app.contentResolver

  fun install(apkUri: Uri) {
    viewModelScope.launch(Dispatchers.Main) {
      installCoroutine(apkUri)
    }
  }

  private suspend fun installCoroutine(apkUri: Uri) =
    withContext(Dispatchers.IO) {
      resolver.openInputStream(apkUri)?.use { apkStream ->
        val length =
          DocumentFile.fromSingleUri(getApplication(), apkUri)?.length() ?: -1
        val params =
          PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
        val sessionId = installer.createSession(params)
        val session = installer.openSession(sessionId)

        session.openWrite(NAME, 0, length).use { sessionStream ->
          apkStream.copyTo(sessionStream)
          session.fsync(sessionStream)
        }

        val intent = Intent(getApplication(), InstallReceiver::class.java)
        val pi = PendingIntent.getBroadcast(
          getApplication(),
          PI_INSTALL,
          intent,
          PendingIntent.FLAG_UPDATE_CURRENT
        )

        session.commit(pi.intentSender)
        session.close()
      }
    }
}

这里,install()ACTION\u OPEN\u文档中获得了一个Uri。在协同程序中,我创建了一个PackageInstaller会话,打开会话,将APK内容复制到会话提供的流中,然后提交并关闭会话。

端木涵润
2023-03-14

如果你想在Android 10中以编程方式安装应用程序,你需要给你的应用程序安装权限

步骤1:在清单中授予权限

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

步骤2:在Android清单中写入提供程序

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

第4步:在XML文件夹中创建名为provider_path的文件。xml和write

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="files_root"
        path="Android/data/${applicationId}" />
    <external-path
        name="external_files"
        path="." />
</paths>
 类似资料:
  • 我们以编程方式安装了应用程序。 如果应用程序已安装在设备中,则应用程序将自动打开。 指引我。我完全不知道。谢谢。

  • 问题内容: 我想使用来测试崩溃报告,但第一步是我需要使用代码在Android中模拟致命崩溃。 任何想法? 问题答案: 更新:也可以尝试这种创建方法, 并将其称为某处/ buttonClick 或直接抛出未捕获的异常 答对了!

  • 如果我们使用此代码,我们会看到一条消息:搜索GPS。然而,仅示出了GPS符号;GPS实际上不起作用: 为什么没用?以及如何使其正确工作?

  • 我在尝试以编程方式安装apk并在安装后重新启动Android emulator时遇到了一些问题。我指的是这条线。 这是我的代码: 有没有办法安装apk而不启动意图?因为我正在AsyncTask的中执行上述方法。然后在中,我需要显示一个片段,说明安装成功。 然而,对于上面的代码,在调用时,它只是关闭了我的所有片段。

  • 问题内容: 我在另一个构建工具的情况下使用Maven(leiningen为Clojure的,但是这不应该事),我想知道我会怎么称呼像一个插件的依赖:集结类路径编程(即通过Maven- API,而不是通过-command)。 问题答案: 请参阅如何从maven-plugin-testing- harness实现org.apache.maven.plugin.testing.AbstractMojoT