I want to get path to pdf file,which i get as uri from intent action ACTION_OPEN_DOCUMENT,but how i can get it,if media type of uri is document (via debug i understand,what problem in line 126 of my code). For images i haven't any problem,with permission read_media_images or read_external_storage (for android twelve and lower),but with pdf documents i have this problem. I dont want to get full access to external storage,because it will be probably problems with google play,so whether it possible get paths of pdf files without specials permissions,which use in api 30 and hier to get full access to external storage. Thanks very much for any help.
package maximsblog.blogspot.com.visionsender;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.text.TextUtils;
import androidx.loader.content.CursorLoader;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
class AndroidUtilities {
static class IOUtils {
private static final int BUFFER_SIZE = 1024 * 2;
static int copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
BufferedInputStream b = new BufferedInputStream(input, BUFFER_SIZE);
BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
int count = 0;
int n = 0;
try {
while((n =input.read(buffer, 0, BUFFER_SIZE))!= -1) {
out.write(buffer, 0, n);
count += n;
}
out.flush();
} finally {
try {
out.close();
} catch (IOException e) {
}
try {
input.close();
} catch (IOException e) {
}
}
return count;
}
}
static boolean isWhatsappUri(Uri uri) {
return "com.whatsapp.provider.media".equals(uri.getAuthority());
}
static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs, String columnName) {
Cursor cursor =null;
if (columnName == null)
columnName = "_data";
try {
cursor = context.getContentResolver().query(
uri, new String[] {columnName}, selection, selectionArgs,null);
if (cursor == null) return uri.getPath();
if (cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(columnName);
if (columnName.equals("_data"))
return cursor.getString(column_index);
else
return uri.toString() + "/" + cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
return getDataColumn(context, uri, selection, selectionArgs, null);
}
@SuppressLint("NewApi")
static String getRealPathFromURI_API19(Context context, Uri uri) {
String result = null;
if (DocumentsContract.isDocumentUri(context, uri)) {
String[] split =null;
String docId=null;
if (isExternalStorageDocument(uri)) {
docId = DocumentsContract.getDocumentId(uri);
String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory().toString() + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) {
docId = DocumentsContract.getDocumentId(uri);
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
return getDataColumn(context, contentUri, null, null);
} else if (isMediaDocument(uri)) {
docId = DocumentsContract.getDocumentId(uri);
split = docId.split(":");
String type = split[0];
Uri contentUri =null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
else if("document".equals(type)) { //in this line (126) we have a problems. How to get path of file for this case?
//contentUri =MediaStore.getDocumentUri(context,uri); //crash,when we call this method.
}
String selection = "_id=?";
return getDataColumn(context, contentUri, selection, new String[] {split[1]});
}
}
else if ("content".equalsIgnoreCase(uri.getScheme())) {
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
} else if (isWhatsappUri(uri)) {
return getDataColumn(context, uri, null, null, "_display_name");
}
return null;
}
@SuppressLint("NewApi")
static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
if (isWhatsappUri(contentUri)) {
return new File(contentUri.getPath()).getAbsolutePath();
}
String[] proj = new String[] {MediaStore.Images.Media.DATA};
String result = null;
CursorLoader cursorLoader = new CursorLoader(
context,
contentUri, proj, null, null, null
);
Cursor cursor = cursorLoader.loadInBackground();
if (cursor != null) {
cursor.moveToFirst();
result = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
}
cursor.close();
return result;
}
static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
if (isWhatsappUri(contentUri)) {
return new File(contentUri.getPath()).getAbsolutePath();
}
Cursor cursor = context.getContentResolver().query(contentUri, new String[] {MediaStore.Images.Media.DATA}, null, null, null);
cursor.moveToFirst();
String result = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
cursor.close();
return result;
}
static String getRealPath(Context context, Uri uri) {
if(Build.VERSION.SDK_INT < 11) return getRealPathFromURI_BelowAPI11(context, uri);
else if(Build.VERSION.SDK_INT < 19) return getRealPathFromURI_API11to18(context, uri);
else return getRealPathFromURI_API19(context, uri);
}
static String getFileName(String Fpath) {
String[] result=Fpath.split("/");
return result[result.length-1];
}
static void copy(Context context, Uri srcUri, File dstFile) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(
srcUri);
FileOutputStream outputStream = new FileOutputStream(dstFile);
IOUtils.copy(inputStream, outputStream);
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
static String getFilePathFromURI(Context context, Uri contentUri) {
String fileName = getFileName(contentUri.getPath());
if (!TextUtils.isEmpty(fileName)) {
File copyFile = new File(context.getCacheDir().toString() + "/" + fileName);
copy(context, contentUri, copyFile);
return copyFile.getAbsolutePath();
}
return null;
}
}
Call
DocumentFile.fromSingleUri()to get aDocumentFilerepresenting the document identified by theUri. Then callgetName()on theDocumentFileto get a display name. This may or may not be a "file name", but it should be a name that is recognizable to the user.