You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:05:54