有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Android无法在sd卡上写入和删除操作

我现在正在开发ImageCompressor应用程序

我需要deletewrite(更新)映像文件。在内部存储中工作得很好,但**SD卡不能给我删除和写入文件的权限

我的应用程序如何能够在sd卡上执行writedelete操作(可移动存储)

我已经完成了整个项目,所以我必须想办法

更新:

我已经在做研究了;讨论这个问题。我知道我必须使用storage access framework,但我对SAF是新手

我使用了来压缩需要文件而不是Uri的照片。为此,我使用Uri -> File并使用Intent.ACTION_OPEN_DOCUMENT从可移动存储中选择图像

But for removable storage I can't find Image Real Path from uri.

我不知道这是不是正确的方式。如果在SAF中有任何方法可以使用uri压缩我的图像,请告诉我。或者如何从可移动存储照片的uri获取图像真实路径

更新代码SAF:

//  -----------  Intent  -------------
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");

//  ------------  On Activity Result  --------------
Uri uri = data.getData();
try {
    ParcelFileDescriptor fileDescriptor = getContentResolver().openFileDescriptor(uri, "w");
    FileOutputStream fos = new FileOutputStream(fileDescriptor.getFileDescriptor());

    FileInputStream fis = new FileInputStream(getImageFilePath(uri));

    FileChannel source = fis.getChannel();
    FileChannel destination = fos.getChannel();
    destination.transferFrom(source, 0, source.size());

    fis.close();
    fos.close();
    fileDescriptor.close();
    Toast.makeText(this, "File save successfully.", Toast.LENGTH_SHORT).show();
}

Uri到文件路径,我从媒体应用程序(如Gallary、Photos)中选择图像,但从sd卡中选择什么将代替MediaStore.Images.Media.DATA我不知道。代码:

private File getImageFilePath(Uri uri) throws IOException {
    String image_id = null, imagePath = null;

    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null) {
        cursor.moveToFirst();
        image_id = cursor.getString(0);
        image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
        cursor.close();
    }
    cursor = getContentResolver().query(安卓.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    if (cursor!=null) {
        cursor.moveToFirst();
        imagePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
    }

    File file = new File(imagePath);
    return new Compressor(this).setQuality(50).compressToFile(file);
}

共 (3) 个答案

  1. # 1 楼答案

    如果使用File和FileOutputStream类,可移动SD卡只能在现代Android设备上写入

    如果幸运的话,使用getExternalFilesDirs()的设备会在卡片上返回一个特定于应用程序的目录,作为第二项,您仍然可以在其中写入内容

    对于其余部分,使用Storage Access Framework

    首先让用户选择带有Intent.ACTION_OPEN_DOCUMENT_TREE的sd卡或带有Intent.ACTION_OPEN_DOCUMENT的文件

  2. # 2 楼答案

    我挖掘了我的一个旧安卓应用程序,并检索到:

    此方法将sdcard uri的根转换为File路径

    public File getRootPath(Context context, Uri sdcardRootUri)
    {
        List<String> pathSegments =  sdcardRootUri.getPathSegments();
        String[] tokens = pathSegments.get(pathSegments.size()-1).split(":");
        for (File f : ContextCompat.getExternalFilesDirs(context, null))
        {
            String path = f.getAbsolutePath().substring(0, f.getAbsolutePath().indexOf("/Android/"));
            if (path.contains(tokens[0]))
            {
                return new File(path);
            }
        }
        return null;
    }
    

    为了检索sdcard根的uri,我使用了:

    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
    startActivityForResult(intent, SDCARD_ROOT_CODE);
    

    然后用户会选择SD卡的根,然后,我像这样处理结果:

    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {
        if (resultCode == RESULT_OK && requestCode == SDCARD_ROOT_CODE)
        {
            // Persist access permissions
            Uri sdcdardRootUri = data.getData();
            grantUriPermission(getPackageName(), sdcdardRootUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            getContentResolver().takePersistableUriPermission(sdcdardRootUri, takeFlags);
    
            // Do whatever you want with sdcdardRootUri
        }
    }
    

    我希望这就是你想要的。有了它,你可以读取/写入/删除SD卡上你想要的任何文件

  3. # 3 楼答案

    你必须试试

        try {
            Runtime runtime = Runtime.getRuntime();
            Process proc = runtime.exec("mount");
            InputStream is = proc.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            String line;
            BufferedReader br = new BufferedReader(isr);
            while ((line = br.readLine()) != null) {
                //Filter common Linux partitions
                if (line.contains("secure"))
                    continue;
                if (line.contains("asec"))
                    continue;
                if (line.contains("media"))
                    continue;
                if (line.contains("system") || line.contains("cache")
                    || line.contains("sys") || line.contains("data")
                    || line.contains("tmpfs") || line.contains("shell")
                    || line.contains("root") || line.contains("acct")
                    || line.contains("proc") || line.contains("misc")
                    || line.contains("obb")) {
                    continue;
                }
    
                if (line.contains("fat") || line.contains("fuse") || (line
                    .contains("ntfs"))) {
    
                    String columns[] = line.split(" ");
                    if (columns != null && columns.length > 1) {
                        String path = columns[1];
                        if (path!=null&&!SdList.contains(path)&&path.contains("sd"))
                            SdList.add(columns[1]);
                    }
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }