MediaController is not shown after onResume() - android

This is my activity for a video player:
public class myActivity extends Activity
implements MediaPlayer.OnPreparedListener,
MediaController.MediaPlayerControl {
....
}
and in its onPause method I don't release the MediaPlayer and I just pause it:
#Override
protected void onPause() {
super.onPause();
lastPlaybackInfo.IsPlaying = mMediaPlayer.isPlaying();
mMediaPlayer.pause();
lastPlaybackInfo.SeekPosition = mMediaPlayer.getCurrentPosition();
}
and in onResume
#Override
protected void onResume() {
super.onResume();
if (mMediaPlayer != null) {
if (lastPlaybackInfo.IsPlaying) {
mMediaPlayer.start();
} else {
mMediaPlayer.seekTo(lastPlaybackInfo.SeekPosition);
}
mMediaController.show();
}
}
and the onTouchEvent:
#Override
public boolean onTouchEvent(MotionEvent event) {
mMediaController.show();
return true;
}
I have two problems:
The first problem is that the once the app is resumed, the MediaController which is tied to MediaPlayer is shown only one time (the call in onResume), and after that, the calls in onTouchEvent doesn't show MediaController.
The second one is that, if MediaPlayer was paused before app getting paused, after resuming the app, the SurfaceView tied to MediaPlayer is black and doesn't show the very last rendered frame.

In fact I found out if we run the code inside onResume with a delay to let the layout refresh itself, both of the problems would get resolved.
Here's how:
protected void onResume() {
super.onResume();
try {
if (IsMediaReady && IsSubtitleReady) {
if (mMediaPlayer != null) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (lastPlaybackInfo.IsPlaying) {
mMediaPlayer.start();
} else {
mMediaPlayer.seekTo(lastPlaybackInfo.SeekPosition);
}
mMediaController.show();
}
}, 100);
}
}
} catch (NullPointerException e) {
Log.e(TAG, "Exception in resume");
}
}

Related

When I return to the previous page MediaPlayer continues playing

I tried all these and still the media player continues playing when I press the back button and return to the previous activity
oncreate ........ new Handler().postDelayed(new Runnable() {
#Override
public void run() {
int newInt = sharedPreferences.getInt("B" , DEFALT );
if (newInt == DEFALT) {
releaseMediaPlayer();
mediaPlayer = MediaPlayer.create(AlsamadSuraST3.this, wordsResourceArray[0][0]);
if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(mCompletionListener);
editor.putInt("B" , DEFALT + 5 );
editor.apply();;
}
}
#Override
protected void onPause() {
super.onPause();
releaseMediaPlayer();
}
#Override
protected void onStop() {
super.onStop();
releaseMediaPlayer();
}
#Override
protected void onStart() {
super.onStart();
releaseMediaPlayer();
}
#Override
public void onBackPressed() {
super.onBackPressed();
releaseMediaPlayer();
}
#Override
protected void onRestart() {
super.onRestart();
releaseMediaPlayer();
}
private void releaseMediaPlayer() {
if (mediaPlayer != null) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.release();
mediaPlayer = null;
mAudioManager.abandonAudioFocus(mOnAudioFocusChangeListener);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
}
How can I stop the media player when i return to the previous activity >> there are many answers included onpause , onstop ondestroy but none of them worked

Keep radio playing in background

hi i'm trying to create a simple Online Radio i want to keep radio playing in bakcground and i know i should use Service but i don't how to use it please help me to make my app radio keep playing in background
this my code :
Button b_play ;
MediaPlayer mediaPlayer ;
boolean prepared = false;
boolean started = false;
String stream = "http://stream.radio.co/s98f81d47e/listen";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b_play = (Button)findViewById(R.id.b_play);
b_play.setEnabled(false);
b_play.setText("Loading");
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
new PlayerTask().execute(stream);
b_play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(started){
started = false;
mediaPlayer.pause();
b_play.setText("Play");
}else{
started = true;
mediaPlayer.start();
b_play.setText("Pause");
}
}
});
}
class PlayerTask extends AsyncTask<String, Void ,Boolean>{
#Override
protected Boolean doInBackground(String... strings) {
try {
mediaPlayer.setDataSource(strings[0]);
mediaPlayer.prepare();
prepared = true;
} catch (IOException e) {
e.printStackTrace();
}
return prepared;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
b_play.setEnabled(true);
b_play.setText("Play");
}
}
#Override
protected void onPause() {
super.onPause();
if(started){
mediaPlayer.pause();
}
}
#Override
protected void onResume() {
super.onResume();
if(started){
mediaPlayer.start();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if(prepared){
mediaPlayer.release();
}
}
}
Play the music from the foreground service.
Official Android documentation says:
that is a service that the user is actively aware of and is not a
candidate for the system to kill when low on memory. A foreground
service must provide a notification for the status bar, which is
placed under the Ongoing heading. This means that the notification
cannot be dismissed unless the service is either stopped or removed
from the foreground.
In your case a radio that plays music from a service should be set to run in the foreground, because the user is explicitly aware of its operation. The notification in the status bar might indicate the current song and allow the user to launch an activity to interact with the music player.
Here is an example

SurfaceView goes black -- MediaPlayer Android

I am using MediaPlayer and SurfaceView to stream a video from a server. The video plays fine however if the activity goes in "Paused" state, eg. when the user taps home button or recent button, On resuming the player activity the SurfaceView becomes black. I know when you leave the activity, the surfaceView is destroyed and upon resuming it is created again, so as workaround I saved the player's current position in onPause() of the activity and when the activity resumes, I seek the player to that position. This didn't work either.
So my question is how can I make the surfaceView keep the frame/picture it was displaying when the user goes out of the activity?
public class VideoPlayer extends Activity implements SurfaceHolder.Callback, OnPreparedListener {
private long PREV_PLAYER_POS;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_videoplayer);
mDecorView = getWindow().getDecorView();
mediaController = new VideoControllerView(this, mDecorView);
handler = new Handler();
Intent intent = getIntent();
usedURL = intent.getExtras().getString("vidURL");
vidID = intent.getExtras().getString("id");
mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
mProgressBar.setVisibility(ProgressBar.VISIBLE);
mContext = this;
surfView = (SurfaceView) findViewById(R.id.videoView4);
SurfaceHolder holder = surfView.getHolder();
holder.addCallback(this);
mMediaPlayer = new MediaPlayer();
mMediaPlayerControl = new VideoControllerView.MediaPlayerControl() {
……
}
mMediaPlayer.setOnPreparedListener(this);
mediaController.setOnSeekStartListener(new onSeekStartListener() {
#Override
public void onSeekStarted() {
}
});
mediaController.setMediaPlayer(mMediaPlayerControl);
mediaController.setAnchorView((ViewGroup) findViewById(R.id.container4));
mediaController.setEnabled(true);
mediaController.show();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mMediaPlayer.setDisplay(holder);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mMediaPlayer.setDisplay(holder);
try {
mMediaPlayer.setDataSource(usedURL);
mMediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void onPrepared(MediaPlayer mp) {
surfView.requestLayout();
surfView.invalidate();
mMediaPlayer.start();
}
#Override
public void onSurfaceViewSizeChanged(int width, int height) {
}
#Override
protected void onResume() {
super.onResume();
mMediaPlayer.seekTo((int)PREV_PLAYER_POS);
}
#Override
public void onBackPressed() {
super.onBackPressed();
mMediaPlayer.stop();
}
#Override
protected void onPause() {
super.onPause();
PREV_PLAYER_POS = mMediaPlayer.getCurrentPosition();
mMediaPlayer.pause();
}
#Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.release();
mMediaPlayer = null;
}
}
Best Regards
Start your video in onResume,
#Override
protected void onResume() {
super.onResume();
mMediaPlayer.start();
mMediaPlayer.seekTo(length);
}
Hope it ll work..
The SurfaceView's surface may or may not be destroyed when you bring something up in front of the activity. See this section in the graphics architecture document for an overview. If it didn't get destroyed, then surfaceCreated() won't be called again, and your app will never call mMediaPlayer.setDisplay(holder) to connect the MediaPlayer to the surface.
I would guess that, if you brought up "recents" and then rotated the device, things would work when you returned (because the device rotation forces the surface to be recreated). You may want to add some logging to the various callbacks to see when they fire.
You will need to have a static variable that tracks whether or not the surface has been destroyed (e.g. static bool haveSurface = false, set to true in surfaceCreated(), false in surfaceDestroyed(). If it's true in onCreate(), call mMediaPlayer.setDisplay(holder) immediately.
Grafika has some examples of working with the odd SurfaceView-vs-Activity lifecycle issues, though I don't think any of them quite fit your use case.

Android app crashes when calling MediaController.show() - Unable to add window -- token null is not valid

I'm creating a music streaming app. As per android's MediaPlayer guide, I'm controlling the MediaPlayer from a Service. This all works fine and now I'm trying to add a MediaController to control playback. To do so, I'm having my Service implement MediaController.MediaPlayerControl, and having my Activity bind to my Service, and then instantiating the MediaController from the Activity with the Service context from the ServiceConnection.
Player.java
public class Player extends Activity implements OnClickListener, OnItemClickListener, MediaController.MediaPlayerControl {
private MediaController mediaController;
private ServiceConnection mConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
showMediaController();
}
#Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
startService(
new Intent(this, PlayerService.class)
.setAction("com.limastreamer.action.NEXTSHOW"));
bindService(
new Intent(this, PlayerService.class),
mConnection,
Context.BIND_AUTO_CREATE);
}
public void showMediaController() {
if (mBound) {
mediaController = new MediaController(this);
mediaController.setAnchorView(
findViewById(R.id.player)
);
mediaController.setMediaPlayer(mService);
mediaController.setEnabled(true);
mediaController.show(0);
}
}
}
PlayerService.java
public class PlayerService extends Service implements MediaController.MediaPlayerControl {
private MediaPlayer mMediaPlayer;
public class LocalBinder extends Binder {
PlayerService getService() {
return PlayerService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
String action = intent.getAction();
if (action.equals("com.limastreamer.action.NEXTSHOW")) {
if (mMediaPlayer == null)
{
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setLooping(false);
}
try
{
mMediaPlayer.reset();
mMediaPlayer.setDataSource(url);
mMediaPlayer.prepareAsync(); // prepare async to not block main thread
}
catch (Exception ex)
{
Toast.makeText(getApplicationContext(), "Failed to prepare MediaPlayer", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getBufferPercentage() {
return 0;
}
#Override
public int getCurrentPosition() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying())
return mMediaPlayer.getCurrentPosition();
else
return 0;
}
#Override
public int getDuration() {
if (mMediaPlayer != null && mMediaPlayer.isPlaying())
return mMediaPlayer.getDuration();
else
return 0;
}
#Override
public boolean isPlaying() {
if (mMediaPlayer != null)
return mMediaPlayer.isPlaying();
else
return false;
}
#Override
public void pause() {
if (mMediaPlayer != null)
mMediaPlayer.pause();
}
#Override
public void seekTo(int msec) {
if (mMediaPlayer != null)
mMediaPlayer.seekTo(msec);
}
#Override
public void start() {
if (mMediaPlayer != null)
mMediaPlayer.start();
}
}
R.id.player refers to the root element of my xml layout.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/player"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".Player" >
On calling mediaController.show(); the app bombs out with the exception: Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
From looking at other questions on SO (for example), it seems that this is caused by using the wrong context here: mediaController = new MediaController(this);, ie using something other than the Activity context. But as far as I can tell, I am using the Activity context.
I've tried:
Using other views in the layout as the anchor view (even tho the doc says you can use the Activity's main view)
Putting the MediaController in a fragment, and using getActivity() as the context, as shown here
Putting the MediaController in the xml layout instead of instantiating it programatically.
Setting a VideoView as the anchor view (some people say it only works with a VideoView).
Creating a new class that extends VideoView and implements MediaPlayerControl, and instantiating the MediaController in that class, using the saved context that was passed to the class when it was initialized as the context, and this as the anchor view.
Your activity should implement MediaPlayer.OnPreparedListener and set onPreparedListener of mediaPlayer of your service to the player activity.
public class MyMediaPlayer extends Activity implements
MediaController.MediaPlayerControl,MediaPlayer.OnPreparedListener {
...
public void onCreate(Bundle savedInstanceState) {
...
//this mediaPlayer is the reference of your media player inside your service
mediaPlayer.setOnPreparedListener(this);
...
}
...
}
also you have to start your service a little after you created your activity
Intent in=new Intent(MainPlayer.this,MyMediaPlayer.class);
startActivity(in);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//START YOUR SERVICE TO PREPARE YOUR PLAYER
this works for me.

Getting Error in Media Player: SeekTo in wrong state: & start called in state 0

i am facing some issue in media player when i use as service.
1. If i initialize Media Player Object in Activity as static and further use in service class then its show me this error (-38, 0) , Attempt to perform seekTo in wrong state: mPlayer=0x0, mCurrentState=0 , start called in state 0.
2. If i initialize Media Player Object in Service class and user in activity for more
action its show's me Null Pointer.
public static MediaPlayer mPlayer = null;
play Click Event
Audio_Player_Play.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
if (mPlayer == null)
{
Intent Play_Intent = new Intent(RDS_Singel_Audio.this,
Audio_Player.class);
startService(Play_Intent);
Audio_Player_Play.setVisibility(View.GONE);
Audio_Player_Pause.setVisibility(View.VISIBLE);
} else
{
// Play_Streaming();
mPlayer.seekTo(mPlayer.getCurrentPosition());
mPlayer.start();
Audio_Player_Play.setVisibility(View.GONE);
Audio_Player_Pause.setVisibility(View.VISIBLE);
}
}
});
Pause Click Event
Audio_Player_Pause.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
// TODO Auto-generated method stub
// Play_Streaming();
// checking is medai player running
Audio_Player_Play.setVisibility(View.VISIBLE);
Audio_Player_Pause.setVisibility(View.GONE);
// checking is audio playing in background
if (mPlayer != null && mPlayer.isPlaying())
{
mPlayer.pause();
/*
* Intent Pause_Intent = new Intent(RDS_Singel_Audio.this,
* Audio_Player.class); stopService(Pause_Intent);
*/
Audio_Player_Play.setVisibility(View.VISIBLE);
Audio_Player_Pause.setVisibility(View.GONE);
}
}
});
OnResume() - OnPause() -OnDistroy()
#Override
protected void onResume()
{
super.onResume();
}
#Override
protected void onPause()
{
// cleanUp();
if (mPlayer != null && mPlayer.isPlaying())
{
mPlayer.release();
mPlayer = null;
}
super.onPause();
}
#Override
protected void onDestroy()
{
cleanUp();
super.onDestroy();
}
private void cleanUp()
{
if (mPlayer != null)
{
mVisualizerView.release();
mPlayer.release();
mPlayer = null;
}
}
Service.Java
public class Audio_Player extends Service
{
private static final String TAG = "MyService";
// public static MediaPlayer mPlayer;
Function f;
RDS_Singel_Audio sa;
MediaPlayer mPlayer;
#Override
public IBinder onBind(Intent intent)
{
return null;
}
#Override
public void onCreate()
{
try
{
sa = new RDS_Singel_Audio();
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG)
.show();
sa.mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
sa.mPlayer.setDataSource(sa.Audio_URL);
sa.mPlayer.prepare();// might take long! (for buffering, etc)
sa.mVisualizerView.link(sa.mPlayer);
sa.mPlayer.start();
sa.addLineRenderer();
sa.mPlayer.setLooping(false); // Set looping
// sa.mPlayer.start();
} catch (Exception e)
{
// TODO: handle exception
Log.d(TAG, "" + e);
}
}
#Override
public void onDestroy()
{
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
super.onDestroy();
if (sa.mPlayer != null)
{
sa.mPlayer.stop();
sa.mPlayer.release();
}
sa.mPlayer = null;
}
#Override
public void onStart(Intent intent, int startid)
{
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
// mPlayer.setDataSource("http://clients.ncrypted.net/riddimapp/images/audio/4/df9919ccb2880933c795f43d735cf9bc.mp3");
}
}
I found some link about same issue but I don't know how solve it.
Well, I see this part of your code, but it is not clear what you are trying to achieve. You are trying to make the player go to its current position, but it is already at that position? You could remove that part then.
// Play_Streaming();
mPlayer.seekTo(mPlayer.getCurrentPosition());
Also, on your onpause you're releasing the player, but not generating it again on your onresume. You can recreate it there with code from that link you provided:
#Override
protected void onResume()
{
super.onResume();
}
#Override
protected void onPause()
{
// cleanUp();
if (mPlayer != null && mPlayer.isPlaying())
{
mPlayer.release();
mPlayer = null;
}
super.onPause();
}
Also, as you seem to be setting the source of the mediaplayer to be an url, you should change the prepare for a prepareAsync in the following part, so that it buffers:
sa.mPlayer.setDataSource(sa.Audio_URL);
sa.mPlayer.prepare();// might take long! (for buffering, etc)
The link you provided already has a lot of suggestions for overcoming these problems above.
Please try the code on that link, especially the ones that suggest prepareAsync and the onprepared listener. Then you can get back here if it does not work.

Categories

Resources