Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android WebView not allowed to load local video file

I have an application with a WebView showing an HTML file. In the HTML file, there's a button that will request the user to record video, or select a video from his documents folder.

Upon selecting (or recording) a video, it calls a javascript function with the link (encoded by Uri) to the video file, which it should then display in a element, by setting it as its source:

function showPreview(previewFile){
    console.log(previewFile);
    document.getElementById('previewVideo').src = previewFile;
}

I'm running into this error and I've been looking around but can't seem to find the solution:

I/chromium﹕ [INFO:CONSOLE(94)] "content://com.android.providers.media.documents/document/video%3A19961", source: file:///android_asset/index.html (94)
W/MediaResourceGetter﹕ permission denied to access network state
W/MediaResourceGetter﹕ non-file URI can't be read due to unsuitable network conditions
E/MediaResourceGetter﹕ Unable to configure metadata extractor

As you can see I'm logging the link to the video file in my javascript function, which as you can tell links to content://com.android.providers.media.documents/document/video%3A19961.

This is how I load the WebView in my code (and there's a corresponding WebView in the XML of course):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    webView = (WebView) this.findViewById(R.id.webView);
    webView.getSettings().setAllowFileAccess(true);
    webView.getSettings().setAllowFileAccessFromFileURLs(true);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.setWebChromeClient(new WebChromeClient());
    webView.addJavascriptInterface(new CSJSInterface(getApplicationContext()), "jsInterface");
    webView.loadUrl("file:///android_asset/index.html");
}

Javascript Interface function & callback

 @JavascriptInterface
 public void showCapture() {
     File imageStorageDir = new File(
             Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
             , CS_MOVIE_DIRECTORY);

     // Create the directory if needed:
     if (!imageStorageDir.exists()) {
         imageStorageDir.mkdirs();
     }

     // Create camera captured image file path and name
     File file = new File(
             imageStorageDir + File.separator + "MOV_"
                     + String.valueOf(System.currentTimeMillis())
                     + ".mp4");
     mCapturedImageURI = Uri.fromFile(file);
     // Camera capture image intent
     final Intent captureIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
     captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
     Intent i = new Intent(Intent.ACTION_GET_CONTENT);
     i.addCategory(Intent.CATEGORY_OPENABLE);
     i.setType("video/*");

     // Create file chooser intent
     Intent chooserIntent = Intent.createChooser(i, "Video Chooser");

     // Set camera intent to file chooser
     chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});

     // On select image call onActivityResult method of activity
     startActivityForResult(chooserIntent, CAMERA_CAPTURE_RESULT);
 }

Call to javascript to link the video file that was selected/recorded:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    LogUtils.log(LogUtils.DEBUG, "onActivityResult called: " + requestCode + " ," + resultCode);

    if (requestCode == CAMERA_CAPTURE_RESULT) {
        // Test if the WebView is loaded:
        if (webView != null) {
            LogUtils.log(LogUtils.DEBUG, "Calling javascript to set preview video.");
            webView.loadUrl("javascript: showPreview('" + Uri.encode(data.getData().toString()) + "');");
        }
    }
}

AndroidManifest.xml

Here's my manifest, as I'm assuming the permissions are likely playing a role

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.tomspee.comingsoon" >

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permissions.READ_EXTERNAL_STORAGE" />

<application
    android:hardwareAccelerated="true"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

like image 537
Fons Avatar asked Sep 30 '22 00:09

Fons


1 Answers

Realize this is old, hit it in my own problem. Thought I'd apply some answers.

first, READ_EXTERNAL_STORAGE is "permission.", not "permissions."

Second, webview apparently needs ACCESS_NETWORK_STATE permission in the manifest as well, as certain types of media playback the streaming system looks at the network status and tries to prefetch metadata for the stream. Add that, MediaResourceGetter errors will go away.

Separately, not related to my problem, I have seen that certain URL structures might work for say webview itself, but not other subsystems. Not sure if content:// is one of those...

hope that helps someone.

like image 68
davebytes Avatar answered Oct 27 '22 12:10

davebytes