Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert Video to gallery [Android Q]

To record a SurfeceView I'm using a 3rd-party library , this library requires a path where the output (the recorded video) saved in my case is savedVideoPath :

mRenderPipeline = EZFilter.input(this.effectBmp)
                .addFilter(new Effects().getEffect(VideoMaker.this, i))
                .enableRecord(savedVideoPath, true, false)
                .into(mRenderView);

After the recording stopped, the video should be saved with savedVideoPath as a path, when I test the code, that is to say , when I open the gallery app, I see the saved video there, but when I tested on Android Q, I can't see anything.

Since getExternalStoragePublicDirectory and getExternalStorageDirectory are deprecated ,I tried to use getExternalFilesDir as following :

private void getPath() {
    String videoFileName = "video_" + System.currentTimeMillis() + ".mp4";
    fileName = videoFileName;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        File imageFile = null;
        File storageDir = new File(
            getExternalFilesDir(Environment.DIRECTORY_MOVIES), 
            "Folder");
        source = storageDir;
        boolean success = true;
        if (!storageDir.exists()) {
            success = storageDir.mkdirs();
        }
        if (success) {
            imageFile = new File(storageDir, videoFileName);
            savedVideoPath = imageFile.getAbsolutePath();
        }
    } else {
        File storageDir = new File(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
            + "/Folder");
        boolean success = true;
        if (!storageDir.exists()) {
            success = storageDir.mkdirs();
        }
        if (success) {
            File videoFile = new File(storageDir, videoFileName);
            savedVideoPath = videoFile.getAbsolutePath();
        }
    }
}

After the recording stopped, I go to Files Explorer app > Android > data > com.packageName > files > Movies > Folder ,I can see all saved videos there,but I can't see them on the gallery.

I tried to use Intent.ACTION_MEDIA_SCANNER_SCAN_FILE to refresh the gallery, but unfortunately doesn't work.

I also tried MediaScannerConnection:

MediaScannerConnection.scanFile(
    context, 
    new String[]{savedVideoPath}, 
    new String[]{"video/mp4"}, 
    new MediaScannerConnection.MediaScannerConnectionClient() {

    public void onMediaScannerConnected() {
    }

    public void onScanCompleted(String s, Uri uri) {
    }
});
  • Can anyone help me to get resolve this issue? I stuck on it for almost 2 days
like image 278
Mouaad Abdelghafour AITALI Avatar asked Sep 13 '19 19:09

Mouaad Abdelghafour AITALI


People also ask

How to save YouTube videos to Gallery?

Method 1. Save YouTube Videos to Gallery with an App You can download YouTube videos to the gallery by using some video downloader apps, be computer-based or mobile-based. Each type of app has its pros and cons. Personally, we recommend using computer-based apps. Here are the reasons why you should do that.

How to add a picture to a video in inshot?

Step 1. Open the InShot app and tap on the option that says "Video" to start a video project. Step 2. Tap on "New" and choose the video you want to add a picture to. Step 3. Tap on the "+" (plus) sign at the bottom-left corner and select the option that says "Video/Photo".

How to download YouTube videos and save them into the phone gallery?

2.How to download youtube videos and save them into the phone gallery using Ins Tube. InsTube is one of the best easy, fast and free apps which is used to download youtube video and save into the phone gallery. it is used to download the videos from other sites also. step.1: Install the InsTube app on your Android phone from the InsTube website.

How to add a picture to a video on Android?

Open the YouCut app on your phone, tap on the "+" (plus) sign, and choose your video. Step 2. Tap on the "+" (plus) sign at the lower-left corner, and it will let you select the picture you want to add to your video.


2 Answers

You have to change the library to make it work with Android Q. If you cannot do this you could copy the video to the media gallery and then delete the old video created in getExternalFilesDir(). After this you have the URI of the video and can do what you want with the URI.

If you have saved the video with getExternalFilesDir() you could use my example here: The media URI you get is "uriSavedVideo". This is only an example. A large video should also be copied in the background.

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());
    // get the already saved video as fileinputstream
    // The Directory where your file is saved
    File storageDir = new File(
        getExternalFilesDir(Environment.DIRECTORY_MOVIES), 
        "Folder");
    //Directory and the name of your video file to copy
    File videoFile = new File(storageDir, "Myvideo"); 
    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);
}
like image 56
Frank Avatar answered Sep 20 '22 01:09

Frank


Here it is my solution - save photo/video to Gallery.

private fun saveMediaFile2(filePath: String?, isVideo: Boolean, fileName: String) {
filePath?.let {
    val context = MyApp.applicationContext
    val values = ContentValues().apply {
        val folderName = if (isVideo) {
            Environment.DIRECTORY_MOVIES
        } else {
            Environment.DIRECTORY_PICTURES
        }
        put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
        put(MediaStore.Images.Media.MIME_TYPE, MimeUtils.guessMimeTypeFromExtension(getExtension(fileName)))
        put(MediaStore.Images.Media.RELATIVE_PATH, folderName + "/${context.getString(R.string.app_name)}/")
        put(MediaStore.Images.Media.IS_PENDING, 1)
    }

    val collection = if (isVideo) {
        MediaStore.Video.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    } else {
        MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
    }
    val fileUri = context.contentResolver.insert(collection, values)

    fileUri?.let {
        if (isVideo) {
            context.contentResolver.openFileDescriptor(fileUri, "w").use { descriptor ->
                descriptor?.let {
                    FileOutputStream(descriptor.fileDescriptor).use { out ->
                        val videoFile = File(filePath)
                        FileInputStream(videoFile).use { inputStream ->
                            val buf = ByteArray(8192)
                            while (true) {
                                val sz = inputStream.read(buf)
                                if (sz <= 0) break
                                out.write(buf, 0, sz)
                            }
                        }
                    }
                }
            }
        } else {
            context.contentResolver.openOutputStream(fileUri).use { out ->
                val bmOptions = BitmapFactory.Options()
                val bmp = BitmapFactory.decodeFile(filePath, bmOptions)
                bmp.compress(Bitmap.CompressFormat.JPEG, 90, out)
                bmp.recycle()
            }
        }
        values.clear()
        values.put(if (isVideo) MediaStore.Video.Media.IS_PENDING else MediaStore.Images.Media.IS_PENDING, 0)
        context.contentResolver.update(fileUri, values, null, null)
    }
}
}
like image 33
nAkhmedov Avatar answered Sep 19 '22 01:09

nAkhmedov