Android 11 Media store - cannot record new videos on relative path. It works with Environment.DIRECTORY_MOVIES path but not not with sub folder
Asked Answered
A

1

6

My code runs perfect on any Android lower then Android 11. On Android 11 (specifically on Pixel2 & Pixel3 emulator and real devices) the file descriptor fail to find the file after inserting it to the media store.

If I change the relative path on the second line to be only the Environment.DIRECTORY_MOVIES path - it works

String relativeLocation = Environment.DIRECTORY_MOVIES;

This is my code:

String mimeType = "video/mp4";
String relativeLocation = Environment.DIRECTORY_MOVIES + File.separator + SUB_DIRECTORY_NAME ;
shortFileName = getDateStamp() + selectedExtension;
videoContentValues = new ContentValues();
videoContentValues.put(MediaStore.Video.Media.TITLE, shortFileName);
videoContentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, shortFileName);
videoContentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
videoContentValues.put(MediaStore.Video.Media.DATE_ADDED, System.currentTimeMillis() / 1000);
videoContentValues.put(MediaStore.Video.Media.DATE_TAKEN, System.currentTimeMillis());

videoContentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);
videoContentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);
videResolver = mContext.getContentResolver();

Uri contentUri = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
videoUri = videResolver.insert(contentUri, videoContentValues);
if (videoUri == null) {
    throw new IOException("Failed to create new MediaStore record.");
}
pfd = mContext.getContentResolver().openFileDescriptor(videoUri, "w");
mMediaRecorder.setOutputFile(pfd.getFileDescriptor());

The code runs OK until it gets to the openFileDescriptor which return the following error:

java.io.FileNotFoundException: java.io.FileNotFoundException: No item at content://media/external_primary/video/media/47

What am I doing wrong?

Update 1: More info: I am still requesting WRITE_EXTERNAL_STORAGE and making sure it is allowed before start recording

The following code works in the same camera app on Android 11 Pixel 2 emulator to save pics:

    String mimeType = "image/jpeg";
    final String relativeLocation = Environment.DIRECTORY_PICTURES + File.separator + SUB_DIRECTORY_NAME;
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, createImageFileNameQ());
    contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
    contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);
    ContentResolver resolver = mContext.getContentResolver();
    OutputStream stream = null;
    Uri uri = null;
    try {
          final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
          uri = resolver.insert(contentUri, contentValues);
      try {
                OutputStream fos = resolver.openOutputStream(uri);
                fos.write(data);
                fos.flush();
                    fos.close();
           }
     catch (Exception ex) {
        Log.e(TAG, ex.toString());
      }

Update 2:

If I write on the second line "String relativeLocation = Environment.DIRECTORY_PICTURES + File.separator + SUB_DIRECTORY_NAME;" and not DIRECTORY_MOVIES : It works!@!! Video files are saved on Videos\Sub_Directory

Update 3: Now on the emulators:

no trick helps to make relative path. And also the pics cannot be saved to relative path

String mimeType = "image/jpeg"; String relativeLocation = Environment.DIRECTORY_PICTURES + File.separator + SUB_DIRECTORY_NAME;
ContentValues contentValues = new ContentValues();
    
 contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, createImageFileNameQ());
  contentValues.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
  contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, relativeLocation);

  ContentResolver resolver = mContext.getContentResolver();


  OutputStream stream = null;
  Uri uri = null;

  try {
    final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
     uri = resolver.insert(contentUri, contentValues);
 try {
     OutputStream fos = resolver.openOutputStream(uri);
     fos.write(data);
     fos.flush();
     fos.close();
 } catch (Exception ex) {
 Log.e(TAG, ex.toString());
 }
 } catch (Exception e) {}
Actinia answered 13/9, 2020 at 8:5 Comment(20)
In the Constants file - public static final String SUB_DIRECTORY_NAME = "KVRD";Actinia
Uri contentUri = MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY) Try other collections. VOLUME_EXTERNAL?Nakesha
Not running on Emulator. Same error - other collection. java.io.FileNotFoundException: java.io.FileNotFoundException: No item at content://media/external/video/media/48Actinia
Can you, for a test, try to open an InputStream for the obtained videoUri? getContentResolver().openInputStream(videoUri);Nakesha
You mean "InputStream inStream = getContentResolver().openInputStream(videoUri);"? same error - does it help? java.io.FileNotFoundException: java.io.FileNotFoundException: No item at content://media/external/video/media/50Actinia
Sorry! That should have been openOutputStream of course. Try again please.Nakesha
Same "java.io.FileNotFoundException: java.io.FileNotFoundException: No item at content://media/external_primary/video/media/52" the code now for this error is : OutputStream outStream = getContentResolver().openOutputStream(videoUri);Actinia
For descripter and stream same result. Hmmm.. interesting...will try later..Nakesha
Tested on Pixel 3 Emulator API 30 and your code works for me.Nakesha
Thanks for trying. maybe it relates to the latest update because until recently it was working for me. and now not (the latest android studio update came yesterday, for SDK 10.0+(R) which is revision 8). I have checked again now, on Pixel 2 & 3 emulators and a real Pixel 2 - I get this error. it works only when relativeLocation = Environment.DIRECTORY_MOVIES. maybe its a bug the latest android 11 update or maybe a feature to stayActinia
I have added update 2Actinia
It works!@!! Video files are saved on Videos\Sub_Directory ? You mean on Pictures/Sub_Directory i think.Nakesha
I know it sounds weird, but it goes to the Video\sub_directory . double checked it. to prove my case I have uploaded a video that shows it. I will send you the link in private if you wish for, its on youtube but I do not want to be public here in the comments.Actinia
I can try for myself and download latest sdk too. Later...Nakesha
It works perfect with the $ sign. I mean instead of Videos\Sub_Directory - need to put Videos\$Sub_DirectoryActinia
I have opened a ticket to Google/Android with full recording of the emulator debug messages like they asked. they said: "interesting, they will look into it". they did not answer - but they have fixed it for the latest Android 11 release. Security patch Nov. 2020. So - problem was solved.Actinia
they said: "interesting me too.Nakesha
Hi, can anyone confirm that do i need to use $ sign (Music\$Sub_Directory) for DIRECTORY_MUSIC, the DIRECTORY_VIDEO is having that problem, but is the music directory having the same issues?Blake
I had same problem with the picture directory, I do not know about the Music directory since I do not use this media type in my projectsActinia
Is there a way to modify this to get the path/uri for video thumbnails? The new loadThumbnail method doesn't provide an actual URI to the thumbnail.Apparently
A
4

I have opened a ticket to Google/Android with full recording of the emulator debug messages like they asked. they said: "interesting, they will look into it". they did not answer - but they have fixed it for the latest Android 11 release. Security patch Nov. 2020. So - problem was solved. I have left a bug fix in my code in case somebody did not get the last android 11 update. In case of this error - I set IsAndroid11SaveOnSubDirectoryEnabled variable to false

String relativeLocation = Environment.DIRECTORY_MOVIES + File.separator + SUB_DIRECTORY_NAME;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q && IsAndroid11SaveOnSubDirectoryEnabled == false)
{
relativeLocation = Environment.DIRECTORY_MOVIES + File.separator + "$" + SUB_DIRECTORY_NAME;
Log.e(TAG, "Recording on $SubDirectory");
}

Edit II: I got an answer from Google/Android that maybe I have a ".nomedia" file in the directory, and so - the Media store cannot insert/index new files. (.nomedia is a file that tells the gallery not to read the medias on this folder, it applies until Android 10, on Android 11 - this file cannot be created or deleted in the movies folder because it is not media). But it was not correct - the log files and recording that I have sent to Google/Android were from an Android 11 Emulator which did not have this file.

Edit III - Since Dilijeet asked, IsAndroid11SaveOnSubDirectoryEnabled is a boolean that I save to the SharedPreference. here is the code - whenever the recording crash on IOExcpetion & Android 11 - I assume it is the subdirectory problem, and set this boolean for further recordings.

catch (IOException ex)
{

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && IsAndroid11SaveOnSubDirectoryEnabled == true) {
    mSharedPreferences.edit().putBoolean("chkSaveOnSubDirectory", false).apply();
    IsAndroid11SaveOnSubDirectoryEnabled = false;    
}
Actinia answered 6/11, 2020 at 7:23 Comment(5)
I am getting unsupported MIME type in android 11 and it works fine in Android 10.Elodiaelodie
Sorry - that was not the case for me. MIME Type was OK. Adding "$" to the relative location fixed it. And now they fixed also this bug. make sure to update - it was fixed only a week ago. maybe it will helpActinia
@Actinia May i know how do i determine value of this variable "IsAndroid11SaveOnSubDirectoryEnabled" . I have no clue where to find value of this save to sub directory variable, can you help?Blake
It is a simple boolean that I save and extract from the sharedpreferences to know that this problem exists. I have updated my answerActinia
In android 5.1 API 22 device, MediaStore.MediaColumns.RELATIVE_PATH and MediaStore.MediaColumns.IS_PENDING this two value not allow to put in ContentValues. It's force stop the app. Anyone have alternative for this?Monogyny

© 2022 - 2024 — McMap. All rights reserved.