0

I have a file in my raw assets directory which I am trying to save to shared phone storage that will allow other apps to open and view this video.

Basic code to copy file from assets to local storage and generate intent

Intent in = new Intent(Intent.ACTION_VIEW);

// using getFilesDir() below causes this error: 
File videoFile = new File(getExternalFilesDirs(null)[1], "talking.mp4");

// check if we have already copied file over
if (!videoFile.exists()) {

    try {
        InputStream is = getResources().openRawResource(R.raw.talking);
        boolean newFile = videoFile.createNewFile();
        if (!newFile) {
            throw new Exception("Failed to create file");
        }
        OutputStream os = new FileOutputStream(videoFile);
        byte[] data = new byte[is.available()];
        is.read(data);
        os.write(data);
        is.close();
        os.close();
    } catch (IOException e) {
        Log.w("ExternalStorage", "Error writing " + videoFile, e);
        Toast.makeText(this, "Failed to copy talking.mp4", Toast.LENGTH_LONG).show();
        return;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

and getting the file using the FileProvider.getUriForFile(Context, String, File) and creating the intent following this:

Uri uri =  FileProvider.getUriForFile(getApplicationContext(), getPackageName(), videoFile);

// type of file to view
in.setDataAndType(uri, "video/*");

// ask some other app to deal with it
startActivity(in);

in addition, the following is required in my manifest:

<application ... >
    //...
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${getPackageName()}"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/paths" />
    </provider>  
</application>

next, to define the paths mentioned above in the FileProvider:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_files_data" path="." />
    <external-files-path name="my_files_ext_data" path="." />
    <external-path name="my_files_ext" path="." />
</paths>

Question:

When selecting e.g. VLC for Android as the file to handle the intent, the app doesn't play the video. If I try playing it with Google Photos, it loads forever.

This shows my there is something wrong - however I am not quite sure why this isn't working. Is it related to app permissions accessing content root of another app?

CybeX
  • 2,060
  • 3
  • 48
  • 115
  • Try to copy the file to public directory, It may help you to identify whether it's permission issue or code issue – MathankumarK Dec 09 '20 at 10:41
  • Unless the video is very short, `byte[] data = new byte[is.available()]` is going to crash with an `OutOfMemoryError`. I also recommend making `os` be a `FileOutputStream` and doing `os.flush();` and `os.getFD().sync();` before `os.close();`. Have you used Device File Explorer in Android Studio to copy the video off your device and onto your development machine, to ensure that your copy is faithful? – CommonsWare Dec 09 '20 at 12:26
  • @CommonsWare I have tested it on my local machine (copied from the location I copied the resource to), and it plays 100% start to finish. The video is 2min duration with size 3.99Mb. I think I should create an entirely new app that accepts this video intent and see what the problem is... – CybeX Dec 10 '20 at 08:41
  • @CommonsWare this entire ruse is to allow a video file (in raw assets) to be played via an implicit intent w/o using deprecated methods i.e. copying to `Environment.getExternalStorageDirectory()` – CybeX Dec 10 '20 at 08:42

0 Answers0