I have two type of Uris.
type one :
content://media/external/images/media/465
content://media/external/images/media/466
type two :
file:///storage/emulated/0/DCIM/Camera/20151112_185009.jpg
file:///storage/emulated/0/testFolder/20151112_185010.jpg
What is difference and how to convert file uri to content uri?
Because, file uri is just causing error. When I call method :
ContentResolver contentResolver = getContentResolver();
fis = (FileInputStream) contentResolver.openInputStream(fileTypeUri);
how do I fix this?
Try It :)
public static Uri getImageContentUri(Context context, File file) {
String filePath = file.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID },
MediaStore.Images.Media.DATA + "=? ",
new String[] { filePath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (file.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
If you're trying to share data that is stored as part of your app with another app you'll need to use a content:// scheme and not a file:// scheme. This can be accomplished using the FileProvider class found here: https://developer.android.com/reference/android/support/v4/content/FileProvider.html.
By using the FileProvider class you can more precisely and more securely define what files your app can share.
Though be aware that external-cache-path and external-files-path don't work despite what the documentation says. See: how to set FileProvider for file in External Cache dir for more info.
Related
In my app, the user can choose where the created files (text files) are created.
This part is working fine.
But now, I want to open an external "file explorer" app, pointing directly to the chosen folder.
The "file explorer " apps I know accept an absolute path as input (like /storage/emulated/0/Documents/test_folder)
When the user chooses a folder (with Intent.ACTION_OPEN_DOCUMENT_TREE), I get a content uri (like content://com.android.externalstorage.documents/tree/home%3Atest_folder)
Another example with an external sd card:
uri: content://com.android.externalstorage.documents/tree/3877-DB74%3ADocuments%2Ftest_folder
expected path: /storage/3877-DB74/Documents/test_folder
The uri points to a folder, not a file, so I can't use something like openInputStream
I have tried :
File f = new File(uri.getPath());
String path = f.getAbsolutePath();
but it gives: /tree/home:test_folder or /tree/3877-DB74:Documents/test_folder if on sd card
How can I get the real absolute path?
The code I use to call a file explorer:
Intent intent = new Intent(Intent.ACTION_VIEW);
String path = getExternalFilesDir(null).getAbsolutePath();
intent.setDataAndType(Uri.parse(path), "resource/folder");
if (intent.resolveActivityInfo(getPackageManager(), 0) != null)
{
startActivity(intent);
}
so basically you want to get file path from uri
you give try with this code
https://gist.github.com/pratikbutani/eb56f6f9f7013e31d8bfea9effbd4251
I have tried the suggested code (see above).
Unfortunately, I got an exception:
Caused by: java.lang.UnsupportedOperationException: Unsupported Uri content://com.android.externalstorage.documents/tree/home%3Atest_folder
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:167)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:418)
at android.content.ContentResolver.query(ContentResolver.java:760)
at android.content.ContentResolver.query(ContentResolver.java:710)
at android.content.ContentResolver.query(ContentResolver.java:668)
at ....UriUtils.getDataColumn(UriUtils.java:278)
Here is a copy of the code:
private static String getDataColumn(Context context, Uri uri)
{
Cursor cursor = null;
final String column = "_data";
final String[] projection = { column };
try {
cursor = context.getContentResolver().query(uri, projection,
null, null, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
I finally wrote my own method to get the absolute path for a folder from a Uri.
It is surely not fully generic, but it meets my need.
if it can help someone, here is my code:
Note: VOLUME_MAP is a map containing all mounted external volumes
/**************************************************************************/
public static String getRealPathFromContentUri(final Uri uri)
{
if (!isExternalStorageDocument(uri))
{
return null;
}
List<String> segs = uri.getPathSegments();
if (!"tree".equalsIgnoreCase(segs.get(0)))
{
return null;
}
String path = uri.getLastPathSegment();
final String[] split = path.split(":");
final String volumeId = split[0];
String userPath = "";
if (split.length > 1)
{
userPath = "/" + split[1];
}
if ("primary".equalsIgnoreCase(volumeId))
{
return Environment.getExternalStorageDirectory().getAbsolutePath() + userPath;
}
if ("home".equalsIgnoreCase(volumeId))
{
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + userPath;
}
// look for real volumeId
final String volumeName = VOLUME_MAP.get(volumeId);
if (volumeName == null)
{
return null;
}
path = "/storage";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
{
path = Environment.getStorageDirectory().getAbsolutePath();
}
return path + "/" + volumeId + userPath;
}
Thanks to all contributors on this topic.
I am trying to give users an option to set image as wallpaper/whatsapp dp like this.
But I'm stuck with this code
Uri sendUri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.a_day_without_thinking_mobile);
Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
intent.setDataAndType(sendUri, "image/jpg");
intent.putExtra("mimeType", "image/jpg");
startActivity(Intent.createChooser(intent,"Set As"));
It shows a dialog that no apps can perform this action.
I also tried to check my Uri through this method
ContentResolver cr = getContentResolver();
String[] projection = {MediaStore.MediaColumns.DATA};
Cursor cur = cr.query(sendUri, projection, null, null, null);
if (cur != null) {
if (cur.moveToFirst()) {
String filePath = cur.getString(0);
if (new File(filePath).exists()) {
Log.d("URI: ","File path exist");
} else {
Log.d("URI: ","File not found");
}
} else {
Log.d("URI: ","URI ok but no enty found");
}
cur.close();
} else {
Log.d("URI: ","URI was invalid for some other reason");
}
And It always returned that the URI was invalid. But I'm sure that the image is valid jpg and is present in raw folder.
I tried changing URI paths but to no success.
Android file read format has been changed after targetSdkVersion >= 24
You can find the details here;
https://stackoverflow.com/a/38858040/1367450
I'm using the Android's DownloadManager class. It returns Uri with content:// scheme after clicking on the "downloaded file" notification. I have a method which is now only able to open files using file Uris (with "file" scheme). What is the easiest way to get the File file from the content Uri. Any examples are welcome.
public PlsReader(URI path) {
File file = new File(path);
}
Use Context#getContentResolver().openInputStream(uri) to get an InputStream from a Uri.
Or use Context#getContentResolver().openFileDescriptor() to get a ParcelFileDescriptor. Then use ParcelFileDescriptor#getFileDescriptor() to get a FileDescriptor.
try this
1st method to get is below
Uri.getPath();
this will give u whole absolute path of any file
and 2nd method is below
Strinf absolutepath = getRealPathFromURI(this,URI);
and method getRealPathFromURI is here
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();
}
}
}
then pass this absolutepath string to your file like this
public PlsReader(String absolutepath ) {
File file = new File(absolutepath );
}
best of luck dude :)
I'm trying to figure out how to convert an Android Uri to a Java URI. What I'm trying to do is get a File, but as far as I can tell, I need to pass it a Java URI.
Here's my Uri that I'm attempting to convert:
content://media/external/images/media/100
And what I'm attempting to get at:
File mediaFile = new File(new URI("android.net.Uri"));
Where "android.net.Uri" is my Uri object
If there is a different/better way to get a java.io.File object from this content Uri, I'm open to suggestions as I've searched far and wide with no luck so far.
Got it figured out, I was able to get the real filepath of the Uri and then create the File:
Uri uri = Uri.parse("content://media/external/images/media/47");
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cur = managedQuery(uri, projection, null, null, null);
cur.moveToFirst();
String path = cur.getString(cur.getColumnIndex(MediaStore.Images.Media.DATA));
mediaFile = new File(path);
I'm using the follow code to take a picture using the native camera:
private File mImageFile;
private String mTempImagePath;
public static Uri imageUri;
public void imageFromCamera() {
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
Log.d("fototemp", "No SDCARD");
} else {
mImageFile = new File(Environment.getExternalStorageDirectory()+File.separator+"testFolder", "Pic"+System.currentTimeMillis()+".jpg");
imageUri = Uri.fromFile(mImageFile);
DataClass dc = (DataClass) getApplicationContext();
File tempFile = new File(Environment.getExternalStorageDirectory()+File.separator+"testFolder");
Uri tempUri = Uri.fromFile(tempFile);
dc.setString(DataClass.IMAGE_PATH, tempUri.toString());
Log.d("fototemp", "ImagePath: " + tempUri.toString());
mTempImagePath = mImageFile.getAbsolutePath();
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mImageFile));
startActivityForResult(intent, 0);
}
}
The ImagePath I print out in the imageFromCamera() method is: 4file:///file%3A/mnt/sdcard/testFolder
Now when I try to access these foto's by using managedQuery I get a different directory.
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI.toString() gives content://media/external/images/thumbnails
What is the difference between these 2 paths? And how can I get the managedQuery to go to the testFolder map to look for pictures?
edit:
I'm trying to connect:
Uri phoneUriII = Uri.parse(Environment.getExternalStorageDirectory()+File.separator+"testFolder");
imagecursor = managedQuery(phoneUriII, img, null,null, MediaStore.Images.Thumbnails.IMAGE_ID + "");
but this code crashes
Sorry don't really understand your question.
Just send this as the URI path.
Environment.getExternalStorageDirectory()+File.separator+"testFolder"
Also
Check if you have the permissions to write to the sd card.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
I'm using this function in a couple of projects and it works fine.
/**
* Retrieves physical path to the image from content Uri
* #param contentUri
* #return
*/
private String getRealImagePathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = managedQuery(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}