I'm trying to get any file from an android phone and send it to a server.
This is my code to pick any file from the phone:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
startActivityForResult(intent, RESULT_LOAD_FILE);`
Then, I get all informations of this file on activity result:
String[] proj = {MediaStore.Images.Media.DATA};
CursorLoader loader = new CursorLoader(AttachmentsActivity.this, selectedImageUri, proj, null, null, null);
Cursor cursorPath = loader.loadInBackground();
if (cursorPath != null) {
int column_index = cursorPath.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursorPath.moveToFirst();
mFilePath = cursorPath.getString(column_index);
cursorPath.close();
}
Cursor cursor = getContentResolver().query(selectedImageUri, null, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
Log.i("Ecandidat", "cursor not null");
String displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
String size = "unknown";
if (!cursor.isNull(sizeIndex))
size = cursor.getString(sizeIndex);
if (mFilePath == null) {
mFilePath = selectedImageUri.getPath();
mFilePath = mFilePath.substring(0, mFilePath.lastIndexOf('/') + 1);
mFilePath += displayName;
}
int sizeInt = Integer.parseInt(size);
double sizeFloat = sizeInt;
sizeFloat /= 1048576;
DecimalFormat dff = new DecimalFormat(".##");
size = dff.format(sizeFloat);
if (sizeFloat < 1)
size = "0" + size;
mCurrentAttachment = new Attachment(-1, displayName, selectedImageUri.getPath(), mCommentPieceEditText.getText().toString(), mMode, sizeInt, false);
mAttachmentSizeTextView.setText(size + " MB");
mAttachmentNameTextView.setText(displayName);
findViewById(R.id.attachmentInfosLayout).setVisibility(View.VISIBLE);
findViewById(R.id.attachmentDeleteLayout).setVisibility(View.VISIBLE);
cursor.close();
}
Sorry for this code, I tried many things before posted this message.
So, when i would send the file to the server, i would like create a File from mFilePath string.
And file.exists() returns always false.
This is my code to create a file from the path.
if (mCurrentAttachment == null || mFilePath == null)
return;
File sourceFile = new File(mFilePath);
Log.i("Ecandidat", "upload file: " + mFilePath);
if (!sourceFile.isFile()) {
Toast.makeText(AttachmentsActivity.this, "file doesen't exists", Toast.LENGTH_LONG).show();
Log.e("Ecandidat", "Source File not exist :" + mFilePath);
} else {
Toast.makeText(AttachmentsActivity.this, "file exists", Toast.LENGTH_LONG).show();
}
I don't understand why file.exists returns false because i found this code on many topics and it works many people but don't works for me.
My manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
If anyone has any idea....
Thanks
I get all informations of this file on activity result
At best, that code will work only if you get a Uri from the MediaStore. There are many ways that you will get a Uri that is not from the MediaStore.
i would like create a File from mFilePath string.
A Uri does not necessarily point to a file, let alone one for which you can find a path, let alone one for which you can access.
i found this code on many topics and it works many people
It works for nobody on modern versions of Android.
Use the Uri properly:
Use DocumentFile to get at information such as the size of the content
Use ContentResolver and openInputStream() to get a stream on the content itself
It works when i take a file from the phone but when i take a photo by the camera, file.isFile returns false. Do you know why ?
Uri selectedImageUri = data.getData();
mFile = DocumentFile.fromSingleUri(AttachmentsActivity.this, selectedImageUri);
if (mFile.exists() && mFile.isFile()) {
mCurrentAttachment = new Attachment(-1, mFile.getName(), "", mCommentPieceEditText.getText().toString(), mMode, mFile.length(), false);
mAttachmentSizeTextView.setText(mCurrentAttachment.getSize() + " KB");
mAttachmentNameTextView.setText(mCurrentAttachment.getName());
findViewById(R.id.attachmentInfosLayout).setVisibility(View.VISIBLE);
findViewById(R.id.attachmentDeleteLayout).setVisibility(View.VISIBLE);
}
This is my code. mFile is a DocumentFile.
Thanks
Related
I got a MP4 File (MIME_TYPE = audio/x-m4a) which I can't find quering mediastore.
I don't know if it's a video or an audio file, so I try to query File table of mediastore (also checke video and audio table with same result).
The file is stored in Music/MP4TestFiles Folder on internal storage (not on an SD-Card, not stored in internal app storage).
Testing on Android 13.
Uri uri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
String audiodir = "%MP4TestFiles%";
String[] projection = new String[] {
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns._ID};
String selection = MediaStore.Files.FileColumns.RELATIVE_PATH+ " like ? ";
String[] selectionArgs = new String[] {audiodir};
String sortOrder = MediaStore.Files.FileColumns.DATE_ADDED + " ASC";
Cursor cur = getContentResolver().query(uri, projection, selection, selectionArgs,sortOrder);
if (cur == null) {
Log.e(TAG, "mp4...no file found in Directory: "+audiodir);
} else if (!cur.moveToFirst()) {
Log.e(TAG, "mp4 Failed to move cursor to first row (no query results). 1");
} else {
Log.d(TAG, "mp4 files found")
}
Permission is set in Manifest:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage"/>
If I rename the file into m4b, I got a result.
Any suggestions what's going wrong?
Thanks,
GGK
I developed an app which saves photos inside the app folder (/android/data/[app-folder]/files/Report/[directory]) with some data saved into DESCRIPTION field, here is my code to save image:
ContentValues image = new ContentValues();
image.put(Images.Media.TITLE, directory);
image.put(Images.Media.DISPLAY_NAME, FOTOC_PREFIX_NAME + "_" + directory + "_" + data + ".jpg");
image.put(Images.Media.DESCRIPTION, "EXAMPLE DESC");
image.put(Images.Media.DATE_ADDED, System.currentTimeMillis());
image.put(Images.Media.MIME_TYPE, "image/jpg");
image.put(Images.Media.ORIENTATION, 0);
File parent = imagePath.getParentFile();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
image.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, parent.getAbsolutePath());
}
image.put(Images.ImageColumns.BUCKET_ID, parent.toString().toLowerCase().hashCode());
image.put(Images.ImageColumns.BUCKET_DISPLAY_NAME, parent.getName().toLowerCase());
image.put(Images.Media.SIZE, imagePath.length());
image.put(Images.Media.DATA, imagePath.getAbsolutePath());
Uri result = getContentResolver().insert(MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY), image);
And then i read data with:
String whereCause = MediaStore.Images.Media.DISPLAY_NAME + " LIKE '%" + UsefullThings.getNameWithoutExtension(photofile.getName()) + "%'";
String[] projection = new String[] {MediaStore.Images.Media.DISPLAY_NAME,MediaStore.Images.Media.DESCRIPTION,MediaStore.Images.Media.TITLE,MediaStore.Images.Media._ID};
Cursor cursor = getContentResolver().query(MediaStore.Images.Media
.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY), projection, whereCause, null, MediaStore.Images.Media._ID);
if (cursor.getCount() == 1) {
cursor.moveToFirst();
}
String descstring = "";
try {
descstring =cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DESCRIPTION));
}catch(Exception e){
....
}
where photofile is the image.
Everything is working fine, but if i reboot my tablet then the same query returns empty cursor.
Can anyone help me?
Thanks
app which saves photos inside the app folder (/android/data/[app-folder]/files/Report/[directory])
You mean /storage/emulated/0/Android/data/[app-folder]/files/Report/[directory] ?
That is impossible to begin with if you use the MediaStore.
That is an app specific directory and the MediaStore will not give you insert() uries for that location.
image.put(MediaStore.Images.ImageColumns.RELATIVE_PATH, parent.getAbsolutePath());
You should put a relative path in .RELATIVE_PATH. Not a full absolute path as you do now. Also we cannot see what exactly you put in there. Please tell value of parent.getAbsolutePath().
Hello guys i am trying to get the absolute path of audio file in android api level 29 i.e, Q but the problem is that DATA is deprecated so how to resolve this problem and also using the absolute path (e.x : storage/sdcard/music.mp3) we can get the embedded picture to that audio but in content uri (content://) that we can get using the _ID Column by appending the id of the file.But if we are not able to to get the absolute path then how to play an audio file using content:// Uri ?
The previous codes that i am using is :
public ArrayList<Song> FolderFilesList(Context context, String FolderPath) {
//folder-exclude-sub-folders
ArrayList<Song> songs = new ArrayList<>();
String[] columns = {
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.ALBUM_ID,
MediaStore.Audio.Media.TRACK,
MediaStore.Audio.Media.ARTIST_ID,
MediaStore.Audio.Media.DISPLAY_NAME,
};
String selection = MediaStore.Audio.Media.DATA + " LIKE ? AND " + MediaStore.Audio.Media.DATA + " NOT LIKE ? ";
String[] selectionArgs = new String[]{
"%" + FolderPath + "%",
"%" + FolderPath + "/%/%"
};
Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
columns(), selection, selectionArgs, null);
if (cursor.moveToFirst()) {
do {
Song song = new Song(
cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM)),
cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)),
cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST_ID)),
cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)),
cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.TRACK)),
cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION))
);
//File f = new File(cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA)));
// if (f.isFile() && f.exists()) {
songs.add(song);
//}
} while (cursor.moveToNext());
}
if (cursor != null) {
cursor.close();
}
return songs;
}
You won't be able to get the absolute path now but you can get content uri and using that content uri means (content://) and use it to write file in your cache directory of your package folder using the below code :
String filePath = new File(resolver.openFileDescriptor(contentUri, "r");
And then use InputStream and OutputStream to store it in cache directory and use this filePath to as a File.
Use this line in application in the Manifest file
android:requestLegacyExternalStorage="true"
I recently upgraded the app's target version to API 29. Due to the scoped storage in Android 10, i used MediaStore API to store and retrieve images from app external storage. Earlier, i used getExternalStoragePublicDirectory to store images taken through camera, now i use MediaStore.Images.Media.EXTERNAL_CONTENT_URI to write file to an external storage location.
Issue i am facing now is,
When i open my app and take pictures, it stores under a folder name that i gave 'myapp' and i can retrieve my images through Mediastore cursor and show them in a custom gallery. And when i uninstall my app 'myapp' folder still exists. And when i install my app again and try to read the images from the gallery, cursor is not returning any image. But if i take picture again, then i could load them to my custom gallery. Custom gallery view is just a row of images at the bottom of the screen, so that user doesn't have to browse through the photos folder to load the image to the app.
This is how i store my images in the MediaStore
Content values:
String RELATIVE_PATH = Environment.DIRECTORY_PICTURES + File.separator + "myApp";
final ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, generateImageName(new Date()));
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, RELATIVE_PATH);
Generate Name method:
int sameSecondCount;
protected String generateName(Date now)
{
String result = formatter.format(now);
long nowMillis = now.getTime();
if (nowMillis / 1000 == lastMillis / 1000)
{
sameSecondCount++;
result += "_" + sameSecondCount;
}
else
sameSecondCount = 0;
lastMillis = nowMillis;
return result + PICTURE_EXTENSION_JPG;
}
#WorkerThread
private Uri writePictureToFile(ContentValues contentValues, byte[] bitmapBytes) throws IOException
{
final ContentResolver resolver = getApplication().getContentResolver();
Uri uri = null;
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
try
{
uri = resolver.insert(contentUri, contentValues);
if (uri == null)
throw new IOException("Failed to create new MediaStore record.");
OutputStream stream = resolver.openOutputStream(uri);
if (stream == null)
{
throw new IOException("Failed to get output stream.");
}
stream.write(bitmapBytes);
}
catch (IOException e)
{
// Delete the content from the media store
if (uri != null)
resolver.delete(uri, null, null);
throw e;
}
return uri;
}
Reading images
{
String selectionMimeType = MediaStore.Files.FileColumns.MIME_TYPE + " in (?,?,?)";
String[] args = new String[]{
MimeTypeMap.getSingleton().getMimeTypeFromExtension("jpg"),
MimeTypeMap.getSingleton().getMimeTypeFromExtension("png")};
Cursor cursor = context.getContentResolver()
.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, selectionMimeType, selectionArgs,
orderBy + " DESC");
if (cursor != null)
{
int idColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
imageCursor.moveToFirst();
int imageCount = imageCursor.getCount();
for (int i = 0; i < imageCount && i < totalCount; i++)
{
final long imageId = imageCursor.getLong(idColumnIndex);
Uri uriImage = Uri.withAppendedPath(uriExternal, "" + imageId);
GalleryData galleryImageData = new GalleryImageData(imageId, uriImage); // Custom class with id and Uri
galleryViewModelList.add(galleryImageData);
imageCursor.moveToNext();
}
imageCursor.close();
}
Why the images that i stored in the folder in Mediastore is not being returned by the above code when i reinstall my App. Is it by design or am i missing something?
These are the columns i am retrieving,
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID, MediaStore.Images.Media.MIME_TYPE };
final String orderBy = MediaStore.Images.Media.DATE_TAKEN; ```
For unclear reasons, Android 10 considers two app installations separated by time to be separate apps, no different than if those were two completely different apps.
As a result, once your app is uninstalled, it loses access to all files that it created... even if the same app is later reinstalled.
So, you need to treat files from a previous installation of your app the same way as you would treat files from completely unrelated apps: request READ_EXTERNAL_STORAGE to be able to query for them and read their contents. The "read their contents" part requires android:requestLegacyExternalStorage="true" on the <application> in the manifest.
I've spent hours trying to figure out my problems but I just can't seem to figure out the solution.
I'm trying to delete an image that was saved when I was trying to get it's uri. The image was put in the internal storage.
My code is:
Uri imageUri = getImageUri(this, selectedImage);
File file = new File(imageUri.getPath());
if (!file.exists()) {
Log.i(TAG, "nope");
else{
file.delete();
}
}
public Uri getImageUri(Context Context, Bitmap image) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(Context.getContentResolver(), image, "Title", null);
Log.i(TAG, path);
return Uri.parse(path);
}
However, file.exists() returns false despite the fact that I have just made the image uri. Why is this so?
Update
Thanks to Shinil M S I have found the solution to my problem. However I have one more issue in that whenever I delete the photo, the image is replaced with this other empty image. I have attached the picture as I'm not sure exactly what it is. How do I get rid of it completely so that the image doesn't appear at all? Image mentioned above
Update 2
I have gotten everything to work as intended.
My code is:
public static void deleteUri(Context context, Uri uri){
long mediaId = ContentUris.parseId(uri);
Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Uri itemUri = ContentUris.withAppendedId(contentUri, mediaId);
context.getContentResolver().delete(itemUri, null, null);
}
I used this person's solution: Deleting files via a 'ContentResolver' as opposed to deleting them via 'file.delete()'
try this,
Uri imageUri = getImageUri(this, selectedImage);
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = context.getContentResolver().query(imageUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
cursor.close();
File file = new File(filePath);
if (!file.exists())
Log.i(TAG, "nope");
else
file.delete();