4

one of the activities of my Android app contains a WebView that displays the GrooveShark player webpage. When the user taps on the play button of the webpage the activity automatically launches a default MediaPlayer that plays the track. Everything works fine, the problem arises when the user closes this activity and the MediaPlayer, although is not playing the track anymore, it remains alive... even when the app is closed, the MediaPlayer is still alive. The only way to kill it is by forcing the app to stop... I doesn't seem a big deal but in some devices when the user hangs up after a phone call, this "zombie" MediaPlayer all of a sudden starts to play the track even though the app was already previously destroyed...

This is a summary of the code of my Activity:

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

    myWV = (WebView) findViewById(R.id.webview);

    WebSettings webSettings = myWV.getSettings();
    webSettings.setJavaScriptEnabled(true);

    myWV.setWebViewClient(new MyWebViewClient());
    myWV.setWebChromeClient(new WebChromeClient());
    myWV.loadUrl(url);
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    myWV.onPause();
    myWV.pauseTimers();
}

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();
    myWV.onResume();
    myWV.resumeTimers();
}

@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    myWV.destroy();
}

private class MyWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        if (Uri.parse(url).getHost().equals("grooveshark.com")) {
            return false;
        }

       Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        startActivity(intent);

        return true;
    }
}

And this is what the log shows when the track is played for the first time:

 12-03 20:52:13.184: D/webkit(23440): euler: isUrlBlocked = false
 12-03 20:52:13.794: V/MediaPlayer(23440): constructor
 12-03 20:52:13.804: V/MediaPlayer(23440): setListener
 12-03 20:52:13.814: D/HTML5Audio(23440): setDataSource()
 12-03 20:52:13.894: V/MediaPlayer(23440): setVideoSurfaceTexture
 12-03 20:52:13.894: V/MediaPlayer(23440): prepareAsync
 12-03 20:52:16.144: V/MediaPlayer(23440): message received msg=3, ext1=12, ext2=0
 12-03 20:52:16.154: V/MediaPlayer(23440): buffering 12
 12-03 20:52:16.154: V/MediaPlayer(23440): callback application
 12-03 20:52:16.154: V/MediaPlayer(23440): back from callback
 12-03 20:52:16.154: V/MediaPlayer(23440): message received msg=5, ext1=0, ext2=0
 12-03 20:52:16.154: V/MediaPlayer(23440): New video size 0 x 0
 12-03 20:52:16.154: V/MediaPlayer(23440): callback application
 12-03 20:52:16.154: V/MediaPlayer(23440): back from callback
 12-03 20:52:16.154: V/MediaPlayer(23440): message received msg=1, ext1=0, ext2=0
 12-03 20:52:16.154: V/MediaPlayer(23440): prepared
 12-03 20:52:16.154: V/MediaPlayer(23440): callback application
 12-03 20:52:16.154: V/MediaPlayer(23440): back from callback
 12-03 20:52:16.184: E/MediaPlayer(23440): mOnVideoSizeChangedListener is null. Failed to send MEDIA_SET_VIDEO_SIZE message.
 12-03 20:52:16.194: I/MediaPlayer(23440): Don't send intent. msg.arg1 = 0, msg.arg2 = 0
 12-03 20:52:16.194: I/MediaPlayer(23440): mOnPreparedListener. Send MEDIA_PREPARED message.
 12-03 20:52:16.194: D/HTML5Audio(23440): onPrepared()
 12-03 20:52:16.214: V/MediaPlayer(23440): getDuration
 12-03 20:52:16.224: V/MediaPlayer(23440): seekTo 0
 12-03 20:52:16.224: V/MediaPlayer(23440): getDuration
 12-03 20:52:16.224: V/MediaPlayer(23440): message received msg=4, ext1=0, ext2=0
 12-03 20:52:16.224: D/HTML5Audio(23440): play() called. mState = 2
 12-03 20:52:16.224: V/MediaPlayer(23440): Received seek complete
 12-03 20:52:16.224: V/MediaPlayer(23440): All seeks complete - return to regularly      scheduled program
 12-03 20:52:16.224: V/MediaPlayer(23440): callback application
 12-03 20:52:16.224: V/MediaPlayer(23440): back from callback
 12-03 20:52:16.244: V/MediaPlayer(23440): start
 12-03 20:52:16.264: D/HTML5Audio(23440): play() - start()
 12-03 20:52:16.284: I/MediaPlayer(23440): mOnSeekCompleteListener. Send MEDIA_SEEK_COMPLETE message.
 12-03 20:52:16.464: V/MediaPlayer(23440): isPlaying: 1
 12-03 20:52:16.714: V/MediaPlayer(23440): isPlaying: 1
 ....

And finally this is what the log keeps showing forever once the activity has finished

12-03 20:52:36.164: V/MediaPlayer(23440): message received msg=3, ext1=100, ext2=0
12-03 20:52:36.164: V/MediaPlayer(23440): buffering 100
12-03 20:52:36.164: V/MediaPlayer(23440): callback application
12-03 20:52:36.164: V/MediaPlayer(23440): back from callback
12-03 20:52:36.244: V/MediaPlayer(23440): isPlaying: 0
12-03 20:52:36.494: V/MediaPlayer(23440): isPlaying: 0
12-03 20:52:36.744: V/MediaPlayer(23440): isPlaying: 0
12-03 20:52:36.994: V/MediaPlayer(23440): isPlaying: 0
12-03 20:52:37.164: V/MediaPlayer(23440): message received msg=3, ext1=100, ext2=0
12-03 20:52:37.164: V/MediaPlayer(23440): buffering 100
12-03 20:52:37.164: V/MediaPlayer(23440): callback application
12-03 20:52:37.164: V/MediaPlayer(23440): back from callback
12-03 20:52:37.244: V/MediaPlayer(23440): isPlaying: 0
12-03 20:52:37.504: V/MediaPlayer(23440): isPlaying: 0
12-03 20:52:37.754: V/MediaPlayer(23440): isPlaying: 0
12-03 20:52:38.004: V/MediaPlayer(23440): isPlaying: 0
....

I need to find a way to retrieve that "zombie" MediaPlayer and stop it...

Many thanks

Hannibalem
  • 483
  • 5
  • 7
  • 1
    Did you ever find a solution to this issue? I am facing a similar issue with a video inside my webview – Yaniv Efraim Dec 12 '13 at 11:19
  • Nothing man… Nevertheless I tried my app in Xperia and HTC devices and this problem doesn't occur… in those devices the zombie "MediaPlayer Service" dies when the WebView does. It seems to be a bug of some specific Samsung devices (e.g. Samsung Galaxy Trend (4.0.4)) and I don't think is related to the API level… The only way to stop it is by killing the app when you are closing it: Process.killProcess(Process.myPid()); – Hannibalem Dec 12 '13 at 15:20
  • I also tried to retrieve the pid of that MediaPlayer process and kill it with the command I posted before… but nothing, Android doesn't allow me to kill it… really annoying stuff. – Hannibalem Dec 12 '13 at 15:26

1 Answers1

10

After struggling with a similar issue, I finally found a solution. It appears that if the AudioService does not have focus when you close the Webview, it is not paused. This causes severals issues (another player cannot start playing etc.)

The only solution that worked for me is:

@Override
protected void onPause() {
    super.onPause();

    ((AudioManager)getSystemService(
            Context.AUDIO_SERVICE)).requestAudioFocus(
                    new OnAudioFocusChangeListener() {
                        @Override
                        public void onAudioFocusChange(int focusChange) {}
                    }, AudioManager.STREAM_MUSIC, 
                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);

}

This will cause the current player to be paused/killed (not sure which) when going down and solve all of my issues / problems. Hope it could help you too...

Community
  • 1
  • 1
Yaniv Efraim
  • 6,633
  • 7
  • 53
  • 96
  • 2
    Genius man! Your solution doesn't kill the zombie "MediaPlayer" service when one closes the WebView, but at least the device is not behaving weirdly anymore and it doesn't play the song after a call or after playing a youtube video… thanks man! – Hannibalem Dec 13 '13 at 17:02