8

So our app has the option to take either a picture or a video. If the user takes a picture, we can use the MediaStore.Images.Media.insertImage function to add the new image (via a filepath) to the phone's gallery and generate a content:// style URI. Is there a similar process for a captured video, given that we only have it's filepath?

Robert
  • 322
  • 1
  • 3
  • 7
  • Possible duplicate of http://stackoverflow.com/questions/1925502/android-gallery-view-video-also-thumbnail-issues. I posted a response there. – user287989 Mar 07 '10 at 15:10

5 Answers5

12

Here is an easy 'single file based solution':

Whenever you add a file, let MediaStore Content Provider knows about it using

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageAdded)));

Main advantage: work with any mime type supported by MediaStore

Whenever you delete a file, let MediaStore Content Provider knows about it using

getContentResolver().delete(uri, null, null)
Pascal
  • 15,257
  • 2
  • 52
  • 65
  • The question asked about getting the Content style URI. how do you get it? – Sam Nov 13 '14 at 11:47
  • I was looking to scan a video file. Does that make a difference for you? – qix Apr 20 '15 at 09:38
  • @qix Oh.. Well I just tried with images. Will try with Video, but have not the opportunity to test now. – Pascal Apr 20 '15 at 14:11
  • Should file be stored on specific location prior invoking this? – Predrag Manojlovic Jun 28 '16 at 20:40
  • AFAIK files can be located anywhere – Pascal Jun 30 '16 at 08:21
  • "For deletion: just use getContentResolver().delete(uri, null, null)" It's an unsafe approach which leaves the actual media file untouched if you are deleting a media file that is located on your sd-card. In this case only it's media store related information will be removed from media store. – Eftekhari Dec 05 '16 at 01:50
  • @Eftekhari: "for deletion" must be read: "Whenever you delete a file, let MediaStore Content Provider knows about it using". Will make the answer clearer. – Pascal Dec 05 '16 at 09:10
8

I'm also interested, could you find a solution?

Edit: solution is RTFM. Based on the "Content Providers" chapter here is my code that worked:

        // Save the name and description of a video in a ContentValues map.  
        ContentValues values = new ContentValues(2);
        values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
        // values.put(MediaStore.Video.Media.DATA, f.getAbsolutePath()); 

        // Add a new record (identified by uri) without the video, but with the values just set.
        Uri uri = getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);

        // Now get a handle to the file for that record, and save the data into it.
        try {
            InputStream is = new FileInputStream(f);
            OutputStream os = getContentResolver().openOutputStream(uri);
            byte[] buffer = new byte[4096]; // tweaking this number may increase performance
            int len;
            while ((len = is.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }
            os.flush();
            is.close();
            os.close();
        } catch (Exception e) {
            Log.e(TAG, "exception while writing video: ", e);
        } 

        sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
Gabor
  • 7,352
  • 4
  • 35
  • 56
  • Re: The solution posted. Note that Java has BufferedInputStream and BufferedOutputStream so you don't have to do that yourself. –  Apr 30 '10 at 17:44
  • 1
    How about this: http://developer.android.com/reference/android/media/MediaScannerConnection.html – Sam Nov 13 '14 at 14:01
6

If your app is generating a new video and you simply want to give the MediaStore some metadata for it, you can build on this function:

public Uri addVideo(File videoFile) {
    ContentValues values = new ContentValues(3);
    values.put(MediaStore.Video.Media.TITLE, "My video title");
    values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
    values.put(MediaStore.Video.Media.DATA, videoFile.getAbsolutePath());
    return getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
}

EDIT: As of Android 4.4 (KitKat), this method no longer works.

acj
  • 4,821
  • 4
  • 34
  • 49
  • http://stackoverflow.com/questions/2114168/android-mediastore-insertvideo#comment35248961_22373136 – Urboss Apr 14 '14 at 17:44
  • Yes, the entire media storage/provider system was overhauled in 4.4. Anyone targeting 4.4+ should look for a more modern solution. FWIW, I don't think that warrants a downvote on the answers to this years-old question. – acj Apr 14 '14 at 18:15
  • Thanks for your reply and sorry for the downvote but as I spent about 0.5h not going anywhere because of this answer, I thought that it would be good to save fellow Android developers from doing the same. I hope you understand. I don't think that targeting a lower API would make a difference here as rather the Android team would not devote any time to create compatibility measures for an undocumented/unsupported behaviour which just has happen to work earlier. Would removing that answer restore those points from the downvote? If not, I can alternatively remove the downvote before the removal. – Urboss Apr 15 '14 at 14:23
  • 1
    Oh, sending the broadcast worked for me: http://stackoverflow.com/a/14849684/501940 – Urboss Apr 15 '14 at 14:24
  • Good to hear that you found a solution. I've updated the post to mention obsolescence as of 4.4. The answer may be relevant to developers who are targeting earlier builds, though, so I don't think it should be removed. – acj Apr 15 '14 at 14:48
  • I have heard (but not yet confirmed) that this method can be adapted for 4.4+ by adding a `MediaStore.Video.Media.CONTENT_TYPE` value that matches the mime type. – acj Dec 08 '14 at 21:59
  • 1
    Still working even on Android P, I wonder why it's mentioned that it's not going to be working on 4.4+ – Hamzeh Soboh Sep 15 '19 at 04:09
5

I was unable to get the Intent.ACTION_MEDIA_SCANNER_SCAN_FILE broadcast to work for me under API 21 (Lollipop), but the MediaScannerConnection does work, e.g.:

        MediaScannerConnection.scanFile(
                context, new String[] { path }, null,
                new MediaScannerConnection.OnScanCompletedListener() {
                    public void onScanCompleted(String path, Uri uri) {
                        Log.d(TAG, "Finished scanning " + path + " New row: " + uri);
                    }
                } );
qix
  • 7,228
  • 1
  • 55
  • 65
1

Try this code. It seems working for me.

 filePath = myfile.getAbsolutePath();
 ContentValues values = new ContentValues();
 values.put(MediaStore.Video.Media.DATA, filePath);
 return context.getContentResolver().insert(
                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);

Example of filePath -

/storage/emulated/0/DCIM/Camera/VID_20140313_114321.mp4
Ajith M A
  • 3,838
  • 3
  • 32
  • 55
  • 3
    This code returns null, the newest KitKat, Nexus 5. I guess it just works for videos that are already in the Media Store, so it's more like query not insert... VID_20140313_114321 and the path suggests that as it's the standard path and naming for standard camera app when capturing videos. – Urboss Apr 14 '14 at 17:27