Xamarin Android中Directory.GetFiles返回Null问题排查求助
问题分析与解决方案
嘿,我来帮你捋清楚这个问题!首先先指出你代码里一个明显的逻辑bug——你把文件夹存在性的判断写反了:
var folder = "/storage/emulated/0/Pictures/Viber"; // 这里的!Directory.Exists(folder)是"如果文件夹不存在"的意思,你却输出"folder exist" if (!Directory.Exists(folder)) Console.WriteLine("folder exist"); else Console.WriteLine("doesnt exist");
修正后应该是:
var folder = "/storage/emulated/0/Pictures/Viber"; if (Directory.Exists(folder)) Console.WriteLine("folder exists"); else Console.WriteLine("folder doesn't exist");
接下来说说你遇到的核心问题:明明文件夹存在,但Directory.GetFiles返回空(正常情况下这个方法要么返回数组,要么抛异常,大概率是返回空数组),主要原因有两个:
1. 存储权限未正确获取
从Android 6.0(API 23)开始,读取外部存储属于危险权限,必须在运行时动态申请,只在AndroidManifest.xml里声明是不够的:
- 对于Android 12及以下,你需要在
AndroidManifest.xml中添加:
然后在代码中用Xamarin.Essentials请求权限:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />var status = await Permissions.RequestAsync<Permissions.StorageRead>(); if (status != PermissionStatus.Granted) { Console.WriteLine("存储权限未授予,无法访问文件夹"); return; } - 对于Android 13及以上,权限名称变了,需要替换为:
对应的权限请求是:<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />var status = await Permissions.RequestAsync<Permissions.MediaImages>();
2. Android 10+的Scoped Storage限制
从Android 10(API 29)开始,系统默认启用Scoped Storage,限制了App直接通过绝对路径访问外部存储的大部分目录,包括第三方App创建的子目录(比如这里的Viber图片目录)。此时Directory类的文件系统操作会被系统拦截,导致无法读取到文件。
这种情况下,推荐使用Android系统提供的MediaStore来查询媒体文件,而不是直接操作文件路径。比如这段代码可以获取Viber文件夹下的所有图片:
using Android.Content; using Android.Provider; using Android.Database; public List<string> GetViberImageFiles(Context context) { var viberImages = new List<string>(); // 定义要查询的字段(这里只需要文件路径) string[] projection = { MediaStore.Images.Media.Data }; // 筛选路径包含"/Pictures/Viber/"的文件 string selection = $"{MediaStore.Images.Media.Data} LIKE ?"; string[] selectionArgs = new string[] { "%/Pictures/Viber/%" }; using (ICursor cursor = context.ContentResolver.Query( MediaStore.Images.Media.ExternalContentUri, projection, selection, selectionArgs, null)) { if (cursor != null) { int pathColumnIndex = cursor.GetColumnIndex(MediaStore.Images.Media.Data); while (cursor.MoveToNext()) { string filePath = cursor.GetString(pathColumnIndex); viberImages.Add(filePath); } cursor.Close(); } } return viberImages; }
总结
你现在的问题本质是:
- 代码逻辑错误导致你对文件夹存在性的判断出现误解
- 未正确申请存储权限,导致无法访问目标目录
- Android 10+的存储政策限制了直接路径访问,需要用MediaStore替代
按照上面的步骤修正后,应该就能正常获取到Viber文件夹里的文件了。
内容的提问来源于stack exchange,提问作者John Jepeto
相关产品推荐
相关产品推荐

