0

My goal:

Download a zip file that contains a video and JS file. Create a webview that runs the JS file which (among other things) contains a video tag to play that video file.

Problem: when I try to play the video I get an error saying "Sorry this video cannot be played". In logcat I get: error( 1, -2147483648)

Here is the code to unzip the files:

String path = context.getFilesDir().getPath()+"/";
InputStream is;
ZipInputStream zis;
try {
    is = new FileInputStream(zip file);
    zis = new ZipInputStream( new BufferedInputStream(is));          
    ZipEntry ze = null;
    while ((ze = zis.getNextEntry()) != null) {
        String filename = ze.getName();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int count;

        FileOutputStream fout = 
        _context.openFileOutput( path + filename, Context.MODE_WORLD_READABLE );

    while ((count = zis.read(buffer)) != -1) {
            baos.write(buffer, 0, count);
            baos.toByteArray();
            fout.write(baos.toByteArray());             
            baos.reset();
        }
        fout.close();               
        zis.closeEntry();
        baos.close();
    }
    zis.close();    
}

To show the video I override MraidWebChromeClient.onShowCustomView:

super.onShowCustomView(view, callback);
if (view instanceof FrameLayout) {
  FrameLayout frame = (FrameLayout) view;
  if (frame.getFocusedChild() instanceof VideoView) {
   VideoView video = (VideoView) frame.getFocusedChild();
   frame.removeView(video);
   Activity a = (Activity)getContext();
   a.setContentView(video);
   video.setOnCompletionListener(this);
   video.setOnErrorListener(this);
   video.start();
  }
}  

I do not believe there is an error with the video file, pathing or JS because:

  • The video plays fine if included as a resource in res or streamed with an external http link.
  • when loading the js file I use loadDataWithBaseURL and all other image elements show up fine.
  • I have copied the file from res to the local app folder (using similar code to the unzipping code) and the same error occurs.

I am thinking either:

  • the file is being corrupted while its being unzipped/copied
  • there is a permissions issue for playing a local video from a webview (even after I've set the file to world_readable. (from this link WebView NOT opening android default video player?)

Any insights into this issue would be greatly appreciated!

K

Ps: does anyone know why in the normal web-browser it will download .mp4 links while in other cases it will try and stream them?

EDIT: After researching these two post seem to suggest that Android has security to prevent this: Android - Load video from private folder of app Playing an app local video (.mp4) in a webview Copying files to public external worked fine.

And with regards to the Ps: why some videos stream and some are downloaded, Android 3 doesn't support streaming from https and so will download the file.

Community
  • 1
  • 1
iakiak
  • 109
  • 1
  • 11
  • To narrow down the problem, try putting it on the external storage as a test. That will also let you play the written out file with another app as an additional validity test. – Chris Stratton Jun 28 '12 at 16:16
  • Yup we extracted the files to external storage and that played fine. We think its a Android security issue. – iakiak Jul 05 '12 at 15:40
  • anything of note in logcat when it fails to play from internal storage? – Chris Stratton Jul 05 '12 at 17:46
  • Ahh sorry I left a space for this in the original post but never came back to fill it in. In logcat all I get is: MediaPlayer error( 1, -2147483648) – iakiak Jul 06 '12 at 18:10

1 Answers1

0
  1. Since you're unzipping/reading video to/from the SD card, make sure to add the following line to your manifest file: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

  2. Since you're using JS, make sure to enable it in your WebView as follows:

    private WebView mWebView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            ...
            ...
            mWebView = (WebView) findViewById(R.id.webview);
            mWebView.getSettings().setJavaScriptEnabled(true);
            ...
    }
    
  3. As for video playback, the most reliable solution I've found so far is to hand it off to the native media player app (cause I found the WebView really buggy). In order to achieve this, you need to Bind JavaScript code to Android code so that when the user taps on a video thumbnail, you create the corresponding intent and launch the media player app as follows:

    Intent i = new Intent();
    i.setAction(android.content.Intent.ACTION_VIEW);
    File file = new File(PATH_TO_YOUR_VIDEO);
    i.setDataAndType(Uri.fromFile(file), "video/*");
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    mContext.startActivity(i);
    
  4. [UPDATE] As per the official documentation (see under "Accessing files on external storage"),

"If you're using API Level 8 or greater, use getExternalFilesDir() to open a File that represents the external storage directory where you should save your files".

"If you're using API Level 7 or lower, use getExternalStorageDirectory(), to open a File representing the root of the external storage".

Your unzipping code contains the line String path = context.getFilesDir().getPath(), try to modify it as per the above.

Community
  • 1
  • 1
Andrés Pachon
  • 838
  • 1
  • 7
  • 15
  • Thanks for your suggestions. Unfortunately I have already done points one and two. The code in theory is fine as it is able to play videos if the js gives the video either an external url to stream, or a file uri to an embedded raw resource. It only is unable to play files which I have manually copied or unzipped to local file storage eg: data/data//files – iakiak Jun 29 '12 at 15:05
  • @iakiak : See the update above (point #4). Let me know if that works! :) – Andrés Pachon Jul 02 '12 at 19:14
  • Thanks again for you help. We want to store and play the files from the apps local storage. From these two posts: http://stackoverflow.com/questions/9067468/android-load-video-from-private-folder-of-app and http://stackoverflow.com/questions/7739494/playing-an-app-local-video-mp4-in-a-webview It seems that this is not possible due to security reasons. The video plays fine if the files are copied to external storage as you suggest. – iakiak Jul 05 '12 at 15:36