From what I have been able to find out, this seems to be specific to recent Samsung devices. The S4 will do this. The Nexus 7 will not.
If a WebView with a WebChromeClient begins to play an HTML5 video, it creates a MediaPlayer instance. Once the video is over, there doesn't seem to be a way to kill the MediaPlayer short of System.exit(0).
This is my entire MainActivity.java
package com.test.webviewtest;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
public class MainActivity extends Activity {
WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
webView = new WebView(this);
webView.setWebChromeClient(new WebChromeClient());
String html = "<video width=\"320\" height=\"240\" controls autoplay>" +
"<source src=\"http://www.w3schools.com/html/movie.mp4\" " +
"type=\"video/mp4\"></video>";
webView.loadData(html, "text/html", null);
setContentView(webView);
}
@Override
protected void onPause(){
super.onPause();
// attempt to kill the MediaPlayer here...
}
}
And naturally this is required in the manifest
<uses-permission android:name="android.permission.INTERNET"/>
As soon as you click the video, logcat starts spitting out MediaPlayer messages and it NEVER STOPS. There are useful ones while the video is playing but after that, it just logs
02-25 17:13:19.395 220-8584/? V/MediaPlayerService﹕ [470] notify (0x51b7aa00, 3, 100, 0)
02-25 17:13:19.395 8532-8610/? V/MediaPlayer﹕ message received msg=3, ext1=100, ext2=0
02-25 17:13:19.395 8532-8610/? V/MediaPlayer﹕ buffering 100
02-25 17:13:19.395 8532-8610/? V/MediaPlayer﹕ callback application
02-25 17:13:19.405 8532-8610/? V/MediaPlayer﹕ back from callback
02-25 17:13:20.406 220-8584/? V/MediaPlayerService﹕ [470] notify (0x51b7aa00, 3, 100, 0)
02-25 17:13:20.406 8532-8544/? V/MediaPlayer﹕ message received msg=3, ext1=100, ext2=0
02-25 17:13:20.406 8532-8544/? V/MediaPlayer﹕ buffering 100
02-25 17:13:20.406 8532-8544/? V/MediaPlayer﹕ callback application
02-25 17:13:20.406 8532-8544/? V/MediaPlayer﹕ back from callback
02-25 17:13:21.407 220-8584/? V/MediaPlayerService﹕ [470] notify (0x51b7aa00, 3, 100, 0)
02-25 17:13:21.407 8532-8611/? V/MediaPlayer﹕ message received msg=3, ext1=100, ext2=0
02-25 17:13:21.407 8532-8611/? V/MediaPlayer﹕ buffering 100
02-25 17:13:21.407 8532-8611/? V/MediaPlayer﹕ callback application
02-25 17:13:21.417 8532-8611/? V/MediaPlayer﹕ back from callback
And this repetition never ends until you force close or uninstall or something else drastic. I have already tried:
webView.onPause();
This pauses the video so it stops playing in the background, but does not kill the MediaPlayer.webView.destroy();
Still doesn't stop that zombie MediaPlayerwebView = null;
nopewebView = new WebView(this);
still nopefinish();
- I've also tried various ways of getting a hold of the WebChromeClient and destroying it, but nothing works.
I'll update this list as I try more things. Appreciate the help.
- I've now also tried redirecting the webView to non video content with
webView.loadData("hi", "text/html", null);
still alive...
HACKED ANSWER
Well this is the best I can find. If someone has a better solution, please still let me know.
In order to get the MediaPlayer
to stop, I told it to go to page with a <video>
tag that pointed to something other than a video.
String html = "<video width=\"320\" height=\"240\" controls>" +
"<source src=\"http://www.w3schools.com/html/NOT_A_MOVIE.mp4\" " +
"type=\"video/mp4\"></video>";
webView.loadData(html, "text/html", null);
When I do this, I see a video player on screen and when I click the play button, it logs
02-26 12:26:37.112 220-11354/? V/MediaPlayerService﹕ [576] notify (0x47fa92b8, 100, 1, -1004)
02-26 12:26:37.112 11264-11325/com.test.webviewtest V/MediaPlayer﹕ message received msg=100, ext1=1, ext2=-1004
02-26 12:26:37.112 11264-11325/com.test.webviewtest E/MediaPlayer﹕ error (1, -1004)
02-26 12:26:37.112 11264-11325/com.test.webviewtest V/MediaPlayer﹕ callback application
02-26 12:26:37.112 11264-11325/com.test.webviewtest V/MediaPlayer﹕ back from callback
02-26 12:26:37.122 11264-11264/com.test.webviewtest E/MediaPlayer﹕ Error (1,-1004)
From this point on, the MediaPlayer
seems to be mostly dead (only slightly alive). It ceases all logging activity, which is the desired result. The only trace of it remaining is when you force close the app, you will still see this.
02-26 12:29:35.826 220-738/? V/MediaPlayerService﹕ Client(576) destructor pid = 11264
02-26 12:29:35.836 220-738/? V/MediaPlayerService﹕ disconnect(576) from pid 11264
02-26 12:29:35.836 220-738/? W/MediaPlayerService﹕ native_window_api_disconnect returned an error: Broken pipe (-32)
I'm ok with that but a real solution would be nice. I'll obviously wire up the bad video with autoplay so the crash can happen in the background, but that's the framework.
UPDATE 2-27-14 While this 'fixes' the issue on Samsung devices, it does breaks other devices, so this is not a good solution. On other devices (Nexus 7 tested), this code will render the WebView useless to any future calls. I'll update this when I find more information. If you never need to render another WebView for the rest of the app's lifespan, I guess that's ok, but I need it to be able to load another page later.