在 Android 上以编程方式安装应用程序
可以通过编程方式安装从自定义 Android 应用程序动态下载的 apk。
Is possible to programmatically install a dynamically downloaded apk from a custom Android application.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
您可以轻松启动市场链接或安装提示:
来源
来源
但是,您未经用户明确许可,无法安装 .apks;除非设备和您的程序已获得 root 权限。
You can easily launch a market link or an install prompt:
source
source
However, you cannot install .apks without user's explicit permission; not unless the device and your program is rooted.
该问题提供的解决方案均适用于23及以下的
targetSdkVersion
。然而,对于 Android N(即 API 级别 24 及更高版本),它们不起作用并崩溃,并出现以下异常:这是因为从 Android 24 开始,用于寻址下载的
Uri
文件已更改。例如,存储在应用程序的主要外部文件系统上的名为appName.apk
的安装文件,其包名称为com.example.test
将是file:/ //storage/emulated/0/Android/data/com.example.test/files/appName.apk
适用于
API 23
及以下版本,而适用于
API 24< /code> 及以上。
有关此内容的更多详细信息,请参阅此处和我我不会经历它。
要回答
24
及以上的targetSdkVersion
问题,必须遵循以下步骤:将以下内容添加到 AndroidManifest.xml:
将以下
paths.xml
文件添加到 src、main 中res
上的xml
文件夹:pathName
是如上面的示例内容 uri 示例所示,pathValue
是系统上的实际路径。最好加上一个“.”。如果您不想添加任何额外的子目录,请使用上面的 pathValue (不带引号)。
编写以下代码以在主外部文件系统上安装名为
appName.apk
的 apk:在外部文件系统上写入您自己的应用程序的私有目录时,也不需要任何权限。
我在此处编写了一个自动更新库,其中我使用了上述内容。
The solutions provided to this question are all applicable to
targetSdkVersion
s of 23 and below. For Android N, i.e. API level 24, and above, however, they do not work and crash with the following Exception:This is due to the fact that starting from Android 24, the
Uri
for addressing the downloaded file has changed. For instance, an installation file namedappName.apk
stored on the primary external filesystem of the app with package namecom.example.test
would be asfile:///storage/emulated/0/Android/data/com.example.test/files/appName.apk
for
API 23
and below, whereas something likefor
API 24
and above.More details on this can be found here and I am not going to go through it.
To answer the question for
targetSdkVersion
of24
and above, one has to follow these steps:Add the following to the AndroidManifest.xml:
Add the following
paths.xml
file to thexml
folder onres
in src, main:The
pathName
is that shown in the exemplary content uri example above andpathValue
is the actual path on the system.It would be a good idea to put a "." (without quotes) for pathValue in the above if you do not want to add any extra subdirectory.
Write the following code to install the apk with the name
appName.apk
on the primary external filesystem:No permission is also necessary when writing to your own app's private directory on the external filesystem.
I have written an AutoUpdate library here in which I have used the above.
我遇到了同样的问题,经过多次尝试,它以这种方式解决了我的问题。我不知道为什么,但单独设置数据和类型破坏了我的意图。
I had the same problem and after several attempts, it worked out for me this way. I don't know why, but setting data and type separately screwed up my intent.
好吧,我深入挖掘,并从 Android Source 找到了 PackageInstaller 应用程序的来源。
https://github.com/android/platform_packages_apps_packageinstaller
从清单中我发现它需要权限
:确认后进行实际安装过程
Well, I dug deeper, and found sources of PackageInstaller application from Android Source.
https://github.com/android/platform_packages_apps_packageinstaller
From manifest I found that it require permission:
And the actual process of installation occurs after confirmation
这可以帮助其他人很多!
第一:
第二: 对于 android 7 及更高版本,您应该在清单中定义一个提供程序,如下所示!
第三:在res/xml文件夹中定义path.xml,如下所示!
我正在使用此路径作为内部存储,如果您想将其更改为其他内容,有几种方法!您可以访问此链接:
FileProvider
第四: 您应该在清单中添加此权限:
This can help others a lot!
First:
Second: For android 7 and above you should define a provider in manifest like below!
Third: Define path.xml in res/xml folder like below!
I'm using this path for internal storage if you want to change it to something else there is a few way! You can go to this link:
FileProvider
Forth: You should add this permission in manifest:
我只是想分享这样一个事实:我的 apk 文件已保存到我的应用程序“Data”目录中,并且我需要将 apk 文件的权限更改为全局可读,以便允许以这种方式安装它,否则系统抛出“解析错误:解析包时出现问题”;所以使用@Horaceman的解决方案使得:
I just want to share the fact that my apk file was saved to my app "Data" directory and that I needed to change the permissions on the apk file to be world readable in order to allow it to be installed that way, otherwise the system was throwing "Parse error: There is a Problem Parsing the Package"; so using solution from @Horaceman that makes:
在 Android Oreo 及以上版本中,我们必须采用不同的方法以编程方式安装 apk。
在Oreo及以上版本中我们需要未知资源安装权限。所以在活动结果中你必须检查结果的权限
In Android Oreo and above version we have to approach different methods to install apk programatically.
In Oreo and above version we need unknown resource installation permission. so in activity result u have to check the result for the permission
不要忘记请求权限:
在 AndroidManifest.xml 中添加提供程序和权限:
创建 XML 文件提供程序 res/xml/provider_paths.xml
使用以下示例代码:
Do not forget to request permissions:
Add in AndroidManifest.xml the provider and permission:
Create XML file provider res/xml/provider_paths.xml
Use below example code:
另一种解决方案不需要对接收应用程序进行硬编码,因此更安全:
Another solution that doesn't not require to hard-code the receiving app and that is therefore safer:
大约两个月前来到这里,据说已经弄清楚了。今天回来了,却一头雾水。据我所知,我的设置没有任何改变,所以显然过去我想出的任何东西对于现在的我来说都不够强大。我终于设法让某些东西再次工作,因此在这里将其记录下来,以供将来的我和其他可能从另一次尝试中受益的人使用。
此尝试代表原始 Android Java 安装 APK - 会话 API 示例。它可能需要一些额外的工作,但这至少是一个开始。我让它在 Android 9 设备上运行,尽管我有一个针对 Android 11 的项目。InstallApkSessionApi.cs
我
AndroidManifest.xml
特别喜欢这种方法的是,它不需要在清单中进行任何特殊工作 - 没有广播接收器、文件当然,这将应用程序资产中的某些 APK 作为其来源,而更有用的系统可能会使用某些给定的 APK 路径。我想这会带来一定程度的额外复杂性。此外,在 Android 处理完流之前,我从未遇到过 Xamarin GC 关闭流的任何问题(至少据我所知)。我也没有遇到任何未解析 APK 的问题。我确保使用签名的 APK(部署到设备时由 Visual Studio 生成的 APK 工作得很好),而且我再次没有遇到任何文件访问权限问题,仅仅是因为在此示例中使用了应用程序资产中的 APK 。
这里的其他一些答案提供的一件事是使侧面加载权限授予更加简化的想法。 Yabaze Cool 的回答提供了此功能:
当我测试翻译时,我卸载了启动器演示及其安装的应用程序。未提供对 canRequestPackageInstalls 的检查,导致我必须手动按其他“设置”按钮才能进入与上面的 ACTION_MANAGE_UNKNOWN_APP_SOURCES 意图相同的对话框。因此,添加此逻辑有助于在一定程度上简化用户的安装过程。
Came at this some two months ago and supposedly figured it out. Came back today and couldn't make heads or tails of it. Nothing had changed in my setup as far as I am aware, so apparently whatever past me had come up with wasn't robust enough for present me. I finally managed to get something working again, so documenting it here for future me and anyone else who might stand to benefit from yet another attempt.
This attempt represents a direct Xamarin C# translation of the original Android Java Install APK - Session API example. It could probably use some additional work, but it's at least a start. I have it running on an Android 9 device, though I have the project targetting Android 11.
InstallApkSessionApi.cs
AndroidManifest.xml
What I particularly like about this approach is that it does not require any special work in the manifest - no broadcast receivers, file providers, etc. Granted, this takes as its source some APK in the app's assets, whereas a more useful system will probably use some given APK path. I imagine that will introduce a certain level of additional complexity. In addition, I never ran into any issues here (at least as far as I could tell) with the Xamarin GC closing streams before Android was done with them. Nor did I have any issues with the APK not being parsed. I made sure to use a signed APK (the one generated by Visual Studio when deploying to the device worked just fine), and again I did not run into any file access permission issues simply due to using an APK from the app's assets in this example.
One thing that some of the other answers here provided was the idea of making the sideloading permission grant more streamlined. The answer by Yabaze Cool provided this feature:
When I tested my translation, I uninstalled both the launcher demo and the app it installed. Not providing the check to
canRequestPackageInstalls
made it to where I had to manually press an additional Settings button to take me to the same dialog as does theACTION_MANAGE_UNKNOWN_APP_SOURCES
intent above. So adding this logic can help to somewhat simplify the installation process for the user.值得注意的是,如果您使用
DownloadManager
开始下载,请务必将其保存到外部位置,例如setDestinationInExternalFilesDir(c, null, ")。 apk";
.包归档类型的意图似乎并不像用于下载到内部位置的content:
方案,但类似于file:
。 (尝试将内部路径包装到 File 对象中然后获取路径也不起作用,即使它会产生file:
url,因为应用程序不会解析 apk;看起来就像它必须是外部的一样。)示例:
It's worth noting that if you use the
DownloadManager
to kick off your download, be sure to save it to an external location e.g.setDestinationInExternalFilesDir(c, null, "<your name here>).apk";
. The intent with a package-archive type doesn't appear to like thecontent:
scheme used with downloads to an internal location, but does likefile:
. (Trying to wrap the internal path into a File object and then getting the path doesn't work either, even though it results in afile:
url, as the app won't parse the apk; looks like it must be external.)Example:
是的,这是可能的。但为此,您需要手机安装未经验证的来源。例如,slideMe 就是这样做的。我认为您能做的最好的事情就是检查应用程序是否存在并发送 Android Market 的意图。你应该使用 android Market 的 url 方案。
我不知道如何开始活动,但如果您使用这种网址开始活动。它应该会打开 Android 市场并让您选择安装应用程序。
Yes it's possible. But for that you need the phone to install unverified sources. For example, slideMe does that. I think the best thing you can do is to check if the application is present and send an intent for the Android Market. you should use something the url scheme for android Market.
I don't know exactly how to start the activity but if you start an activity with that kind of url. It should open the android market and give you the choice to install the apps.
只是一个扩展,如果有人需要一个库,那么 这 可能会有所帮助。感谢 Raghav
Just an extension, if anyone need a library then this might help. Thanks to Raghav
试试这个
try this
UpdateNode 为 Android 提供了一个 API,可以从另一个应用程序内部安装 APK 包。
您只需在线定义更新并将 API 集成到您的应用程序中 - 就是这样。
目前该 API 处于 Beta 状态,但您已经可以自己进行一些测试。
除此之外,UpdateNode 还提供通过系统显示消息的功能 - 如果您想告诉用户一些重要的信息,这非常有用。
我是客户端开发团队的一员,并且至少在我自己的 Android 应用程序中使用消息功能。
在此处查看如何集成 API 的说明
UpdateNode provides an API for Android to install APK packages from inside another App.
You can just define your Update online and integrate the API into your App - that's it.
Currently the API is in Beta state, but you can already do some tests yourself.
Beside that, UpdateNode offers also displaying messages though the system - pretty useful if you want to tell something important to your users.
I am part of the client dev team and am using at least the message functionality for my own Android App.
See here a description how to integrate the API
试试这个
- 在清单上写入:
编写代码:
Try this
- Write on Manifest:
Write the Code:
首先将以下行添加到 AndroidManifest.xml :
然后使用以下代码安装 apk:
First add the following line to AndroidManifest.xml :
Then use the following code to install apk:
基于答案@Uroš Podkrižnik。
对于不同版本的 android(API 级别 21-30),通过 APK 安装应用程序可能会有所不同:
创建并注册接收器:
拦截权限请求的结果 WRITE_EXTERNAL_STORAGE:
拦截安全设置中用户选择的结果:
添加到清单:
将provider_paths.xml文件添加到res/xml:
对于android API级别= 30,从安全设置返回不起作用,
所以使用通过浏览器安装:
Based on answer @Uroš Podkrižnik.
Installing the application through the APK may differ for various versions of android (API Levels 21-30):
Create and register receiver:
Intercept the result of the permission request WRITE_EXTERNAL_STORAGE:
Intercept the result of user selection in security settings:
Add to your manifest:
Add provider_paths.xml file to res/xml:
For android API level = 30, return from security settings does not work,
so used installation via browser: