使用DocumentFile.createFile()在SD卡中创建新文件时出错; [英] Error while creating new File in SD Card using DocumentFile.createFile();
问题描述
我正在尝试在适用于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屋!