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

MAUI Android平台文件删除异常问题求助

MAUI Android 10+ 真机删除SD卡文件失效问题解决方案

问题概述

  • 开发的MAUI应用可读取USB读卡器连接的SD卡中CSV格式日志,提取数据写入SQL并备份至云端,需删除SD卡上的日志文件
  • 仅Android平台存在异常:模拟器中删除操作正常,但Android 10+(目标SDK31)真机上,代码执行后File.Exists返回false,提示文件已删除,但SD卡上的文件实际仍存在
  • 已在Manifest中配置相关权限,代码中也请求了用户权限,删除逻辑按微软文档编写,无异常抛出;已完成文件读取,将文件移至内部存储(如下载目录)后问题仍存在

已配置的Android权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS" />
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

核心删除逻辑代码

var ff1 = System.IO.File.ReadAllLines(csvorig);
var csvlen= ff1.Length;
if (csvlen < 300)   // 每秒一行,少于300行判定为无效数据
{
    var nl = System.Environment.NewLine;
    var answ = await DisplayAlert(dbpath + nl + "Small file", "the file you've selected contains no flight" + nl + "prob cause = switching on avionics for < 5min " + nl + " file should be deleted", "DELETE", "ignore");
    if (answ)
    {
        status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
        if (status == PermissionStatus.Denied)
        {
            PermissionStatus status2=awaitPermissions.RequestAsync<Permissions.StorageWrite>();
        }
        // 再次检查权限
        status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
        if (status == PermissionStatus.Denied)
        {
            await DisplayAlert("warn", "Sorry cannot grant permission \n you will need to delete this file using filemanager \n" + csvorig, "cancel");
            return;
        }
        try
        {
            // 重置文件属性
            File.SetAttributes(csvorig, FileAttributes.Normal);
            File.Delete(csvorig);
        }
        catch (Exception ee)
        {
            var m = ee.Message;
            await DisplayAlert("", m, "Cancel");
        }

        if (File.Exists(csvorig))
        {           
            await DisplayAlert("warn", "failed to delete", "cancel");
        }
        else
        { 
            await DisplayAlert(csvorig, "has been deleted", "back"); 
        }
    }
}

解决方案

1. 清理并修正权限配置

  • 移除重复的MANAGE_EXTERNAL_STORAGE权限
  • 删除无用/废弃权限:READ_INTERNAL_STORAGE、WRITE_INTERNAL_STORAGE、MOUNT_UNMOUNT_FILESYSTEMS、MOUNT_FORMAT_FILESYSTEMS,这些权限要么已被Android废弃,要么普通应用无法获取
  • 对于Android 10+,WRITE_EXTERNAL_STORAGE已失效,需依赖MANAGE_EXTERNAL_STORAGE或存储访问框架(SAF)

2. 改用存储访问框架(SAF)执行删除

Android 10+的Scoped Storage限制下,直接通过文件路径操作可能无法真正修改外部存储文件,改用SAF通过文件URI执行删除:

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Q)
{
    // 若通过FilePicker获取文件,优先使用FileResult中的FileUri
    var fileUri = Android.Net.Uri.Parse(csvorig);
    var resolver = Android.App.Application.Context.ContentResolver;
    
    // 执行删除操作
    int rowsDeleted = resolver.Delete(fileUri, null, null);
    
    if (rowsDeleted > 0)
    {
        await DisplayAlert(csvorig, "已成功删除", "返回");
    }
    else
    {
        await DisplayAlert("警告", "删除失败,请检查权限", "取消");
    }
}

如果是通过MAUI的FilePicker.PickAsync()获取文件,直接使用返回的FileResult.FileUri即可,无需手动转换路径。

3. 确保文件句柄完全释放

虽然ReadAllLines会自动关闭流,但显式使用using块可以确保文件句柄被释放,避免因文件占用导致删除失效:

string[] ff1;
using (var stream = new FileStream(csvorig, FileMode.Open, FileAccess.Read))
using (var reader = new StreamReader(stream))
{
    ff1 = reader.ReadToEnd().Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
}
var csvlen = ff1.Length;

4. 正确检查MANAGE_EXTERNAL_STORAGE权限

Android 11+需要用户手动开启“访问所有文件”权限,代码中需单独检查并引导用户开启:

if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.R)
{
    if (!Android.OS.Environment.IsExternalStorageManager)
    {
        var intent = new Android.Content.Intent(Android.OS.Environment.ActionManageAppAllFilesAccessPermission);
        intent.SetData(Android.Net.Uri.Parse($"package:{Android.App.Application.Context.PackageName}"));
        intent.AddFlags(Android.Content.ActivityFlags.NewTask);
        Android.App.Application.Context.StartActivity(intent);
        await DisplayAlert("提示", "请开启“访问所有文件”权限以完成删除操作", "确定");
        return;
    }
}

内容的提问来源于stack exchange,提问作者john murray

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:25:09