Android 对5.0+的外置SD卡删除操作

本文介绍了在Android 4.4以上版本中如何处理外部SD卡的读写权限问题,包括使用Storage Access Framework (SAF)的方法及实现代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#在4.4以上中,谷歌对其已经做了权限限制,为了规范SD卡操作!在推出后,引起业界一片吐槽,迫于压力,google推出了一种全新的方式去操作SD卡:Android SAF

注:
一定要进行版本判断
一定要进行版本判断
一定要进行版本判断

private static int DOCUMENT_TREE_REQUEST = 1;
 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
 activity.startActivityForResult(intent, DOCUMENT_TREE_REQUEST);

通过上面意图会进入到:
http://jingyan.baidu.com/article/91f5db1b3fc3981c7f05e3f1.html(这时es文件管理器的操作方式,其实都一样)

选择SD卡后,会调用

public static String ACTION_OPEN_DOCUMENT_TREE_URL = "ACTION_OPEN_DOCUMENT_TREE";
    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        SharedPreferences lee = getApplicationContext().getSharedPreferences("xxx", 0);
        if (requestCode == 1) {
                String p = lee.getString("URI", null);
                Uri oldUri = null;
                if (p != null) oldUri = Uri.parse(p);
                Uri treeUri = null;
                if (resultCode == Activity.RESULT_OK) {
                    // Get Uri from Storage Access Framework.
                    treeUri = data.getData();
                    // Persist URI - this is required for verification of writability.
                    if (treeUri != null) lee.edit().putString(ACTION_OPEN_DOCUMENT_TREE_URL, treeUri.toString()).commit();
                }
                // If not confirmed SAF, or if still not writable, then revert settings.
                if (resultCode != Activity.RESULT_OK) {
               /* DialogUtil.displayError(getActivity(), R.string.message_dialog_cannot_write_to_folder_saf, false,
                        currentFolder);||!FileUtil.isWritableNormalOrSaf(currentFolder)
*/
                    if (treeUri != null) lee.edit().putString(ACTION_OPEN_DOCUMENT_TREE_URL, oldUri.toString()).commit();
                    return;
                }

                // After confirmation, update stored value of folder.
                // Persist access permissions.
                final int takeFlags = data.getFlags()
                        & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                getContentResolver().takePersistableUriPermission(treeUri, takeFlags);
                Toast.makeText(getApplicationContext(),getApplicationContext().getString(R.string.success_get_premiss_tips),Toast.LENGTH_SHORT).show();
        }
    }

注意上面的 SharedPreferences lee = getApplicationContext().getSharedPreferences(“xxx”, 0); 会将URI保存到SharedPreferences中,
然后在需要删除外置SD卡时我们需要获取一个DocumentFile对象

  public  DocumentFile getDocumentFile(final File file, final boolean isDirectory,Context context) {
        String baseFolder = getExtSdCardFolder(file,context);
        boolean originalDirectory=false;
        if (baseFolder == null) {
            return null;
        }

        String relativePath = null;
        try {
            String fullPath = file.getCanonicalPath();
            if(!baseFolder.equals(fullPath))
                relativePath = fullPath.substring(baseFolder.length() + 1);
            else originalDirectory=true;
        }
        catch (IOException e) {
            return null;
        }
        catch (Exception f){
            originalDirectory=true;
            //continue
        }
        //此处更换你的SharedPreferences
        SharedPreferences lee = context.getSharedPreferences("xxx", 0);
        String uri = lee.getString(ACTION_OPEN_DOCUMENT_TREE_URL,null);
        Uri parse = Uri.parse(uri);

        // start with root of SD card and then parse through document tree.
        DocumentFile document = DocumentFile.fromTreeUri(context, parse);
        if(originalDirectory)return document;
        String[] parts = relativePath.split("\\/");
        for (int i = 0; i < parts.length; i++) {
            DocumentFile nextDocument = document.findFile(parts[i]);
            if (nextDocument == null) {
                if ((i < parts.length - 1) || isDirectory) {
                    if( document.createDirectory(parts[i])==null){
                        return null;
                    }
                    nextDocument = document.createDirectory(parts[i]);
                }
                else {
                    nextDocument = document.createFile("image", parts[i]);
                }
            }
            document = nextDocument;
        }

        return document;
    }

 @TargetApi(Build.VERSION_CODES.KITKAT)
    public static String getExtSdCardFolder(final File file,Context context) {
        String[] extSdPaths = getExtSdCardPaths(context);
        try {
            for (int i = 0; i < extSdPaths.length; i++) {
                if (file.getCanonicalPath().startsWith(extSdPaths[i])) {
                    return extSdPaths[i];
                }
            }
        }
        catch (IOException e) {
            return null;
        }
        return null;
    }
    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static String[] getExtSdCardPaths(Context context) {
        List<String> paths = new ArrayList<String>();
        for (File file : context.getExternalFilesDirs("external")) {
            if (file != null && !file.equals(context.getExternalFilesDir("external"))) {
                int index = file.getAbsolutePath().lastIndexOf("/Android/data");
                if (index < 0) {
                    Log.w("AmazeFileUtils", "Unexpected external file dir: " + file.getAbsolutePath());
                }
                else {
                    String path = file.getAbsolutePath().substring(0, index);
                    try {
                        path = new File(path).getCanonicalPath();
                    }
                    catch (IOException e) {
                        // Keep non-canonical path.
                    }
                    paths.add(path);
                }
            }
        }
        if(paths.isEmpty())paths.add("/storage/sdcard1");
        return paths.toArray(new String[0]);
    }

拿到DocumentFile对象后进行删除操作:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public boolean delect(FileInfo f) {
        DocumentFile documentFile = getDocumentFile(new File(f.filePath), f.IsDir, mContext);
        if(documentFile!=null) {
            documentFile.delete();
        }else {
            //当更换SD卡后,uri值会发生变化,拿到的DocumentFile会为null,而此处在进行一次上面操作既可
        }
        return true;

    }

剩下的创建复制剪贴和File一样,只将换成documentFile既可!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值