Android C#无法打开Download文件夹中APK文件的问题排查
问题描述
- 已查阅所有相关问题及答案仍未解决,推测问题出在MediaProvider/Intent调用无法访问Download文件夹,设备日志显示MediaProvider报错,提示文件路径未找到及EACCES权限错误
- 已获取
READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE和REQUEST_INSTALL_PACKAGES权限 - 模拟器显示「解析软件包时出现问题」,无法打开/安装APK文件
- 尝试将APK复制到内部目录,但因权限问题无法通过adb复制到
Android/data/路径下
相关代码
Java.IO.File path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads); Java.IO.File file = new Java.IO.File(path, "test2.apk"); // Get URI and MIME type of file Android.Net.Uri uri = FileProvider.GetUriForFile(context, AppInfo.PackageName + ".fileprovider", file); String mime = context.ContentResolver.GetType(uri); // Open file with user selected app Intent intent = new Intent(); intent.SetAction(Intent.ActionView); intent.SetDataAndType(uri, mime); intent.AddFlags(ActivityFlags.NewTask); intent.AddFlags(ActivityFlags.GrantReadUriPermission); intent.AddFlags(ActivityFlags.GrantWriteUriPermission); intent.AddFlags(ActivityFlags.GrantPersistableUriPermission); //context.StartActivity(intent); Intent chooser = Intent.CreateChooser(intent, "Update"); chooser.SetFlags(ActivityFlags.NewTask); IList<Android.Content.PM.ResolveInfo> resInfoList = context.PackageManager.QueryIntentActivities(chooser, Android.Content.PM.PackageInfoFlags.MatchDefaultOnly); foreach (Android.Content.PM.ResolveInfo resolveInfo in resInfoList) { String packageName = resolveInfo.ActivityInfo.PackageName; context.GrantUriPermission(packageName, uri, ActivityFlags.GrantWriteUriPermission | ActivityFlags.GrantReadUriPermission); } context.StartActivity(chooser);
Manifest配置
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" /> <application android:label="DRIVER" android:theme="@style/MainTheme" android:requestLegacyExternalStorage="true"> <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"></meta-data> </provider> </application>
FileProvider路径配置
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external" path="." /> <external-files-path name="external_files" path="." /> <files-path name="files" path="." /> <external-files-path name="my_images" path="Pictures" /> <external-files-path name="my_movies" path="Movies" />|
设备错误日志
12-21 19:18:50.371 pixel_5_-_api_30 Warning 13637 InstallStaging java.io.FileNotFoundException: open failed: EACCES (Permission denied) at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:151) at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:781) at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1983) at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1798) at android.content.ContentResolver.openInputStream(ContentResolver.java:1475) at com.android.packageinstaller.InstallStaging$StagingAsyncTask.doInBackground(InstallStaging.java:174) at com.android.packageinstaller.InstallStaging$StagingAsyncTask.doInBackground(InstallStaging.java:167) at android.os.AsyncTask$3.call(AsyncTask.java:394) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:923) 12-21 19:18:50.371 pixel_5_-_api_30 Warning 13637 InstallStaging Error staging apk from content URI 12-21 19:18:50.370 pixel_5_-_api_30 Error 1332 MediaProvider Couldn't find file: /storage/emulated/0/Download/test2.apk
解决方案
1. 修复FileProvider路径配置错误
你的file_paths.xml最后一行存在多余的|符号,导致XML解析失败,FileProvider无法正确映射公共Download目录。修改后的配置如下:
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external" path="." /> <external-files-path name="external_files" path="." /> <files-path name="files" path="." /> <external-files-path name="my_images" path="Pictures" /> <external-files-path name="my_movies" path="Movies" /> </paths>
2. 适配Android 10+公共目录访问
公共Download目录属于MediaProvider管理,使用FileProvider访问容易出现权限问题,建议直接通过MediaStore获取文件URI:
// 替换原FileProvider URI获取逻辑 Android.Net.Uri apkUri = MediaStore.Downloads.GetContentUri(MediaStore.VolumeExternal); string[] projection = new string[] { MediaStore.Downloads.InterfaceConsts.Id }; string selection = MediaStore.Downloads.InterfaceConsts.DisplayName + " = ?"; string[] selectionArgs = new string[] { "test2.apk" }; using (var cursor = context.ContentResolver.Query(apkUri, projection, selection, selectionArgs, null)) { if (cursor != null && cursor.MoveToFirst()) { long id = cursor.GetLong(cursor.GetColumnIndexOrThrow(MediaStore.Downloads.InterfaceConsts.Id)); Android.Net.Uri uri = ContentUris.WithAppendedId(MediaStore.Downloads.ContentUri, id); // 直接指定APK的MIME类型,避免ContentResolver获取错误 Intent intent = new Intent(Intent.ActionView); intent.SetDataAndType(uri, "application/vnd.android.package-archive"); intent.AddFlags(ActivityFlags.NewTask); intent.AddFlags(ActivityFlags.GrantReadUriPermission); Intent chooser = Intent.CreateChooser(intent, "Update"); chooser.SetFlags(ActivityFlags.NewTask); IList<Android.Content.PM.ResolveInfo> resInfoList = context.PackageManager.QueryIntentActivities(chooser, Android.Content.PM.PackageInfoFlags.MatchDefaultOnly); foreach (Android.Content.PM.ResolveInfo resolveInfo in resInfoList) { string packageName = resolveInfo.ActivityInfo.PackageName; context.GrantUriPermission(packageName, uri, ActivityFlags.GrantReadUriPermission); } context.StartActivity(chooser); } }
3. 补充运行时权限检查
针对Android 6.0+,即使Manifest中声明了权限,也需要动态申请READ_EXTERNAL_STORAGE:
if (ContextCompat.CheckSelfPermission(context, Manifest.Permission.ReadExternalStorage) != Permission.Granted) { ActivityCompat.RequestPermissions((Activity)context, new string[] { Manifest.Permission.ReadExternalStorage }, 1001); }
4. 验证APK文件完整性
模拟器提示「解析软件包时出现问题」,可能是APK损坏:
- 直接在模拟器Download文件夹中手动点击APK,确认是否能正常安装
- 重新通过adb推送APK:
adb push test2.apk /storage/emulated/0/Download/
内容的提问来源于stack exchange,提问作者TryingAgain
相关产品推荐
相关产品推荐

