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

Xamarin Android无法在存储中创建文件:权限被拒问题求助

问题分析与解决方案

核心问题1:权限请求代码错误

你当前的权限请求逻辑存在明显错误:

  • 在if分支中,判断是否缺少WRITE_EXTERNAL_STORAGE权限,但实际请求的却是Camera权限,导致权限弹窗永远不会申请你需要的存储权限。
  • else分支中,明明已经拥有权限,却重复发起权限请求,完全冗余。

核心问题2:权限请求后立刻执行文件操作

ActivityCompat.RequestPermissions是异步操作,调用后不会立刻拿到权限,你紧接着调用eCreateFile,此时权限还未授予,必然触发权限拒绝报错。


修复步骤

1. 修正权限请求逻辑(利用已安装的Plugin.Permissions)

将点击事件中的权限请求代码替换为异步逻辑,等待权限请求结果后再执行文件操作:

_start.Click += async (sender, e) =>
{
    _stop.Enabled = !_stop.Enabled;
    _start.Enabled = !_start.Enabled;
    _text2.Text = path.ToString();

    // 检查存储权限状态
    var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
    if (status != PermissionStatus.Granted)
    {
        // 发起权限请求
        var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
        status = results[Permission.Storage];
    }

    // 权限授予后执行文件创建
    if (status == PermissionStatus.Granted)
    {
        eCreateFile(path);
    }
    else
    {
        _text3.Text = "存储权限未授予,无法创建文件";
    }
};

2. 移除冗余代码

删除原来的static readonly int WRITE_EXTERNAL_STORAGE = 0;以及旧的ActivityCompat.RequestPermissions相关代码。

3. 可选:改用应用专属存储路径(无需权限)

如果不需要让其他应用访问这个文件,建议使用应用专属外部存储路径,无需申请存储权限,且卸载应用时文件会自动删除:

// 获取应用专属外部存储目录
string path = Path.Combine(ApplicationContext.GetExternalFilesDir(null).AbsolutePath, "esi2.txt");

4. 验证Manifest配置(当前已正确配置)

你已经添加了android:requestLegacyExternalStorage="true",对于targetSdkVersion=30(Android 10),该配置可让应用使用旧存储策略,无需适配Scoped Storage,当前配置无问题。


完整修改后的关键代码示例

public class MainActivity : AppCompatActivity
{
    Button _start;
    Button _stop;
    TextView _text1;
    TextView _text2;
    TextView _text3;
    MediaRecorder Recorder;
    string path;

    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        SetContentView(Resource.Layout.activity_main);

        _start = FindViewById<Button>(Resource.Id.materialButton1);
        _stop = FindViewById<Button>(Resource.Id.materialButton2);
        _text1 = FindViewById<TextView>(Resource.Id.textView1);
        _text2 = FindViewById<TextView>(Resource.Id.textView2);
        _text3 = FindViewById<TextView>(Resource.Id.textView3);
        
        // 可选:应用专属路径(无需权限)
        // path = Path.Combine(ApplicationContext.GetExternalFilesDir(null).AbsolutePath, "esi2.txt");
        // 原公共路径(需权限)
        path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/esi2.txt";
        
        _start.Click += async (sender, e) =>
        {
            _stop.Enabled = !_stop.Enabled;
            _start.Enabled = !_start.Enabled;
            _text2.Text = path.ToString();

            var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
            if (status != PermissionStatus.Granted)
            {
                var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
                status = results[Permission.Storage];
            }

            if (status == PermissionStatus.Granted)
            {
                eCreateFile(path);
            }
            else
            {
                _text3.Text = "存储权限未授予,无法创建文件";
            }
        };
    }

    public void eCreateFile(string FileName)
    {
        string text = "Ehsan Test";
        byte[] data = System.Text.ASCIIEncoding.ASCII.GetBytes(text);
        try
        {
            File.WriteAllBytes(FileName, data);
            _text3.Text = "文件创建成功";
        }
        catch(Exception ex) 
        {
            _text3.Text = ex.Message;
        }
    }

    // 重写权限回调,适配插件需求
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

内容的提问来源于stack exchange,提问作者eag-ehsan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:45:33