如何用C#与Xamarin在Android手机上程序化安装APK?
嗨,我来帮你搞定这个问题!Xamarin C#完全可以实现程序化安装APK,你之前遇到的问题主要是没适配安卓高版本的文件访问规则,还有Java和C# API的命名差异,咱们一步步来解决:
第一步:配置FileProvider(适配安卓7.0+)
安卓7.0开始禁止直接使用file://格式的Uri访问共享文件,必须用FileProvider生成安全的Content Uri,所以首先要完成配置:
- 在
AndroidManifest.xml的<application>节点下添加Provider配置:
<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/file_paths" /> </provider>
- 在项目的
Resources/xml目录下创建file_paths.xml文件(如果xml目录不存在就新建一个),内容如下:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 允许访问外部存储根目录,可根据你的APK实际存储路径调整 --> <external-path name="external_files" path="." /> </paths>
第二步:编写C#的安装核心代码
接下来是安装逻辑,需要区分安卓版本处理Uri,同时做好权限检查:
using Android.Content; using Android.Net; using Android.OS; using AndroidX.Core.Content; using Java.IO; using System.IO; // 替换成你的APK实际完整路径,比如下载到Download目录的app.apk string apkFilePath = Path.Combine( Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "download", "app.apk" ); File apkFile = new File(apkFilePath); if (!apkFile.Exists()) { // 这里可以添加文件不存在的提示逻辑,比如Toast提醒用户 return; } Intent installIntent = new Intent(Intent.ActionView); if (Build.VERSION.SdkInt >= BuildVersionCodes.N) { // 安卓7.0及以上,用FileProvider生成安全Uri Uri apkUri = FileProvider.GetUriForFile( this, PackageName + ".fileprovider", // 和Manifest里的authorities完全对应 apkFile ); installIntent.SetDataAndType(apkUri, "application/vnd.android.package-archive"); // 给系统安装器授予临时读取权限 installIntent.AddFlags(ActivityFlags.GrantReadUriPermission); } else { // 安卓7.0以下,直接使用Uri.FromFile(注意C#是驼峰命名,不是Java的fromFile) Uri apkUri = Uri.FromFile(apkFile); installIntent.SetDataAndType(apkUri, "application/vnd.android.package-archive"); } // 启动安装界面必须的Flag installIntent.AddFlags(ActivityFlags.NewTask); // 安卓8.0+需要检查"安装未知应用"权限 if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { if (!PackageManager.CanRequestPackageInstalls()) { // 无权限时跳转到设置页面让用户开启 Intent settingIntent = new Intent(Android.Provider.Settings.ActionManageUnknownAppSources, Uri.Parse($"package:{PackageName}")); StartActivityForResult(settingIntent, 1001); return; } } StartActivity(installIntent);
第三步:配置必要权限
在AndroidManifest.xml里添加以下权限声明:
<!-- 安卓8.0+需要的安装未知应用权限 --> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <!-- 读取外部存储权限(如果APK存储在外部存储) --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
另外,读取外部存储权限需要动态申请,在访问APK文件前要确保已经获得权限,否则会出现文件找不到的错误。
关键说明
你之前遇到的Uri.fromFile问题,在C#里对应的是Uri.FromFile(注意大小写,C#采用驼峰命名),但这个方法在安卓7.0以上会触发FileUriExposedException,所以必须用FileProvider替代——这也是很多人误以为C#实现不了的原因,其实只是没做好高版本适配而已。
最后记得在不同安卓版本的设备上测试,确保全版本兼容哦!
内容的提问来源于stack exchange,提问作者Ray Yago
相关产品推荐
相关产品推荐

