Uri = content://com.whatsapp.provider.media/item/118727
I'm not able to get the actual path from this URI
Following the Documentation , i receive the image intent through :
void onCreate (Bundle savedInstanceState) {
...
// Get intent, action and MIME type
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if (type.startsWith("image/")) {
handleSendImage(intent); // Handle single image being sent
}
}
}
ContentResolver wasn't working in this case as "_data" field was returning null. So i found another way to get a file from content URI.
In handleSendImage() you need to open inputStream and then copy it into a file.
void handleSendImage(Intent intent) throws IOException {
Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) {
File file = new File(getCacheDir(), "image");
InputStream inputStream=getContentResolver().openInputStream(imageUri);
try {
OutputStream output = new FileOutputStream(file);
try {
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
} finally {
output.close();
}
} finally {
inputStream.close();
byte[] bytes =getFileFromPath(file);
//Upload Bytes.
}
}
}
getFileFromPath() gets you the bytes which you can upload on your server.
public static byte[] getFileFromPath(File file) {
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
buf.read(bytes, 0, bytes.length);
buf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bytes;
}
You can get imageFilePath from getRealPathFromUri() below:
String filePath = getRealPathFromUri(this, fileUri);
// You can upload it as File
if (filePath != null && !filePath.isEmpty()) {
File file = new File(filePath);
if (file.exists()) {
// Using Retrofit you can do it like
// create Retrofit Client code......
// creates RequestBody instance from file
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
// MultipartBody.Part is used to send also the actual filename
MultipartBody.Part body = MultipartBody.Part.createFormData("file", file.getName(), requestFile);
// pass body as parameter while execute call
}
}
getRealPathFromUri()
public static String getRealPathFromUri(Context context, final Uri uri) {
// DocumentProvider
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
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 index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
private static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
Related
I am New in Android, Working on one functionality in which I have to pick up a file from internal storage and SDCARD. I have implemented some code. With the help of below code, I am able to pick up or select a file from SDcard and internal storage in the Android pie version(9 API level 28) and Android Nougat version(7) but I am not able to get pdf file in from SDCARD in Android Oreo(8 api level 26) version and for Marshmallow it is unable to select file from internal as well as SDCARD. I am not able to figure out what is the problem. Same code working for one not working for another. There is any universal way to access files(pdf and images).Thanks in advance
Implemented Code Below
private void SelectFileFromGallery(){
Intent intent = new Intent();
String[] mimeTypes = {"image/*", "application/pdf"};
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(Intent.createChooser(intent, getString(R.string.select_file)), SELECT_FILE);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == SELECT_FILE) {
onSelectFileFromGalleryResult(data);
isUpdated = true;
} else if (requestCode == 11) {
onBackPressed();
}
}
private void onSelectFileFromGalleryResult(Intent data) {
try {
InputStream is;
Uri selectedImageUri = data.getData();
String file= AndroidUtilities.getFilePath(selectedImageUri);
File imageFile = new File(file);
Log.d("File Path",imageFile.getAbsolutePath());
if (imageFile.exists()) {
// Here I am Compressing the file to store
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getFilePath(final Uri uri) {
String filePath="";
try {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
if (isKitKat && DocumentsContract.isDocumentUri(MyApp.applicationContext, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type=split[0];
String storageDefinition;
// if ("primary".equalsIgnoreCase(type)) {
// return Environment.getExternalStorageDirectory() + "/" + split[1];
// } else {
//
// if(Environment.isExternalStorageRemovable()){
// storageDefinition = "EXTERNAL_STORAGE";
//
// } else{
// storageDefinition = "SECONDARY_STORAGE";
// }
//
// return System.getenv(storageDefinition) + "/" + split[1];
// }
if("primary".equalsIgnoreCase(type)){
if (split.length > 1) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
return Environment.getExternalStorageDirectory() + "/";
}
// This is for checking SD Card
}
else if ("home".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/documents/" + split[1];
}
else {
return "storage" + "/" + docId.replace(":", "/");
}
} else if (isDownloadsDocument(uri)) {
String fileName = getFileName(MyApp.applicationContext, uri);
final String id = DocumentsContract.getDocumentId(uri);
if(fileName!=null){
return Environment.getExternalStorageDirectory().toString()+"/Download/"+fileName;
}
if (id != null && id.startsWith("raw:")) {
return id.substring(4);
}
String[] contentUriPrefixesToTry = new String[]{
"content://downloads/public_downloads",
"content://downloads/my_downloads",
"content://downloads/all_downloads",
};
// final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefixesToTry), Long.valueOf(id));
// return getDataColumn(MyApp.applicationContext, contentUri, null, null);
for (String contentUriPrefix : contentUriPrefixesToTry) {
Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
try {
String path = getDataColumn(MyApp.applicationContext, contentUri, null, null);
if (path != null) {
return path;
}
} catch (Exception e) {}
}
// File cacheDir = getDocumentCacheDir(MyApp.applicationContext);
// File file = generateFileName(fileName, cacheDir);
// String destinationPath = null;
// if (file != null) {
// destinationPath = file.getAbsolutePath();
// saveFileFromUri(MyApp.applicationContext, uri, destinationPath);
// }
// return destinationPath;
} else if (isMediaDocument(uri)||isMediaStorage(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
switch (type) {
case "image":
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
break;
case "video":
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
break;
case "audio":
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
break;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(MyApp.applicationContext, contentUri, selection, selectionArgs);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(MyApp.applicationContext, uri, null, null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
} catch (Exception e) {
Log.e("Exception", e.toString());
}
return null;
}
private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {MediaStore.Images.Media.DATA};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String value = cursor.getString(column_index);
if (value.startsWith("content://") || !value.startsWith("/") && !value.startsWith("file://")) {
return null;
}
return value;
}
} catch (Exception e) {
Log.e("Exception", e.toString());
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
private static boolean isMediaStorage(Uri uri) {
return "com.google.android.apps.docs.storage".equals(uri.getAuthority());
}
I want when choosing non-type files(apk, exe, pdf, ...) with intent chooser then extract data chose the file as a byte array in OnActivityResult I have a lot of searches but I can't do this, please help me.
This is my pick button Code:
private void Pick_Click(object sender, EventArgs e)
{
Intent = new Intent();
Intent.SetType("*/*");
Intent.SetAction(Intent.ActionGetContent);
Intent chooser = Intent.CreateChooser(Intent, "Select Any File");
StartActivityForResult(chooser, 1);
}
Now how can I get the choosed file in OnActivityResult?
I have created a new app and test with pdf and image, it works properly. The main code is as follows:
static readonly int REQUEST_CHOOSER = 0x001;
static readonly int REQUEST_File = 0x002;
Intent intent = new Intent(Intent.ActionGetContent);
intent.SetType("*/*");
intent.AddCategory(Intent.CategoryOpenable);
StartActivityForResult(Intent.CreateChooser(intent, "Select ,Music"), REQUEST_CHOOSER);
method OnActivityResult
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
if (resultCode == Result.Canceled)
{
Finish();
}
else
{
try
{
var _uri = data.Data;
var filePath = IOUtil.getPath(this, _uri);
if (string.IsNullOrEmpty(filePath))
filePath = _uri.Path;
var file = IOUtil.readFile(filePath);// here we can get byte array
}
catch (Exception readEx)
{
System.Diagnostics.Debug.Write(readEx);
}
finally
{
Finish();
}
}
}
IOUtil.cs
public class IOUtil
{
public static string getPath(Context context, Android.Net.Uri uri)
{
bool isKitKat = Build.VERSION.SdkInt >= BuildVersionCodes.Kitkat;
// DocumentProvider
if (isKitKat && DocumentsContract.IsDocumentUri(context, uri))
{
// ExternalStorageProvider
if (isExternalStorageDocument(uri))
{
var docId = DocumentsContract.GetDocumentId(uri);
string[] split = docId.Split(':');
var type = split[0];
if ("primary".Equals(type, StringComparison.OrdinalIgnoreCase))
{
return Android.OS.Environment.ExternalStorageDirectory + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri))
{
string id = DocumentsContract.GetDocumentId(uri);
Android.Net.Uri contentUri = ContentUris.WithAppendedId(
Android.Net.Uri.Parse("content://downloads/public_downloads"), long.Parse(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri))
{
var docId = DocumentsContract.GetDocumentId(uri);
string[] split = docId.Split(':');
var type = split[0];
Android.Net.Uri contentUri = null;
if ("image".Equals(type))
{
contentUri = MediaStore.Images.Media.ExternalContentUri;
}
else if ("video".Equals(type))
{
contentUri = MediaStore.Video.Media.ExternalContentUri;
}
else if ("audio".Equals(type))
{
contentUri = MediaStore.Audio.Media.ExternalContentUri;
}
var selection = "_id=?";
var selectionArgs = new string[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".Equals(uri.Scheme, StringComparison.OrdinalIgnoreCase))
{
return uri.Path;
}
return null;
}
public static string getDataColumn(Context context, Android.Net.Uri uri, string selection,
string[] selectionArgs)
{
ICursor cursor = null;
var column = "_data";
string[] projection = {
column
};
try
{
cursor = context.ContentResolver.Query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.MoveToFirst())
{
int column_index = cursor.GetColumnIndexOrThrow(column);
return cursor.GetString(column_index);
}
}
finally
{
if (cursor != null)
cursor.Close();
}
return null;
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is ExternalStorageProvider.
*/
public static bool isExternalStorageDocument(Android.Net.Uri uri)
{
return "com.android.externalstorage.documents".Equals(uri.Authority);
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is DownloadsProvider.
*/
public static bool isDownloadsDocument(Android.Net.Uri uri)
{
return "com.android.providers.downloads.documents".Equals(uri.Authority);
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is MediaProvider.
*/
public static bool isMediaDocument(Android.Net.Uri uri)
{
return "com.android.providers.media.documents".Equals(uri.Authority);
}
public static byte[] readFile(string file)
{
try
{
return readFile(new File(file));
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
return new byte[0];
}
}
public static byte[] readFile(File file)
{
// Open file
var f = new RandomAccessFile(file, "r");
try
{
// Get and check length
long longlength = f.Length();
var length = (int)longlength;
if (length != longlength)
throw new IOException("Filesize exceeds allowed size");
// Read file and return data
byte[] data = new byte[length];
f.ReadFully(data);
return data;
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
return new byte[0];
}
finally
{
f.Close();
}
}
}
Note: you need to add permission in AndroidManifest file, and add Runtime Permisssion in Android M and above.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I was using below code to get a file path from Uri.
private String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
// Below logic is how External Storage provider build URI for documents
// Based on http://stackoverflow.com/questions/28605278/android-5-sd-card-label and https://gist.github.com/prasad321/9852037
StorageManager mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
try {
Class<?> storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
Method getUuid = storageVolumeClazz.getMethod("getUuid");
Method getState = storageVolumeClazz.getMethod("getState");
Method getPath = storageVolumeClazz.getMethod("getPath");
Method isPrimary = storageVolumeClazz.getMethod("isPrimary");
Method isEmulated = storageVolumeClazz.getMethod("isEmulated");
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);
final boolean mounted = Environment.MEDIA_MOUNTED.equals(getState.invoke(storageVolumeElement))
|| Environment.MEDIA_MOUNTED_READ_ONLY.equals(getState.invoke(storageVolumeElement));
//if the media is not mounted, we need not get the volume details
if (!mounted) continue;
//Primary storage is already handled.
if ((Boolean) isPrimary.invoke(storageVolumeElement) && (Boolean) isEmulated.invoke(storageVolumeElement))
continue;
String uuid = (String) getUuid.invoke(storageVolumeElement);
if (uuid != null && uuid.equals(type)) {
String res = getPath.invoke(storageVolumeElement) + "/" + split[1];
return res;
}
}
} catch (Exception ex) {
}
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
if (!TextUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
}
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
// // Return the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
/**
* Get the value of the data column for this Uri.
*/
private 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;
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is ExternalStorageProvider.
*/
private boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is DownloadsProvider.
*/
private boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is MediaProvider.
*/
private boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
But sometimes getting below exception in Crashlytics-
Fatal Exception: java.lang.IllegalArgumentException: column '_data' does not exist. Available columns: [] at
android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:340)
at
android.database.CursorWrapper.getColumnIndexOrThrow(CursorWrapper.java:87)
at
To resolve this I changed(seeing this) -
private 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;
}
to
private 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);
}
} catch(IllegalArgumentException e) {
getFilePathFromURI(context,uri);
}finally
{
if (cursor != null)
cursor.close();
}
return null;
}
public static String getFilePathFromURI(Context context, Uri contentUri) {
//copy file and send new file path
File moviesDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES
);
boolean success = true;
if (!moviesDir.exists()) {
success = moviesDir.mkdir();
}
if(success) {
String fileName = getFileName(contentUri);
if (!TextUtils.isEmpty(fileName)) {
File copyFile = new File(moviesDir, fileName+".mp4");
copy(context, contentUri, copyFile);
return copyFile.getAbsolutePath();
}
}
return null;
}
public static String getFileName(Uri uri) {
if (uri == null) return null;
String fileName = null;
String path = uri.getPath();
int cut = path.lastIndexOf('/');
if (cut != -1) {
fileName = path.substring(cut + 1);
}
return fileName;
}
public static void copy(Context context, Uri srcUri, File dstFile) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
if (inputStream == null) return;
OutputStream outputStream = new FileOutputStream(dstFile);
IOUtils.copy(inputStream, outputStream);
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
How optimal is this solution?And is there any better way of handling this?
so here is my problem, i need to get a file in phone and then upload it to my parse-server. I've made a file chooser for document, download, external, media folder but android file chooser also propose GoogleDrive option. So i got te Uri but i can't find a way to access that "local copy?".
Do i need to use GoogleDrive SDK to access it? Or can't android just be smart enough and give me methods to handle that Uri ?
I did success getting file name.
content://com.google.android.apps.docs.storage/document/
Here is my file chooser and handler:
public static void pick(final Controller controller) {
final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
chooseFileIntent.setType("application/pdf");
chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
if (chooseFileIntent.resolveActivity(controller.getContext().getPackageManager()) != null) {
controller.startActivityForResult(chooseFileIntent, Configuration.Request.Code.Pdf.Pdf);
}
}
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
private static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
private static boolean isGoogleDriveUri(Uri uri) {
return "com.google.android.apps.docs.storage".equals(uri.getAuthority());
}
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 index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
private static String getPath(Context context, Uri uri) {
if (DocumentsContract.isDocumentUri(context, uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isGoogleDriveUri(uri)) {
// Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
// if (cursor != null) {
// int fileNameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
// cursor.moveToFirst();
// Log.d("=== TAG ===", cursor.getString(fileNameIndex));
// Log.d("=== TAG ===", uri.getPath());
// cursor.close();
// }
} else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
} else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {split[1]};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
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();
}
return null;
}
public static void upload(final Context context, final String name, final ParseObject dataSource, final String field, final Uri uri, final Handler handler) {
if (context != null && name != null && dataSource != null && field != null && uri != null) {
String path = getPath(context, uri);
if (path != null) {
final File file = new File(path);
dataSource.put(field, new ParseFile(file));
dataSource.getParseFile(field).saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
if (handler != null) {
handler.success();
}
}
}
}, new ProgressCallback() {
#Override
public void done(Integer percentDone) {
if (handler != null) {
handler.progress(percentDone);
}
}
});
}
}
}
EDIT :
I've made some try but i got a problem when deleting the temporary file
Here is my code:
public static void copyFile(final Context context, final Uri uri, final ParseObject dataSource, final String field, final String name, final Data.Source target, final Handler handler) {
new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
if (inputStream != null) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int length;
while ((length = inputStream.read(bytes)) != -1) {
byteArrayOutputStream.write(bytes, 0, length);
}
dataSource.put(field, new ParseFile(name, byteArrayOutputStream.toByteArray()));
byteArrayOutputStream.close();
inputStream.close();
return true;
} else {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
dataSource.getParseFile(field).saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
if (handler != null) {
handler.success();
}
}
}
}, new ProgressCallback() {
#Override
public void done(Integer percentDone) {
if (handler != null) {
handler.progress(percentDone);
}
}
});
}
}.execute();
}
Final Edit:
Here my code is correct, temporary file are created and put in cache by Parse himself, so its out of my range. Hope he can help.
So i got te Uri but i can't find a way to access that "local copy?".
There is no "local copy", at least one that you can access.
Or can't android just be smart enough and give me methods to handle that Uri ?
Use ContentResolver and openInputStream() to get an InputStream on the content identified by the Uri. Either use that directly with your "parse-server", or use it to create a temporary "local copy" to a file that you control. Upload that local copy, deleting it when you are done.
Here is my file chooser and handler:
pick() is fine. upload() might be fine; I have not used Parse. The rest of that code is junk, copied from prior junk. It makes many unfounded, unreliable assumptions, and it will not work for Uri values from arbitrary apps (e.g., served via FileProvider).
I tried a solution (see below) that works fine, except in Android 4.4 the call to startActivityForResult() brings up an activity titled "Open from", which has "Recent", "Images", "Downloads" as well as several apps to pick from. When I choose "Images" and try to resolve the returned content URI (using the code below), the call to cursor.getString() returns null. If I choose the exact same file using the Gallery app, cursor.getString() returns a file path. I've only tested this in API levels 16 and 19. Everything works as expected in 16. As far as 19 goes, I have to choose the Gallery or other app or it doesn't work.
private 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();
String path = cursor.getString(column_index);
return path;
} finally {
if (cursor != null) {
cursor.close();
}
}
}
This will get the file path from the MediaProvider, DownloadsProvider, and ExternalStorageProvider, while falling back to the unofficial ContentProvider method you mention.
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.
*
* #param context The context.
* #param uri The Uri to query.
* #author paulburke
*/
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* #param context The context.
* #param uri The Uri to query.
* #param selection (Optional) Filter used in the query.
* #param selectionArgs (Optional) Selection arguments used in the query.
* #return The value of the _data column, which is typically a file path.
*/
public 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;
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
source aFileChooser
Convert content:// URI to actual path in Android 4.4
There is no reliable way to do this on any Android version. A content:// Uri does not have to represent a file on the filesystem, let alone one that you are able to access.
Android 4.4's changes to offer the storage framework simply increases the frequency with which you will encounter content:// Uri values.
If you get a content:// Uri, please consume it using a ContentResolver and methods like openInputStream() and openOutputStream().
I have been facing this problem too, but in my case, what I wanted to do was to specify a concrete Uri to the Gallery so I can use crop later. Looks like in the new Document Browser of KitKat we can't do that anymore unless you choose galery in the navigation drawer, and, like you said, open the image or file directly from there.
In the Uri case, you can still retrieve the path when opening fromt he Document Browser.
Intent dataIntent= new Intent(Intent.ACTION_GET_CONTENT);
dataIntent.setType("image/*"); //Or whatever type you need
And then in onActivityResult:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTIVITY_SELECT_IMAGE && resultCode == RESULT_OK) {
myUri = data.getData();
String path = myUri.getPath();
openPath(myUri);
}
}
If you need then to open a file with that path, you just have yo use a Content Resolver:
public void openPath(Uri uri){
InputStream is = null;
try {
is = getContentResolver().openInputStream(uri);
//Convert your stream to data here
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It is introduced in a Google API. You can try this:
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
If you really need a file path. First, get the data using ContentResolver. Then, you can save the data to a temp file and use that path.
(I had to use a library with File object in a function parameter.)
Thanks to #FireBear, I modified answer now one will get path of media file
String filePath=saveBitmap(activity,getBitmapFromUri(imageUri),"tmpFile").getPath();
private Bitmap getBitmapFromUri(Context context, Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
context.getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
private File saveBitmap(Context context, Bitmap bitmap, String name) {
File filesDir = context.getFilesDir();
File imageFile = new File(filesDir, name + ".jpg");
OutputStream os;
try {
os = new FileOutputStream(imageFile);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
os.flush();
os.close();
} catch (Exception e) {
//Log.e(getClass().getSimpleName(), "Error writing bitmap", e);
}
return imageFile;
}
I know it does not answer the question itself, but as #CommonsWare sad, SAF was not meant to use this way.
Maybe an option for this is creating a copy of the file on the app's external files dir, use it and then delete it.
public File createFileCopy(Context context, DocumentFile file) {
if (file == null || !file.exists() || file.getName() == null) {
throw new IllegalArgumentException("The file must no be null, and must exist, and must have a name.");
}
File fileCopy = new File(context.getExternalFilesDir(null).getAbsolutePath(), file.getName());
try {
android.os.FileUtils.copy(openFileInputStream(file), new FileOutputStream(fileCopy));
return fileCopy;
} catch (Exception e) {
// do whateveer you want with this exceeption
e.printStackTrace();
}
return null;
}
I tried in a different way. each answer on stackoverflow was having some kind of issue, either it leads to some kind of crash or dosen't works out. the first answer above won't work for finding URI from whatsApp media.
below solution is all rounder solution worked for me. I have copied complete PathUtils class here. use getpath() function for the path.
public class PathUtils {
private static final int BUFFER_SIZE = 1024 * 2;
public static String getPath(Context context, Uri contentUri) {
String fileName = getFileName(contentUri);
if (!TextUtils.isEmpty(fileName)) {
File copyFile = new File(context.getCacheDir() + fileName+contentUri.getScheme());
copy(context, contentUri, copyFile);
return copyFile.getAbsolutePath();
}
return null;
}
public static String getFileName(Uri uri) {
if (uri == null) return null;
String fileName = null;
String path = uri.getPath();
int cut = path.lastIndexOf('/');
if (cut != -1) {
fileName = path.substring(cut + 1);
}
return fileName;
}
public static void copy(Context context, Uri srcUri, File dstFile) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
if (inputStream == null) return;
OutputStream outputStream = new FileOutputStream(dstFile);
copyMain(inputStream, outputStream);
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static int copyMain(InputStream input, OutputStream output) throws Exception, IOException {
byte[] buffer = new byte[BUFFER_SIZE];
BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE);
BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
int count = 0, n = 0;
try {
while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
out.write(buffer, 0, n);
count += n;
}
out.flush();
} finally {
try {
out.close();
} catch (IOException e) {
Log.e(e.getMessage(), e.toString());
}
try {
in.close();
} catch (IOException e) {
Log.e(e.getMessage(), e.toString());
}
}
return count;
}
}
Convert content:// URI to actual path in Android.
I have managed this fileUtils Class From a SO answer, and get path from all kinds of Uri:
package com.alquran.tafhimul_quran.Common;
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.util.Log;
import androidx.annotation.RequiresApi;
import java.io.File;
public class UtilsFile {
private final static String PUBLIC_DOWNLOAD_PATH = "content://downloads/public_downloads";
private final static String EXTERNAL_STORAGE_DOCUMENTS_PATH = "com.android.externalstorage.documents";
private final static String DOWNLOAD_DOCUMENTS_PATH = "com.android.providers.downloads.documents";
private final static String MEDIA_DOCUMENTS_PATH = "com.android.providers.media.documents";
private final static String PHOTO_CONTENTS_PATH = "com.google.android.apps.photos.content";
private Boolean isExternalStorageDocument(Uri uri) {
return EXTERNAL_STORAGE_DOCUMENTS_PATH.equals(uri.getAuthority());
}
private Boolean isPublicDocument(Uri uri) {
return PUBLIC_DOWNLOAD_PATH.equals(uri.getAuthority());
}
private Boolean isDownloadsDocument(Uri uri) {
return DOWNLOAD_DOCUMENTS_PATH.equals(uri.getAuthority());
}
private Boolean isMediaDocument(Uri uri) {
return MEDIA_DOCUMENTS_PATH.equals(uri.getAuthority());
}
private Boolean isGooglePhotosUri(Uri uri) {
return MEDIA_DOCUMENTS_PATH.equals(uri.getAuthority());
}
private Boolean isPhotoContentUri(Uri uri) {
return PHOTO_CONTENTS_PATH.equals(uri.getAuthority());
}
private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
//String column = "_data" REMOVED IN FAVOR OF NULL FOR ALL
//String projection = arrayOf(column) REMOVED IN FAVOR OF PROJECTION FOR ALL
try {
cursor = context.getContentResolver().query(uri, null, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndexOrThrow(DocumentsContract.Document.COLUMN_DISPLAY_NAME);
return cursor.getString(columnIndex);
}
} catch (Exception e) {
Log.e("PathUtils", "Error getting uri for cursor to read file: " + e.getMessage());
} finally {
assert cursor != null;
cursor.close();
}
return null;
}
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public String getFullPathFromContentUri(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
String filePath="";
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}//non-primary e.g sd card
else {
if (Build.VERSION.SDK_INT > 20) {
//getExternalMediaDirs() added in API 21
File[] extenal = context.getExternalMediaDirs();
for (File f : extenal) {
filePath = f.getAbsolutePath();
if (filePath.contains(type)) {
int endIndex = filePath.indexOf("Android");
filePath = filePath.substring(0, endIndex) + split[1];
}
}
}else{
filePath = "/storage/" + type + "/" + split[1];
}
return filePath;
}
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
String fileName = getDataColumn(context, uri,null, null);
String uriToReturn = null;
if (fileName != null) {
uriToReturn = Uri.withAppendedPath(
Uri.parse(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()), fileName
).toString();
}
return uriToReturn;
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
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;
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
else if (isPublicDocument(uri)){
String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse(PUBLIC_DOWNLOAD_PATH), Long.parseLong(id));
String[] projection = {MediaStore.Images.Media.DATA};
#SuppressLint("Recycle") Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
}
return null;
}
}
Usage of OnActivityResult:
if (requestCode == PICK_AUDIO_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
UtilsFile utilsFile = new UtilsFile();
String filePath = utilsFile.getFullPathFromContentUri(mContext, uri);
System.out.println("Audio File Path : "+ filePath);
// audioString = audioFileToString(filePath);
}
Get a file path from a Uri:- I had created a Util class that will get the path for Storage Access Framework Documents, as well as the _data field for the MediaStore and other file-based ContentProviders.
ConvertUriToFilePath :-
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.support.annotation.RequiresApi;
public class ConvertUriToFilePath {
/**
* Get a file path from a Uri. This will get the the path for Storage Access
* Framework Documents, as well as the _data field for the MediaStore and
* other file-based ContentProviders.
*
* #param context The context.
* #param uri The Uri to query.
*/
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static String getPathFromURI(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final 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;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{
split[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
// return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* #param context The context.
* #param uri The Uri to query.
* #param selection (Optional) Filter used in the query.
* #param selectionArgs (Optional) Selection arguments used in the query.
* #return The value of the _data column, which is typically a file path.
*/
public 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;
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* #param uri The Uri to check.
* #return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}
Example Code :
// Just call this function of ConvertUriToFilePath class and it will return full path of file URI.
String actualFilepath= ConvertUriToFilePath.getPathFromURI(activity,tempUri);