使用DocumentFile.createFile()在SD卡中创建新文件时出错; [英] Error while creating new File in SD Card using DocumentFile.createFile();

查看:136
本文介绍了使用DocumentFile.createFile()在SD卡中创建新文件时出错;的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在适用于Android 5.0及更高版本的SD卡中创建新文件.因此,首先让用户通过SAF授予权限.这就是我检查所选目录是否为SD卡的方法.

I am trying to create a new File in SD Card for Android 5.0 and above. So first I am making the user grant the permission through SAF. This is how I am check if the selected Directory is SD Card or Not.

public static boolean wrong_directory_selected(Uri uri, Context con)
    {

        final File uri_path=new File(FileUtil.getFullPathFromTreeUri(uri,con));
        if(uri_path.getName().toLowerCase().equals(new File("SD CARD PATH").getName().toLowerCase()))
        {

            return false;
        }
        return  true;
    }

然后这就是我尝试创建新文件的方式.

And then this is how I am Trying to Create a new File.

DocumentFile move = DocumentFile(new File("path)).createFile(mime,"name); // But I am getting java.lang.NullPointerException 

下面是我用来获取必须将文件创建到的目录的DocumentFile的方法.

Below are the methods which I am using to get the DocumentFile for the Directory to which the file has to be Created.

public static DocumentFile DocumentFile(final File file)
{

    DocumentFile rootDocFile = DocumentFile.fromTreeUri(con, permission().getUri());

    String[] parts = (file.getPath()).split("\\/");

    for (int i = 3; i < parts.length; i++)
    {

        rootDocFile = rootDocFile.findFile(parts[i]);

    }
    return rootDocFile;
}

public static UriPermission permission()
{
    for (UriPermission permissionUri : con.getContentResolver().getPersistedUriPermissions())
    {
        final File uri_path = new File(FileUtil.getFullPathFromTreeUri(permissionUri.getUri(), con));

        if (uri_path.getName().toLowerCase().equals(new File("SD_CARD_PATH").getName().toLowerCase()))
        {
            return permissionUri;

        }

    }

    return null;
}

该代码在大多数情况下都能正常工作,但有时我会得到java.lang.NullPointerException.

The code is working fine most of the time but sometime I am getting java.lang.NullPointerException.

任何帮助将不胜感激.

编辑:这是我的FileUtil类

This is my FileUtil class

public final class FileUtil {


    private static final String PRIMARY_VOLUME_NAME = "primary";




    @Nullable
    public static String getFullPathFromTreeUri(@Nullable final Uri treeUri, Context con) 
    {
        if (treeUri == null) 
        {
            return null;
        }
        String volumePath = FileUtil.getVolumePath(FileUtil.getVolumeIdFromTreeUri(treeUri),con);
        if (volumePath == null)
        {
            return File.separator;
        }
        if (volumePath.endsWith(File.separator))
        {
            volumePath = volumePath.substring(0, volumePath.length() - 1);
        }

        String documentPath = FileUtil.getDocumentPathFromTreeUri(treeUri);
        if (documentPath.endsWith(File.separator)) 
        {
            documentPath = documentPath.substring(0, documentPath.length() - 1);
        }

        if (documentPath.length() > 0)
        {
            if (documentPath.startsWith(File.separator)) 
            {
                return volumePath + documentPath;
            }
            else {
                return volumePath + File.separator + documentPath;
            }
        }
        else
        {
            return volumePath;
        }
    }


    private static String getVolumePath(final String volumeId, Context con)
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) 
        {
            return null;
        }

        try {
            StorageManager mStorageManager =
                    (StorageManager) con.getSystemService(Context.STORAGE_SERVICE);

            Class<?> storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");

            Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
            Method getUuid = storageVolumeClazz.getMethod("getUuid");
            Method getPath = storageVolumeClazz.getMethod("getPath");
            Method isPrimary = storageVolumeClazz.getMethod("isPrimary");
            Object result = getVolumeList.invoke(mStorageManager);

            final int length = Array.getLength(result);
            for (int i = 0; i < length; i++) 
            {
                Object storageVolumeElement = Array.get(result, i);
                String uuid = (String) getUuid.invoke(storageVolumeElement);
                Boolean primary = (Boolean) isPrimary.invoke(storageVolumeElement);

                // primary volume?
                if (primary && PRIMARY_VOLUME_NAME.equals(volumeId)) 
                {
                    return (String) getPath.invoke(storageVolumeElement);
                }

                // other volumes?
                if (uuid != null) 
                {
                    if (uuid.equals(volumeId)) 
                    {
                        return (String) getPath.invoke(storageVolumeElement);
                    }
                }
            }

            // not found.
            return null;
        }
        catch (Exception ex) 
        {
            return null;
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static String getVolumeIdFromTreeUri(final Uri treeUri) 
    {
        final String docId = DocumentsContract.getTreeDocumentId(treeUri);
        final String[] split = docId.split(":");

        if (split.length > 0)
        {
            return split[0];
        }
        else
        {
            return null;
        }
    }


    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static String getDocumentPathFromTreeUri(final Uri treeUri) 
    {
        final String docId = DocumentsContract.getTreeDocumentId(treeUri);
        final String[] split = docId.split(":");
        if ((split.length >= 2) && (split[1] != null))
        {
            return split[1];
        }
        else 
        {
            return File.separator;
        }
    }


}

必须在其中创建文件的路径很好,我还检查了权限URI,即使它也不为空.

The Path in which the file has to be created is fine and I have also checked the Permission URI and even that is not null.

值是

必须在其中创建文件的路径-/storage/external_SD

The path where the file has to be created- /storage/external_SD

权限Uri- content://com.android.externalstorage.documents/tree/6634-3765%3A

我正在使用此查找SD卡路径.

I am using this library to find the SD Card path.

推荐答案

继续,现在您已经有了通过循环DocumentFile(在其中创建文件的目录),只需使用myDocumentFile.createFile(...)在所需的directory上创建一个新文件即可.

Continue from this answer now that you have the DocumentFile (which is a directory to create a file inside it) through the loop just use myDocumentFile.createFile(...) to create a new file on your desired directory.

// creating the file
DocumentFile documentFileNewFile = documentFileGoal.createFile(myMimeType,
myNewFileName);

然后流向它

outputStream = getContentResolver().openOutputStream(documentFileNewFile.getUri());
inputStream = new FileInputStream(myInputFile);

...
   if (outputStream != null) {
       byte[] buffer = new byte[1024];
       int read;
       while ((read = inputStream.read(buffer)) != -1) {
           outputStream.write(buffer, 0, read);
       }
      }
...
...
...
} finally {
         if (inputStream != null)
             inputStream.close();
         if (outputStream != null) {
             outputStream.flush();
             outputStream.close();
           }
         }  

编辑
通过在每个循环中检查rootDocFile的值来防止在DocumentFile上出现findFile. (当用户选择错误的路径而不是sd-card时发生)

Edite
Prevent findFile on a null DocumentFile by checking the value of rootDocFile on each loop. (happens when the user selects a wrong path instead of the sd-card)

for (int i = 3; i < parts.length; i++)
{
    if (rootDocFile != null) {
        rootDocFile = rootDocFile.findFile(parts[i]);
    }
}

这篇关于使用DocumentFile.createFile()在SD卡中创建新文件时出错;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆