如何在 Android 10 中以编程方式安装任何 Android 应用
Posted
技术标签:
【中文标题】如何在 Android 10 中以编程方式安装任何 Android 应用【英文标题】:How to install any Android app programmatically in Android 10 【发布时间】:2021-12-01 13:57:01 【问题描述】:在 Android 9 和 10 中 我在使用文件路径 apk 文件以编程方式在 android Studio 中安装应用程序时遇到问题。 下面显示我尝试过的内容..
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);
我还在清单文件中添加了所需的权限。
当我运行它时,它给了我解析包时出现问题错误。
【问题讨论】:
请edit您的问题并发布整个堆栈跟踪。 我在 logcat 中没有收到任何异常或错误。 【参考方案1】:如果您想在 Android 10 中以编程方式安装应用程序,您需要授予为您的应用程序安装应用程序的权限
第 1 步:在 Manifest 中授予权限
<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 Manifest 中编写提供程序
<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:在名为 provider_paths.xml 的 XML 文件夹中创建文件并写入
<?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>
第 4 步:为 apk 安装和存储权限授予运行时权限
//installtion permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
if (!getPackageManager().canRequestPackageInstalls())
startActivityForResult(new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).setData(Uri.parse(String.format("package:%s", getPackageName()))), 1234);
else
//Storage Permission
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE, 1);
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
ActivityCompat.requestPermissions(this, new String[]Manifest.permission.WRITE_EXTERNAL_STORAGE, 1);
第五步:调用安装apk函数
void installAPK()
String PATH = Environment.getExternalStorageDirectory() + "/" + "apkname.apk";
File file = new File(PATH);
if(file.exists())
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uriFromFile(getApplicationContext(), new File(PATH)), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try
getApplicationContext().startActivity(intent);
catch (ActivityNotFoundException e)
e.printStackTrace();
Log.e("TAG", "Error in opening the file!");
else
Toast.makeText(getApplicationContext(),"installing",Toast.LENGTH_LONG).show();
Uri uriFromFile(Context context, File file)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".provider", file);
else
return Uri.fromFile(file);
【讨论】:
正是我需要这个 ACTION_VIEW 在 android 10 中已弃用【参考方案2】:首先,您的Uri
在每个 Android 版本上都无效,除了设备制造商为您入侵某些设备的少数设备。
其次,默认情况下,您和软件包安装程序进程都无法访问 Android 10 上的外部存储。
第三,通过ACTION_VIEW
或ACTION_INSTALL_PACKAGE
安装应用程序在Android 10 上已弃用。
适用于 Android 10 及更高版本(也适用于 Android 5.0 及更高版本)的解决方案是use PackageInstaller
。
This sample app 演示了如何使用它。关键部分在MainMotor
:
/*
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_OPEN_DOCUMENT
的Uri
。在协程内部,我创建了一个 PackageInstaller
会话,打开会话,将 APK 内容复制到会话提供的流中,然后提交并关闭会话。
【讨论】:
@Ak23:抱歉,我没有可用的PackageInstaller
示例 Java 代码。
安装完成后自动启动应用有什么想法吗?
@Ak23 有很多方法可以解决,具体取决于您的需要。您可以使用PackageManager
和getLaunchIntentForPackage()
,或者如果您已经知道参数,您只需定义一个新意图。我建议将其作为一个单独的问题查找。
@AbandonedCart 你能解释一下 getLaunchIntentForPackage() 我和@Ak23 有同样的问题吗?
@shakil.k 在 Google 上快速搜索 getLaunchIntentForPackage
会找到 Android documentation。这将需要您进行一些投资。以上是关于如何在 Android 10 中以编程方式安装任何 Android 应用的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android Studio 中以编程方式上传和下载 Google Drive 上的任何文件
如何在android中以编程方式设置ImageView的高度宽度?