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

Android Xamarin:目录文件无法添加至Spinner列表问题求助

问题:Spinner无法加载指定目录的文件列表

尝试将指定目录下的文件添加到Spinner中,但Spinner始终为空。目标文件夹确实存在且包含3个文件,代码中“目录已找到”的Toast能正常触发,但循环内的“找到文件”提示从未弹出。

原代码

public class MainActivity : Activity
{
    Button btnGetFiles;
    Spinner spinnerGetFiles;
    List<string> fileList;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.Main);
        spinnerGetFiles = FindViewById<Spinner>(Resource.Id.spinnerGetFiles);
        btnGetFiles = FindViewById<Button>(Resource.Id.btnGetFiles);

        btnGetFiles.Click += delegate 
        {
            fileList = GetFilesFromDirectory("/storage/emulated/0/MyFolder");
            ArrayAdapter<string> adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerItem, fileList);
            spinnerGetFiles.Adapter = adapter;
        };
    }

    List<string> GetFilesFromDirectory(string strDirectoryPath)
    {            
        List<string> files = new List<string>();
        if (Directory.Exists(strDirectoryPath))
        {
            Toast.MakeText(Application.Context, "Directory found", ToastLength.Long).Show();
            string[] fileList2 = Directory.GetFiles(strDirectoryPath);
            foreach (string file in fileList2)
            {
                files.Add(Path.GetFileName(file));
                Toast.MakeText(Application.Context, "File found : " + file, ToastLength.Long).Show();                   
            }
        }
        else { Toast.MakeText(Application.Context, "No directory was found!!", ToastLength.Long).Show(); }
        return files;
    }
}

问题排查与解决

1. 存储权限缺失(核心原因)

Android 6.0(API 23)及以上版本,读取外部存储需要动态申请权限,仅在Manifest中声明权限无效:

  • 先在AndroidManifest.xml中添加权限声明:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- Android 10+ 需全存储访问可添加: -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
  • 在代码中补充权限申请逻辑,修改OnCreate方法:
protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    SetContentView(Resource.Layout.Main);
    spinnerGetFiles = FindViewById<Spinner>(Resource.Id.spinnerGetFiles);
    btnGetFiles = FindViewById<Button>(Resource.Id.btnGetFiles);

    // 启动时检查存储权限
    if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) != Permission.Granted)
    {
        ActivityCompat.RequestPermissions(this, new string[] { Manifest.Permission.ReadExternalStorage }, 100);
    }

    btnGetFiles.Click += delegate 
    {
        // 确认权限授予后再读取文件
        if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.ReadExternalStorage) == Permission.Granted)
        {
            string folderPath = Path.Combine(Environment.ExternalStorageDirectory.AbsolutePath, "MyFolder");
            fileList = GetFilesFromDirectory(folderPath);
            ArrayAdapter<string> adapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleSpinnerItem, fileList);
            spinnerGetFiles.Adapter = adapter;
        }
        else
        {
            Toast.MakeText(this, "请授予存储权限", ToastLength.Long).Show();
        }
    };
}

// 处理权限申请结果
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 100)
    {
        if (grantResults.Length > 0 && grantResults[0] == Permission.Granted)
        {
            Toast.MakeText(this, "权限已授予", ToastLength.Long).Show();
        }
        else
        {
            Toast.MakeText(this, "权限被拒绝,无法读取文件", ToastLength.Long).Show();
        }
    }
}

2. 避免硬编码路径

不要直接写/storage/emulated/0/MyFolder,改用系统API获取路径,适配不同设备:

string folderPath = Path.Combine(Environment.ExternalStorageDirectory.AbsolutePath, "MyFolder");

3. Android 10+ 适配

若目标版本为Android 10(API 29)及以上,默认启用Scoped Storage,直接读取外部目录可能受限:

  • 可在AndroidManifest.xml的<application>标签中添加过渡配置:android:requestLegacyExternalStorage="true";
  • 长期方案建议使用MediaStore API查询文件,适配Scoped Storage规范。

4. 调试文件获取逻辑

可在GetFilesFromDirectory中添加日志,确认文件数组长度:

string[] fileList2 = Directory.GetFiles(strDirectoryPath);
Log.Debug("FileDebug", $"找到{fileList2.Length}个文件");

内容的提问来源于stack exchange,提问作者Anthony Magerera

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 03:52:35