I am having difficulty getting the back button to actually finish my activity when pressed. I am running a very simple videoview, using a progressdialog to show loading dialog and onpreparedlistener, etc etc. simple stuff. Anyways, currently when I press the back button, it will just cancel the progressdialog, and leave a black screen, and pressed again, the progressdialog restarts!!! and then when I click the back button again, it displays an alert dialog, "video cannot be played." very annoying. Thanks for your help.
public class VideoActivity extends Activity {
private VideoView mVideoView;
private static ProgressDialog progressdialog;
private String path;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.videoview);
progressdialog = ProgressDialog.show(this, "", " Video Loading...", true);
progressdialog.setCancelable(true);
mVideoView = (VideoView) findViewById(R.id.surface_view);
mVideoView.setMediaController(new MediaController(this));
Bundle b = this.getIntent().getExtras();
path = b.getString("path");
mVideoView.setVideoURI(Uri.parse(path));
mVideoView.setOnPreparedListener(new OnPreparedListener() {
public void onPrepared(MediaPlayer mp) {
progressdialog.dismiss();
mVideoView.requestFocus();
mVideoView.start();
}
});
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
super.finish();
}
}
You can simply write: (No need to create new class for MediaController)
mVideoView.setMediaController(new MediaController(this){
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP)
((Activity) getContext()).finish();
return super.dispatchKeyEvent(event);
}
});
You'll want to create a custom MediaController class and override the dispatchKeyEvent function to capture the back KeyEvent and tell the activity to finish.
See Android back button and MediaController for more info.
public class CustomMediaController extends MediaController {
public CustomMediaController(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomMediaController(Context context, boolean useFastForward) {
super(context, useFastForward);
}
public CustomMediaController(Context context) {
super(context, true);
}
public boolean dispatchKeyEvent(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
((Activity) getContext()).finish();
return super.dispatchKeyEvent(event);
}
}
From CommansWare
Based on the source code, this should work:
Extend MediaController (for the purposes of this answer, call it
RonnieMediaController)
Override dispatchKeyEvent() in RonnieMediaController
Before chaining to the superclass, check for KeyEvent.KEYCODE_BACK,
and if that is encountered, tell your activity to finish()
Use RonnieMediaController instead of MediaController with your
VideoView
Personally, I'd just leave it alone, as with this change your user
cannot make a RonnieMediaController disappear on demand.
Here is the link to the original post.
finish() doesn't kill your activity, it just signals to Android that it doesn't need to run the Activity anymore.
I remember solving this by putting "return" in proper places.
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
System.exit(0);
}
return false;
}
Related
I have a music app with MediaPayer and MediaController and when music play and i hit back button can't let the activity exit.
I found from source code that MediaController capture the KeyEvent.KEYCODE_BACK in MediaController#dispatchKeyEvent(). so I override the method by adding following code:
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
return false;
}
return super.dispatchKeyEvent(event);
But it still no luck.
You can also override hide() method to show mediaController for every time like this:
mediaController = new MediaController(this){
#Override
public void hide() {
//do Nothing
}
//Handle BACK button
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK){
super.hide();//Hide mediaController
finish();//Close this activity
return true;//If press Back button, finish here
}
//If not Back button, other button (volume) work as usual.
return super.dispatchKeyEvent(event);
}
};
You need to release the MediaPlayer before you can execute finish() or onBackPressed(), this worked for me:
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
MediaController mediaController = new MediaController(MyActivity.this){
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK){
mp.release();
super.hide();//Hide mediaController
finish();//Close this activity
return true;//If press Back button, finish here
}
//If not Back button, other button (volume) work as usual.
return super.dispatchKeyEvent(event);
}
};
videoView.setMediaController(mediaController);
videoView.start();
}
});
I came across this problem too. The solution to my problem was none of them above, was setting MediaController after VideoView prepared. See the code:
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(final MediaPlayer mp) {
videoView.setMediaController(mediaController);
}
});
I have a VideoView which plays a video and I call
videoPlayer.setMediaController(new MediaController(this));
to show the media controller buttons (play, pause, forward, backward).
The question is how am I able to add additional methods when I click the play or pause button of the MediaController?
Here's my class:
public class VideoPlayer extends Activity implements OnCompletionListener {
private String filename;
private VideoView videoPlayer;
private MediaPlayer mediaplayer;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.video_player);
System.gc();
Intent i = getIntent();
Bundle extras = i.getExtras();
filename = extras.getString("video_url");
System.out.println(filename);
videoPlayer = (VideoView) findViewById(R.id.videoPlayer);
videoPlayer.setOnCompletionListener(this);
videoPlayer.setKeepScreenOn(true);
videoPlayer.setVideoPath(filename);
videoPlayer.setMediaController(new MediaController(this));
videoPlayer.requestFocus();
videoPlayer.start();
mediaplayer = new MediaPlayer();
mediaplayer = MediaPlayer.create(
this,
Uri.parse("android.resource://" + getPackageName() + "/"
+ R.raw.alo));
mediaplayer.start();
}
/** This callback will be invoked when the file is finished playing */
#Override
public void onCompletion(MediaPlayer mp) {
// Statements to be executed when the video finishes.
this.finish();
}
/** Use screen touches to toggle the video between playing and paused. */
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
if (videoPlayer.isPlaying()) {
videoPlayer.pause();
mediaplayer.pause();
} else {
videoPlayer.start();
mediaplayer.start();
}
return true;
} else {
return false;
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
I'm not sure what you are trying to achieve.
You could extend a class with MediaController and implement some methods of your own. Basic OO principles.
private class MyMediaController extends MediaController {
#Override
public boolean onTouchEvent(MotionEvent event) {
// Your logic here
return super.onTouchEvent(event);
}
}
I have an activity with different video files displayed. When I click a video file, I'm taken to another activity, where a VideoView plays the video.
My issue is that when I want to exit this activity and return back to previous, I should click twice the back button, in order to return back. If I click only once, the video starts playing once again, and only at the second attempt I'm allowed to exit the screen.
Then I tried this:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.d(Constants.LOG_TAG, "back pressed in videoplayer");
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
And, although I see in the logcat "back pressed in video player", the activity does not exit. I still should press twice the back button.
EDIT: This is the most relevant (I believe) source code. Note however, that the video is played from the internet, and I'm not using the Mediacontroller, instead I'm defining my own layout and link to videoview conrols.
public class VideoPlayer extends Activity implements OnClickListener, OnCompletionListener,
OnSeekBarChangeListener, OnPreparedListener, OnTouchListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.video_view);
// Gets the position of clicked video, from an ArrayList of video urls.
selectedVideo = getPosition();
// the play button
play = (ImageButton) findViewById(R.id.play);
play.setOnClickListener(this);
videoView = (VideoView) findViewById(R.id.videoView);
videoView.setOnCompletionListener(this);
videoView.setOnPreparedListener(this);
videoView.setOnTouchListener(this);
// the url to play
String path = videoUris.get(selectedVideo);
videoView.setVideoPath(getPath(path));
}
/**
* Play or Pause the current video file.
*
* If the video is paused, then invoking this method should start it. If the video is already playing, then the
* video should pause.
*/
private void play() {
if (!isVideoStarted) {
isVideoStarted = true;
videoView.start();
play.setImageResource(R.drawable.video_pause);
videoSeekBar.post(updateSeekBarRunnable);
} else if (isVideoStarted) {
isVideoStarted = false;
pause();
}
}
/**
* Start playing back a video file with the specified Uri.
*/
private void startPlayback() {
String path = videoUris.get(selectedVideo);
videoView.setVideoPath(getPath(path));
videoView.start();
}
/**
* Stops the currently playing video. (The SeekBar position is reset to beginning, 0.)
*/
private void stopPlayback() {
videoView.stopPlayback();
}
/**
* Pause the currently playing video. (The SeekBar remains in its position.)
*/
private void pause() {
videoView.pause();
#Override
public void onPrepared(MediaPlayer mp) {
play();
}
}
Code below work fine for me:
try
{
MediaController mc = new MediaController(YourActivity.this);
mc.setAnchorView(vd);
Uri uri = Uri.parse(YourURL);
vd.setMediaController(mc);
vd.setVideoURI(uri);
//vd.start();
}catch(Exception e)
{
Log.e("Error", e.getMessage());
e.printStackTrace();
}
vd.requestFocus();
vd.start();
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(keyCode == KeyEvent.KEYCODE_BACK)
{
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
Thank you for trying to help me.
It turned out that I was calling startActivity(intent); twice, and that is why I should press the back button twice.
Can you try overriding the onBackPressed instead of KeyEvent. Because your code seems to look correct.
Remove this,
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Log.d(Constants.LOG_TAG, "back pressed in videoplayer");
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
And add,
#Override
public void onBackPressed() {
finish();
}
I try to use MediaController to play music.
I want the MediaController appear until the "back" button is pressed.
Now I have try below code:
MediaController mediaController = new MediaController(this){
#Override
public void setMediaPlayer(MediaPlayerControl player) {
super.setMediaPlayer(player);
this.show();
}
#Override
public void show(int timeout) {
super.show(0);
}
//instead of press twice with press once "back" button to back
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Activity a = (Activity)getContext();
a.finish();
}
return true;
}
};
But it still one trouble while the MediaController visible.
When the MediaController appear touch the screen, the MediaController will hide.
I also already try below code:
#Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("screen","touch");
return true;
}
But it did not work.
The string did not show in Logcat.
Anyone has idea to do it?
Override this method also inside media controller
#Override
public void hide() {
// TODO Auto-generated method stub
super.show();
}
If you want to keep the hide() method but not have the controller disappearing every time a control is used :
this.mediaController = new MediaController(this){
#Override
public void show(int timeout) {
super.show(0);
}
};
I am using mediacontroller in my app, but it shows only for 3 seconds. I have searched a lot, but in every document I see only the show function, set time out, but it has no effect. How can I always show mediacontroller?
I have tested show(0), but it had no effect.
You can extend the MediaController class and programmatically set an instance of it to a VideoView class:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.MediaController;
public class MyMediaController extends MediaController {
public MyMediaController(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyMediaController(Context context, boolean useFastForward) {
super(context, useFastForward);
}
public MyMediaController(Context context) {
super(context);
}
#Override
public void show(int timeout) {
super.show(0);
}
}
Here's the usage:
VideoView myVideoView = (VideoView) findViewById(R.id.my_video_view);
MediaController mc = new MyMediaController(myVideoView.getContext());
mc.setMediaPlayer(myVideoView);
myVideoView.setMediaController(mc);
You can create anonymous class inline and override certain methods. You need to override the hide method and do nothing in there. You also need to override the dispatchKeyEvent method to check for back key press and call the super.hide(). Otherwise on back press the controller wont hide and the activity cannot be closed.
mediaController = new MediaController(this){
#Override
public void hide() {
// TODO Auto-generated method stub
//do nothing
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if (mediaPlayer != null) {
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
super.hide();
Activity a = (Activity)getContext();
a.finish();
}
return true;
}
};
You can also create an anonymous class inline and override the hide method there instead of having to create a whole new class for it:
mediaController = new MediaController(this) {
#Override
public void hide() {
//Do not hide.
}
};
Try the show method in this way:
new media controller().show(50000);
And also check http://developer.android.com/reference/android/widget/MediaController.html#show().
SudeepSR: Please make a note of that, if you called show(0), it will show the Media Controller until hide() is called.
After trying all that I could, the following code worked for me!
mVideoView = (VideoView) findViewById(R.id.video);
mMediaController = new MediaController(this) {
//for not hiding
#Override
public void hide() {}
//for 'back' key action
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Activity a = (Activity)getContext();
a.finish();
}
return true;
}
};
mMediaController.setAnchorView(mVideoView);
mMediaController.setMediaPlayer(mVideoView);
mVideoView.setMediaController(mMediaController);
mMediaController.requestFocus();
//only this showed the controller for me!!
mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mVideoView.start();
mMediaController.show(900000000);
}
});
//finish after playing
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
finish();
}
});
What you need to do is, overrride the hide method in the custom controller and do nothing.
public class MyMediaController extends MediaController {
..
#Override
public void hide() {
// Do nothing here in order to always show
}
...
}
PS: You still need to click on the video to show the media controller.
This may be an old thread, but still unanswered, try this :
final MediaController mediaController = new MediaController(this);
mediaController.setAlwaysDrawnWithCacheEnabled(true);
mediaController.setAnchorView(vView);
mediaController.requestFocus();
vView.setOnPreparedListener( new OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaController.show( 0 );
}
});
vView.setVideoPath(Preview_Path);
vView.setMediaController(mediaController);
vView.start();
theres a comment inside the MediaController Class "show" method
**Use 0 to show
* the controller until hide() is called**
so using 900000 or larger value wont help.
hope it helps you.
cheers.
Try this:
videoView.setOnCompletionListener(onVideoCompleted);
videoView.setOnPreparedListener(onVideoPrepared);
mc.setAnchorView(videoView);
mc.setMediaPlayer(videoView);
MediaController mc = new MediaController(this);
videoView.setMediaController(mc);
MediaPlayer.OnPreparedListener onVideoPrepared = new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mc.show(0);
}
};
MediaPlayer.OnCompletionListener onVideoCompleted = new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
mc.hide();
}
};
I wanted to fade the controller for videos and always show it for audio. This worked
mController = new MediaController(this) {
#Override
public void hide() {
if (mType != TYPE_AUDIO) super.hide();
}
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
mController.hide();
Activity a = (Activity)getContext();
a.finish();
return true;
}
return false;
}
};
In MediaPlayer.onPrepared I added:
if (mType == TYPE_AUDIO) mController.show(0);
This causes the controller to show at the start of audio playback, but not video playback.
The other phone control buttons continue to work as normal.
Easy! Set visibility "GONE" in event hide and set visibility "VISIBLE" in show!
MediaController mc= new MediaController(zoom.this){
#Override
public void setMediaPlayer(MediaPlayerControl player) {
super.setMediaPlayer(player);
this.show(4000);
}
#Override
public void show(int timeout) {
super.show(timeout);
this.setVisibility(View.VISIBLE);
}
//instead of press twice with press once "back" button to back
#Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Activity a = (Activity)getContext();
a.finish();
}
return true;
}
#Override
public void hide() {
// TODO Auto-generated method stub
super.hide();
this.setVisibility(View.GONE);
//super.show(3000);
}
};