Trying to extract file path from send action:
<data android:mimeType="*/*" />
Here is activity:
Uri contentUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (contentUri != null) {
String pathUri = contentUri.toString();
if (pathUri.contains("file://")) {
path = contentUri.getPath();
}
}
if(path==null) {
if (type.startsWith("image/")) {
path = Constant.getRealPathFromURI(this, (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM));
} else if (type.startsWith("video/")) {
path = Constant.getRealPathFromURI(this, (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM));
}
}
if (path == null && intent.getData() != null) {
path = intent.getData().getPath();
}
if (path == null) {
Toast.makeText(getApplicationContext(), "None uri !", Toast.LENGTH_LONG).show();
}
Always getting null path except 'image/' and 'video/".
on: Essential PH-1 device
Working all fine on: Lenovo Vibe K5 Note
Is not bullet proof code for all devices? anything wrong with code?
Is there any universal way to extract send action file path without being worried about it's mimetype?
Edit:
public static String getRealPathFromURI(Context context, Uri contentUri) {
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
Related
When I'm going select a file from all downloads folder and then getting file path from uri using content provider getting following permission denied issue below
Permission Denial: reading com.android.providers.downloads.DownloadProvider uri content://downloads/all_downloads/1092 from pid=31615, uid=10228 requires android.permission.ACCESS_ALL_DOWNLOADS, or grantUriPermission()
using following code
String[] contentUriPrefixesToTry = new String[]{
"content://downloads/public_downloads",
"content://downloads/my_downloads",
"content://downloads/all_downloads"
};
final String id = DocumentsContract.getDocumentId(uri);
String path = null;
for (String uriPath : contentUriPrefixesToTry) {
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse(uriPath), Long.valueOf(id));
String lastPathSagment = uri.getLastPathSegment();
InputStream inputStream = context.getContentResolver().openInputStream(uri);
File file = new File(context.getCacheDir().getAbsolutePath() + "/" + lastPathSagment);
writeFile(inputStream, file);
path = file.getAbsolutePath();
if (path != null) {
return path;
}
}
I had the above issue, but found a solution. I was using ACTION_GET_CONTENT to pick a file from external storage, but it does not work in Android 7 and above. Someone guided me to use ACTION_OPEN_DOCUMENT to pick a file, and now it's working fine for me.
Intent PDF Picker:
if (Build.VERSION.SDK_INT <19) {
Intent pdfIntent = new Intent(Intent.ACTION_GET_CONTENT);
pdfIntent.setType("application/pdf");
startActivityForResult(pdfIntent, PICK_PDF);
} else {
Intent pdfIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
pdfIntent.setType("application/pdf");
pdfIntent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(pdfIntent, PICK_PDF);
}
Code to get File Path:
if (isDownloadsDocument(uri)) {
String fileName = getFilePath(context, uri);
if (fileName != null) {
return String.format("%s/Download/%s", Environment.getExternalStorageDirectory().toString(), fileName);
}
String id = DocumentsContract.getDocumentId(uri);
if (id.startsWith("raw:")) {
id = id.replaceFirst("raw:", "");
File file = new File(id);
if (file.exists())
return id;
}
}
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
Methods used in above code:
public static String getFilePath(Context context, Uri uri) {
Cursor cursor = null;
final String[] projection = { MediaStore.MediaColumns.DISPLAY_NAME };
try {
cursor = context.getContentResolver().query(uri, projection, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME);
return cursor.getString(index);
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
Your code is 'trying' to access that directory to see if it exists, and even open an inputstream to get the supposed File. If the directory doesn't exist Android will be displeased with you and tell you that you're not allowed to access that dir.
No need to request permission as the dir does not exist.
I'm trying to pick file from sd-card or other path which user like to do that, in this my code get file path from uri return null and i can't resolve this problem. I'm using android default file manager to pick file
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_PICK_VIDEO && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
Log.e("", "Video URI= " + getRealPathFromURI(context, uri));
}
}
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = {MediaStore.Images.Media.DATA};
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
It is not necessary for a URI to content a file path with it. But if there is a file path attached with the URI you can draw it using this solution.
Android 5.1.1 lollipop return null file path if image chosen from gallery. The below code works fine in all the devices below 5.1.1, but doesn't work in lollipop 5.1.1
Uri contentUri = data.getData();
Cursor cursor = null;
try {
String[] proj = {MediaStore.Images.Media.DATA};
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
cursor.getString(column_index) this returns null.
For now I have ended up with this for getting an image from gallery. I've tested it on 4.4, 5.0.1 and 5.1.1 but it should work on previous versions too (with new and old Google photo app), should be less hacky and doesn't require a check on Android version.
public static Uri handleImageUri(Uri uri) {
if (uri.getPath().contains("content")) {
Pattern pattern = Pattern.compile("(content://media/.*\\d)");
Matcher matcher = pattern.matcher(uri.getPath());
if (matcher.find())
return Uri.parse(matcher.group(1));
else
throw new IllegalArgumentException("Cannot handle this URI");
}
return uri;
}
And with this I used the same code I have ever used before for getting the image path:
public static String getRealPathFromURI(Context context, Uri uri) {
Cursor cursor = null;
try {
Uri newUri = handleImageUri(uri);
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(newUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} catch (Exception e){
return null;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
For a temporary hack-around for android lollipop 5.1.1. It Works fine now. But m not satisfied with this unofficial hack.
Uri selectedImage = data.getData();
if (Build.VERSION.SDK_INT == 22) {
if (selectedImage != null && selectedImage.toString().length() > 0) {
try {
final String extractUriFrom = selectedImage.toString();
String firstExtraction = extractUriFrom.contains("com.google.android.apps.photos.contentprovider") ? extractUriFrom.split("/1/")[1] : extractUriFrom;
firstExtraction = firstExtraction.contains("/ACTUAL") ? firstExtraction.replace("/ACTUAL", "").toString() : firstExtraction;
String secondExtraction = URLDecoder.decode(firstExtraction, "UTF-8");
selectedImage = Uri.parse(secondExtraction);
} catch (UnsupportedEncodingException e) {
} catch (Exception e) {
}
}
}
I have this code to upload a file to my app, and when the file is opened with a file manager, or dropbox, or anything else, the returned path is correct and I can access it, I am only having problems with Google Drive, it returns some path starting with "exposed_content" and I can't "decode" it any way, I have searched and didn't found a way, anyone have any idea?
if (resultCode == Activity.RESULT_OK) {
if ((data != null) && (data.getData() != null)) {
final Uri filePath;
if (data.getDataString().startsWith("content")) {
filePath = getRealPathFromURI(getApplicationContext(), data.getData());
} else {
filePath = data.getData();
}
// TODO bug with google drive
if (filePath.getLastPathSegment() != null) {
tvSelectedFile.setText("File selected: " + filePath.getLastPathSegment());
} else {
tvSelectedFile.setText("File can not be accessed, please try another way");
}
}
}
Use the attached code... from onActivity result you will get content uri ...pass this uri to the given method...
public static String getGDriveDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_display_name";
final String[] projection = {
column
};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
My Manifest activity code
<activity android:name="FileReceiver" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
My Activity code :
Intent i = getIntent();
String action = i.getAction();
if (action.equals(Intent.ACTION_SEND)) {
Uri imageUri = (Uri) i.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) {
Log.i("1234567", "URI : " + imageUri);
Log.i("123456", "path :" + imageUri.getPath());
File source = null;
source = new File(imageUri.getPath());
String fileNme = "/" + source.getName();
File destination = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + path);
Log.i("123456", "destination path :" + destination);
try {
FileUtils.copyFile(source, destination);
} catch (IOException e) {
Log.i("123456", "IO Exception");
e.printStackTrace();
}
}
im getting exception
01-09 16:10:09.756: W/System.err(30225): java.io.FileNotFoundException: Source 'content:/media/external/images/media/127' does not exist
how do i get the path of the image when i receive an image from DCIM folder ?
/**
* helper to retrieve the path of an image URI
*/
public String getPath(Uri uri) {
// just some safety built in
if( uri == null ) {
// TODO perform some logging or show user feedback
return null;
}
// try to retrieve the image from the media store first
// this will only work for images selected from gallery
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
if( cursor != null ){
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
// this is our fallback here
return uri.getPath();
}
source:
Get/pick an image from Android's built-in Gallery app programmatically
I've got the same problem. Solved it using the following code:
public static String getPathFromURI(Context context, Uri contentUri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
DocumentsContract.isDocumentUri(context, contentUri)) {
return getPathForV19AndUp(context, contentUri);
} else {
return getPathForPreV19(context, contentUri);
}
}
private static String getPathForPreV19(Context context, Uri contentUri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
try {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
return cursor.getString(columnIndex);
} finally {
cursor.close();
}
}
return null;
}
#TargetApi(Build.VERSION_CODES.KITKAT)
private static String getPathForV19AndUp(Context context, Uri contentUri) {
String documentId = DocumentsContract.getDocumentId(contentUri);
String id = documentId.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = context.getContentResolver().
query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[]{ id }, null);
if (cursor != null) {
try {
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
return cursor.getString(columnIndex);
}
} finally {
cursor.close();
}
}
return null;
}