This is the current code I have to store videos generated by my app on disk. I want this videos to be accessible by other apps like TikTok, WhatsApp and google Photos. I also want to create my own gallery inside my app. However, the files saved by approach below do not show up on TikTok. They show up under Google photos Library\Movies folder, which users have to really dig deep to find.
How to make these files accessible to all apps? how can I write my own video gallery to just show files created by my app?
private void addVideoToGallery(File videoFile) {
Uri uriSavedVideo;
File createdvideo = null;
ContentResolver resolver = activity.getContentResolver();
String path = videoFile.getAbsolutePath();
String videoFileName = path.substring(path.lastIndexOf("/") + 1);
ContentValues valuesvideos;
valuesvideos = new ContentValues();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
valuesvideos.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES + File.pathSeparator + activity.getString(R.string.app_name));
valuesvideos.put(MediaStore.Video.Media.TITLE, videoFileName);
valuesvideos.put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName);
valuesvideos.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
valuesvideos.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
Uri collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
uriSavedVideo = resolver.insert(collection, valuesvideos);
} else {
String directory = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + Environment.DIRECTORY_MOVIES;
createdvideo = new File(directory, videoFileName);
valuesvideos.put(MediaStore.Video.Media.TITLE, videoFileName);
valuesvideos.put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName);
valuesvideos.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
valuesvideos.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
valuesvideos.put(MediaStore.Video.Media.DATA, createdvideo.getAbsolutePath());
uriSavedVideo = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, valuesvideos);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
valuesvideos.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());
valuesvideos.put(MediaStore.Video.Media.IS_PENDING, 1);
}
ParcelFileDescriptor pfd;
try {
pfd = resolver.openFileDescriptor(uriSavedVideo, "w");
FileOutputStream out = new FileOutputStream(pfd.getFileDescriptor());
FileInputStream in = new FileInputStream(videoFile);
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
in.close();
pfd.close();
} catch (Exception e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
valuesvideos.clear();
valuesvideos.put(MediaStore.Video.Media.IS_PENDING, 0);
resolver.update(uriSavedVideo, valuesvideos, null, null);
}
}
This code cannot access the same files from my app using code below.
private void getVids(){
List<Video> videoList = new ArrayList<Video>();
Uri collection;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
} else {
collection = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}
String[] projection = new String[] {
MediaStore.Video.Media._ID,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.DURATION,
MediaStore.Video.Media.SIZE
};
String selection = MediaStore.Video.Media.DURATION +
" >= ?";
String[] selectionArgs = new String[] {
String.valueOf(TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES))};
String sortOrder = MediaStore.Video.Media.DISPLAY_NAME + " ASC";
try (Cursor cursor = activity.getContentResolver().query(
collection,
projection,
selection,
selectionArgs,
sortOrder
)) {
// Cache column indices.
int idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID);
int nameColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
int durationColumn =
cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION);
int sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);
while (cursor.moveToNext()) {
// Get values of columns for a given video.
long id = cursor.getLong(idColumn);
String name = cursor.getString(nameColumn);
int duration = cursor.getInt(durationColumn);
int size = cursor.getInt(sizeColumn);
Uri contentUri = ContentUris.withAppendedId(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);
// Stores column values and the contentUri in a local object
// that represents the media file.
videoList.add(new Video(contentUri, name, duration, size));
}
}
}
Related
public String getVideoFilePath() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath() + "/" + System.currentTimeMillis() + "compress.mp4";
}
public static void exportMp4ToGallery(Context context, String filePath) {
File file = new File(filePath);
MediaScannerConnection.scanFile(context, new String[]{file.toString()}, null, null);
}
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/>
android:requestLegacyExternalStorage="true"
Currently, I'm using the above approach. getVideoFilePath() will return a path to the compressor class after compression is successful it will call exportMp4ToGallery(Context context, String filePath).
Is it a good approach? or Should I use MediaStore.video. But I want to know how to do the same with mediaStore.Video. Please help if you know, please provide a code snnipet.
EDIT ANOTHER APPROACH IS:
private String getFileName() {
String path = getExternalFilesDir("TrimmedVideo").getPath();
Calendar calender = Calendar.getInstance();
String fileDateTime = calender.get(Calendar.YEAR) + "_" +
calender.get(Calendar.MONTH) + "_" +
calender.get(Calendar.DAY_OF_MONTH) + "_" +
calender.get(Calendar.HOUR_OF_DAY) + "_" +
calender.get(Calendar.MINUTE) + "_" +
calender.get(Calendar.SECOND);
String fName = "trimmed_video_";
File newFile = new File(path + File.separator +
(fName) + fileDateTime + "." + TrimmerUtils.getFileExtension(this, uri));
return String.valueOf(newFile);
}
This above code will give the compressor class a path to save it in app external directory and then copy that file to gallery using MediaStore like below:
public Uri addVideo(String videoFilePath) {
Uri uriSavedVideo;
File createdvideo = null;
ContentResolver resolver = getContentResolver();
String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
ContentValues valuesvideos;
valuesvideos = new ContentValues();
if (Build.VERSION.SDK_INT >= 29) {
valuesvideos.put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/" + "Folder");
valuesvideos.put(MediaStore.Video.Media.TITLE, videoFileName);
valuesvideos.put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName);
valuesvideos.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
valuesvideos.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
Uri collection = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
uriSavedVideo = resolver.insert(collection, valuesvideos);
} else {
String directory = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + Environment.DIRECTORY_MOVIES + "/" + "YourFolder";
createdvideo = new File(directory, videoFileName);
valuesvideos.put(MediaStore.Video.Media.TITLE, videoFileName);
valuesvideos.put(MediaStore.Video.Media.DISPLAY_NAME, videoFileName);
valuesvideos.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
valuesvideos.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
valuesvideos.put(MediaStore.Video.Media.DATA, createdvideo.getAbsolutePath());
uriSavedVideo = getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, valuesvideos);
}
if (Build.VERSION.SDK_INT >= 29) {
valuesvideos.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());
valuesvideos.put(MediaStore.Video.Media.IS_PENDING, 1);
}
ParcelFileDescriptor pfd;
try {
pfd = getContentResolver().openFileDescriptor(uriSavedVideo, "w");
FileOutputStream out = new FileOutputStream(pfd.getFileDescriptor());
File videoFile = new File(videoFilePath);
FileInputStream in = new FileInputStream(videoFile);
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.close();
in.close();
pfd.close();
} catch (Exception e) {
e.printStackTrace();
}
if (Build.VERSION.SDK_INT >= 29) {
valuesvideos.clear();
valuesvideos.put(MediaStore.Video.Media.IS_PENDING, 0);
getContentResolver().update(uriSavedVideo, valuesvideos, null, null);
}
return uriSavedVideo;
}
Good Morning,
I have a problem with MediaStore on Android 11. I have to download .zip file, then open it and get file uri and path.
This is code for saving file and works correctly. I can find the file.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
imageCollection = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "application/zip");
contentValues.put(MediaStore.MediaColumns.SIZE, lengthOfFile);
Uri uri = context.getContentResolver().insert(MediaStore.Files.getContentUri("external"), contentValues);
OutputStream outputStream = context.getContentResolver().openOutputStream(uri);
InputStream input = new BufferedInputStream(url.openStream(), 8192);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress("" + (int) ((total * 100) / lengthOfFile));
outputStream.write(data, 0, count);
}
outputStream.flush();
outputStream.close();
input.close();
}
But I cannot open this file later.
val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Files.getContentUri("external")
} else {
MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
val projection = arrayOf(
MediaStore.Files.FileColumns.RELATIVE_PATH,
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.SIZE,
MediaStore.Files.FileColumns._ID
)
val cursor = requireContext().contentResolver.query(collection, projection, null, null, null)
if (cursor!!.getCount() == 0) {
Log.d(TAG, "No file")
} else {
val idColumn=cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)
val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
val pathColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.RELATIVE_PATH)
while (cursor!!.moveToNext()) {
val id = cursor.getLong(idColumn)
val name = cursor.getString(nameColumn)
val path = cursor.getString(pathColumn)
if (name == "2.1.2.zip") {
val contentUri: Uri = MediaStore.Files.getContentUri("external")
val file= File("content://media/external/file/2.1.2.zip")
if (file.exists()) {
Log.d(TAG, "File not exist")
} else {
Log.d(TAG, "Error")
}
path value return: Download/
name value return: 2.1.2.zip
MediaStore.Files.getContentUri("external"): content://media/external/file
Have any one idea how get access to this file? I try a lot of different way to get file but always get "File not exist".
I use the following code to save a music and select it as alarm music, but it does not work. where is the problem from?
(Files are saved but not selected as ringtone)
holder.btn_alarm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int resId = getMusicId(position, ringTonesDao);
File file = saveMusic(resId);
setForAlarm(file);
}
});
This code receives the music ID in the software.
public int getMusicId(int position, RingTonesDao ringTonesDao) {
long id = ringTonesList.get(position).getId();
String musicAddress = ringTonesDao.checkMusicAddress(id);
int resId = context.getResources().getIdentifier(musicAddress, "raw", context.getPackageName());
return resId;
}
This code, after receiving the music ID, saves it in the internal memory of the mobile and returns the saved file as the output of the method.
public File saveMusic(int resId) {
File dir;
String folderName = "Ringtones";
if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
dir = new File(Environment.getExternalStorageDirectory(), folderName);
} else {
dir = context.getCacheDir();
}
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, resId + ".mp3");
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
try {
InputStream inputStream = context.getResources().openRawResource(resId);
OutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (Exception e) {
Toast.makeText(context, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
return file;
}
This code receives the file and sets it as an alert song.
public void setForAlarm(File file) {
ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
values.put(MediaStore.MediaColumns.TITLE, "alarm" + file.getName());
values.put(MediaStore.MediaColumns.SIZE, file.length());
values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
values.put(MediaStore.Audio.Media.ARTIST, R.string.app_name);
values.put(MediaStore.Audio.Media.DURATION, 230);
values.put(MediaStore.Audio.Media.IS_RINGTONE, false);
values.put(MediaStore.Audio.Media.IS_NOTIFICATION, false);
values.put(MediaStore.Audio.Media.IS_ALARM, true);
values.put(MediaStore.Audio.Media.IS_MUSIC, false);
Uri uri = MediaStore.Audio.Media.getContentUriForPath(file.getAbsolutePath());
Uri newUri = context.getContentResolver().insert(uri, values);
String[] columns = {MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.IS_ALARM
};
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns, MediaStore.Audio.Media.DATA + " = '" + file.getAbsolutePath() + "'", null, null);
if (cursor != null) {
int idColumn = cursor.getColumnIndex(MediaStore.Audio.Media._ID);
int fileColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DATA);
int ringtoneColumn = cursor.getColumnIndex(MediaStore.Audio.Media.IS_ALARM);
while (cursor.moveToNext()) {
String audioFilePath = cursor.getString(fileColumn);
if (cursor.getString(ringtoneColumn) != null && cursor.getString(ringtoneColumn).equals("1")) {
Uri hasUri = MediaStore.Audio.Media.getContentUriForPath(audioFilePath);
newUri = Uri.withAppendedPath(hasUri, cursor.getString(idColumn));
}
}
cursor.close();
}
RingtoneManager.setActualDefaultRingtoneUri(context, RingtoneManager.TYPE_ALARM, newUri);
}
After the restrictions introduced in Android 10 and 11, I am finding it difficult to fetch a video in Internal / External Storage and copy into app specific directory, then use it(Permission Denied Error is thrown). For the image, I implemented the below:
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
Bitmap bm = testObj.getScaledBitmap(bitmap);//used own method
Uri uriimg = testObj.storeImage(internalPath + imageName, bm);//used own method
I am unable to do the same for video.
Could you please provide the code for fetching video using Mediastore api and store in app specific directory or provide mediastore api video fetch example?
I also appreciate very much if i can get scopedstorage usage example using JAVA, because most examples i found are using Kotlin only.
Code:
After file picked on activity result, then check if its video, then
File file = new File(getPath(ProductFlipperActivity.this,uri));
getPath method:
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
Log.i("URI", uri + "");
String result = uri + "";
// DocumentProvider
// if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
if (isKitKat && (result.contains("media.documents"))) {
String[] ary = result.split("/");
int length = ary.length;
String imgary = ary[length - 1];
final String[] dat = imgary.split("%3A");
final String docId = dat[1];
final String type = dat[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[]{
dat[1]
};
return getDataColumn(context, contentUri, selection, selectionArgs);
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
getDataColumn method():
public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {
column
};
try {
if (checkPermissionREAD_EXTERNAL_STORAGE(context)) {
// do your stuff..
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;
}
Get the file name and use storepdf method
String videoName = file.getName();
testObj.storePDF(internalPath + videoName, file);
storepdf method to save file in app specific directory:
//store pdf to sdcard
public Uri storePDF(String path, File file) {
Uri uri = null;
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(file);
String newFileName = path;
out = new FileOutputStream(newFileName);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
return Uri.fromFile(file);
}
After using uri to save file and when i open inputstream to the real file path or uri, both throw error:
File file = new File(String.valueOf(uri));
//File file = new File(getPath(ProductFlipperActivity.this,uri));
String videoName = file.getName();
InputStream in = new FileInputStream(file);
OutputStream out = new FileOutputStream(new File(internalPath + videoName));
// Copy the bits from instream to outstream
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Error Resolved by using the following code suggested by #blackapps:
File file = new File(getPath(ProductFlipperActivity.this,uri));
String videoName = file.getName();
InputStream in = this.getContentResolver().openInputStream(uri);
OutputStream out = this.getContentResolver().openOutputStream((Uri.fromFile(new File(internalPath + videoName))));
// Copy the bits from instream to outstream
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
I am trying to find the full file path for an URI returned from file picker intent. I have downloaded an image from internet which was saved in the browser default download folder. The problem is the id returned by DocumentsContract.getDocumentId(content_describer) is like "msf:254" instead of Long type id generally returned. The code is as following
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 101 && resultCode == Activity.RESULT_OK) {
Uri content_describer = data.getData();
String src = content_describer.getPath();
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());
imgView.setImageBitmap(bitmap);
}catch(Exception e){
}
Log.e("selected file", content_describer.toString());
String filename = content_describer.getLastPathSegment();
Log.e("selected path", filename);
Log.e("authority",content_describer.getAuthority());
if (content_describer.getAuthority().equals("com.android.externalstorage.documents")) {
final String docId = DocumentsContract.getDocumentId(content_describer);
final String[] split = docId.split(":");
final String type = split[0];
Log.e("npath", "getPath() docId: " + docId + ", split: " + split.length + ", type: " + type);
if ("primary".equalsIgnoreCase(type)) {
if (split.length > 1) {
Log.e("nnpath1", Environment.getExternalStorageDirectory() + "/" + split[1]);
curFile = Environment.getExternalStorageDirectory() + "/" + split[1];
} else {
Log.e("nnpath2", Environment.getExternalStorageDirectory() + "/");
}
// This is for checking SD Card
} else {
Log.e("nnpath3", "storage" + "/" + docId.replace(":", "/"));
curFile = "storage" + "/" + docId.replace(":", "/");
}
}
if (content_describer.getAuthority().equals("com.android.providers.downloads.documents")) {
final String docId = DocumentsContract.getDocumentId(content_describer);
Log.e("docid",docId);
Uri ci = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
final String column = "_data";
final String[] projection = {
column
};
Cursor cursor10 = getActivity().getApplicationContext().getContentResolver().query(ci, projection, null, null,
null);
if (cursor10 != null && cursor10.moveToFirst()) {
final int column_index = cursor10.getColumnIndexOrThrow(column);
Log.e("imgpp", cursor10.getString(column_index));
Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
File fn = new File(cursor10.getString(column_index));
Log.e("imgpp3", fn.getPath());
curFile = fn.getPath();
}
}
if (content_describer.getAuthority().equals("com.android.providers.media.documents")) {
final String docId = DocumentsContract.getDocumentId(content_describer);
Log.e("docid", docId);
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]
};
final String column = "_data";
final String[] projection = {
column
};
Cursor cursor1 = getActivity().getApplicationContext().getContentResolver().query(contentUri, projection, selection, selectionArgs,
null);
if (cursor1 != null && cursor1.moveToFirst()) {
final int column_index = cursor1.getColumnIndexOrThrow(column);
Log.e("imgpp", cursor1.getString(column_index));
Log.e("imgpp2", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getPath());
File fn = new File(cursor1.getString(column_index));
Log.e("imgpp3", fn.getPath());
curFile = fn.getPath();
}
}
Log.e("final path",curFile);
}
}
Please note if I pick the same image going via Image->Downwnload, the above code works normally but when same file is picked from Downloads folder, following error is thrown
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.flexi.app.android, PID: 15414
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196709, result=-1, data=Intent { dat=content://com.android.providers.downloads.documents/document/msf:253 flg=0x1 }} to activity {com.flexi.app.android/com.flexi.app.android.ProfileActivity}: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
at android.app.ActivityThread.deliverResults(ActivityThread.java:4830)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4871)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2009)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7319)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
Caused by: java.lang.IllegalArgumentException: Unknown URI: content://downloads/public_downloads/253
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:170)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:140)
at android.content.ContentProviderProxy.query(ContentProviderNative.java:423)
at android.content.ContentResolver.query(ContentResolver.java:934)
at android.content.ContentResolver.query(ContentResolver.java:872)
at android.content.ContentResolver.query(ContentResolver.java:830)
at com.flexi.app.android.fragments.ProfileImageFragment.onActivityResult(ProfileImageFragment.java:171)
at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
at com.flexi.app.android.ProfileActivity.onActivityResult(ProfileActivity.java:28)
at android.app.Activity.dispatchActivityResult(Activity.java:8091)
The URI is reported as content://com.android.providers.downloads.documents/document/msf%3A253
Any idea what is msf? I have seen image, video, audo but noticed msf for first time.
When you get "msf:xxx" in URI, use below solution:
if (id != null && id.startsWith("msf:")) {
final File file = new File(mContext.getCacheDir(), Constant.TEMP_FILE + Objects.requireNonNull(mContext.getContentResolver().getType(imageUri)).split("/")[1]);
try (final InputStream inputStream = mContext.getContentResolver().openInputStream(imageUri); OutputStream output = new FileOutputStream(file)) {
final 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();
return file;
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
I have fixed this issue and it's working 100% for msf. :)
Also Delete the temp file after the completion of your work:
private void deleteTempFile() {
final File[] files = requireContext().getCacheDir().listFiles();
if (files != null) {
for (final File file : files) {
if (file.getName().contains(Constant.TEMP_FILE)) {
file.delete();
}
}
}
}
Here TEMP_FILE value is "temp."
I found the way from comment section. Thanks to #blackapps.
val inputStream = context!!.contentResolver.openInputStream(data.data!!)
val docFile =File("${activity!!.cacheDir}/doc_${sharedPreferences.getString("applno", "")}.pdf")
if (!docFile.exists()) {
docFile.createNewFile()
}
copyStreamToFile(inputStream!!,docFile)
private fun copyStreamToFile(inputStream: InputStream, outputFile: File) {
inputStream.use { input ->
val outputStream = FileOutputStream(outputFile)
outputStream.use { output ->
val buffer = ByteArray(4 * 1024) // buffer size
while (true) {
val byteCount = input.read(buffer)
if (byteCount < 0) break
output.write(buffer, 0, byteCount)
}
output.flush()
}
}
}