package com.datarecovery.master.utils.xfile; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.provider.DocumentsContract; import java.io.File; import java.io.FileNotFoundException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Objects; public class XSAFFile extends BaseXFile { private final Context context; private final Uri documentUri; private final Uri pathUri; private final String path; private String mimeType; private String name; private boolean exist; private long size; private long lastModified; static String[] queryIds = { DocumentsContract.Document.COLUMN_MIME_TYPE, DocumentsContract.Document.COLUMN_DISPLAY_NAME, DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_SIZE, DocumentsContract.Document.COLUMN_LAST_MODIFIED }; public XSAFFile(Context context, Uri treeRoot, String[] segments) { this.context = context; Uri androidDataUri = null; if (segments == null || segments.length == 0) { this.pathUri = treeRoot; } else { StringBuilder stringBuilder = new StringBuilder(treeRoot.toString()); stringBuilder.append("%3A"); for (int i = 0; i < segments.length; i++) { stringBuilder.append(Uri.encode(segments[i])); if (i == 1) { androidDataUri = Uri.parse(stringBuilder.toString()); } if (i != segments.length - 1) { stringBuilder.append("%2F"); } } this.pathUri = Uri.parse(stringBuilder.toString()); } StringBuilder pathBuilder = new StringBuilder(File.separator); for (String segment : treeRoot.getPathSegments()) { pathBuilder.append(segment).append(File.separator); } if (segments != null && segments.length != 0) { for (String segment : segments) { pathBuilder.append(segment).append(File.separator); } pathBuilder.deleteCharAt(pathBuilder.length() - 1); } this.path = pathBuilder.toString(); String documentId; if (DocumentsContract.isDocumentUri(context, pathUri)) { documentId = DocumentsContract.getDocumentId(pathUri); } else { documentId = DocumentsContract.getTreeDocumentId(pathUri); } this.documentUri = DocumentsContract.buildDocumentUriUsingTree(androidDataUri, documentId); queryData(); } public XSAFFile(Context context, Uri treeRoot, List segments) { this.context = context; if (segments == null || segments.size() == 0) { this.pathUri = treeRoot; } else { StringBuilder stringBuilder = new StringBuilder(treeRoot.toString()); stringBuilder.append("%3A"); for (int i = 0; i < segments.size(); i++) { if (i < 2) { stringBuilder.append(Uri.encode(segments.get(i))); } if (i != segments.size() - 1 && i < 1) { stringBuilder.append("%2F"); } } this.pathUri = Uri.parse(stringBuilder.toString()); } StringBuilder pathBuilder = new StringBuilder(File.separator); for (String segment : treeRoot.getPathSegments()) { pathBuilder.append(segment).append(File.separator); } if (segments != null && segments.size() != 0) { for (String segment : segments) { pathBuilder.append(segment).append(File.separator); } pathBuilder.deleteCharAt(pathBuilder.length() - 1); } this.path = pathBuilder.toString(); String documentId; if (DocumentsContract.isDocumentUri(context, pathUri)) { documentId = DocumentsContract.getDocumentId(pathUri); } else { documentId = DocumentsContract.getTreeDocumentId(pathUri); } this.documentUri = DocumentsContract.buildDocumentUriUsingTree(pathUri, documentId); queryData(); } public XSAFFile(Context context, Uri documentUri) { this.context = context; this.documentUri = documentUri; Uri treeRootUri = DocumentsContract.buildTreeDocumentUri(documentUri.getAuthority(), DocumentsContract.getDocumentId(documentUri)); StringBuilder pathBuilder = new StringBuilder(File.separator); List pathSegments = treeRootUri.getPathSegments(); if (pathSegments != null && pathSegments.size() > 0) { for (String segment : pathSegments) { pathBuilder.append(segment).append(File.separator); } pathBuilder.deleteCharAt(pathBuilder.length() - 1); } this.path = pathBuilder.toString(); this.pathUri = treeRootUri; queryData(); } private void queryData() { try (Cursor cursor = context.getContentResolver().query(documentUri, queryIds, null, null, null)) { if (cursor != null && cursor.moveToFirst()) { for (int i = 0; i < queryIds.length; i++) { if (DocumentsContract.Document.COLUMN_MIME_TYPE.equals(queryIds[i])) { try { mimeType = cursor.getString(i); } catch (Exception ignore) { } } else if (DocumentsContract.Document.COLUMN_DISPLAY_NAME.equals(queryIds[i])) { try { name = cursor.getString(i); } catch (Exception ignore) { } } else if (DocumentsContract.Document.COLUMN_DOCUMENT_ID.equals(queryIds[i])) { try { exist = cursor.getString(i) != null; } catch (Exception ignore) { } } else if (DocumentsContract.Document.COLUMN_SIZE.equals(queryIds[i])) { try { size = cursor.getLong(i); } catch (Exception ignore) { } } else if (DocumentsContract.Document.COLUMN_LAST_MODIFIED.equals(queryIds[i])) { try { lastModified = cursor.getLong(i); } catch (Exception ignore) { } } } } } catch (Exception ignore) { } } @Override public String getName() { return name; } @Override public String getPath() { return path; } @Override public String getMineType() { return mimeType; } @Override public Uri getUri() throws Exception { return documentUri; } @Override public boolean isDirectory() { return Objects.equals(mimeType, DocumentsContract.Document.MIME_TYPE_DIR); } @Override public XFile[] listFiles() { Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(documentUri, DocumentsContract.getDocumentId(documentUri)); try (Cursor cursor = context.getContentResolver().query(childrenUri, new String[]{DocumentsContract.Document.COLUMN_DOCUMENT_ID}, null, null, null)) { ArrayList children = new ArrayList<>(); if (cursor != null && cursor.moveToFirst()) { do { String documentId = cursor.getString(0); Uri childUri = DocumentsContract.buildDocumentUriUsingTree(documentUri, documentId); children.add(new XSAFFile(context, childUri)); } while (cursor.moveToNext()); } return children.toArray(new XFile[0]); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public boolean exists() { return exist; } @Override public boolean delete() { try { DocumentsContract.deleteDocument(context.getContentResolver(), documentUri); return true; } catch (FileNotFoundException e) { e.printStackTrace(); } return false; } @Override public long length() { return size; } @Override public long lastModified() { return lastModified; } @Override public InputStream newInputStream() throws Exception { return context.getContentResolver().openInputStream(documentUri); } public Uri getPathUri() { return pathUri; } public Uri getDocumentUri() { return documentUri; } private String queryForString(String colum) throws Exception { try (Cursor cursor = context.getContentResolver().query(documentUri, new String[]{colum}, null, null, null)) { if (cursor != null && cursor.moveToFirst()) { return cursor.getString(0); } } return null; } private long queryForLong(String colum) throws Exception { try (Cursor cursor = context.getContentResolver().query(documentUri, new String[]{colum}, null, null, null)) { if (cursor != null && cursor.moveToFirst()) { return cursor.getLong(0); } } return 0; } }