I am working on this very simple app that plays videos in a loop with a countDowntimer attached to it. Essentially what I have is the following:
- I instantiate the VideoView
- If the user checked for the video to loop (1x or 2x)
Then in the countdownTimer's
onFinish()
I wait a few seconds and then start a new activity like such:public void openCompletedWorkout() { handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { final Intent mainIntent = new Intent(getActivity(), CompletedWorkoutActivity.class); getActivity().startActivity(mainIntent); getActivity().finish(); } }, 5000); }
The above method is called inside the onFinish()
method (of the CoundDownTimer
).
The problem is if the user doesn't want to have the videoPlayer to loop, everything works fine, meaning, the onFinish()
function calls the OpenCompletedWorkout()
method without crashing ( the activity opens with no problem). However, when the user either says that they want for the video to loop 1x or 2x, when it comes time to call onFinish()
, the app crashes.
I don't know what's wrong. I have been trying to fix this issue for the past 4hrs and still having a lot of issues.
Just to put things into perspective, below is my fragmentActivity where all is happening:
public class PlayVideoFragment extends Fragment implements View.OnClickListener {
private static final String VIDEO_PATH = "android.resource://";
TextView screenTitle;
TextView textTitle;
String myTime;
String myPlan;
private ImageButton pauseButton;
private ImageButton playButton;
private VideoView videoPlayer;
private MediaController mc;
private TextView counter;
private MediaPlayer soundPlayer;
private int mRepeats;
String output;
MyCounter downCounter;
int length;
long leftTime;
long seconds;
Handler handler;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedStateInstance) {
View v = inflater.inflate(R.layout.play_video_container, container,
false);
pauseButton = (ImageButton) v.findViewById(R.id.pauseButton);
pauseButton.setOnClickListener(this);
playButton = (ImageButton) v.findViewById(R.id.playButton);
playButton.setOnClickListener(this);
counter = (TextView) v.findViewById(R.id.counter);
Bundle bundle = getArguments();
if (bundle != null) {
myTime = bundle.getString("time");
myPlan = bundle.getString("plan");
}
videoPlayer = (VideoView) v.findViewById(R.id.videoPlayer);
if (myPlan.equals("intense")) {
if (myTime.equals("fiveMin")) {
playVideoTimed(R.raw.abs_workout_one, myTime.toString(), 0);
} else if (myTime.equals("tenMin")) {
playVideoTimed(R.raw.abs_workout_one, myTime.toString(), 1);
// Toast.makeText(getActivity(), "LOOOP ONCE!!",
// Toast.LENGTH_LONG).show();
} else if (myTime.equals("fifteenMin")) {
playVideoTimed(R.raw.abs_workout_one, myTime.toString(), 2);
}
// playVideo(R.raw.abs_workout_one, myTime.toString());
} else if (myPlan.equals("extreme")) {
if (myTime.equals("fiveMin")) {
playVideoTimed(R.raw.abs_workout_two, myTime.toString(), 0);
} else if (myTime.equals("tenMin")) {
playVideoTimed(R.raw.abs_workout_two, myTime.toString(), 1);
} else if (myTime.equals("fifteenMin")) {
playVideoTimed(R.raw.abs_workout_two, myTime.toString(), 2);
}
// playVideo(R.raw.abs_workout_two, myTime.toString());
} else if (myPlan.equals("insane")) {
if (myTime.equals("fiveMin")) {
playVideoTimed(R.raw.abs_workout_three, myTime.toString(), 0);
} else if (myTime.equals("tenMin")) {
playVideoTimed(R.raw.abs_workout_three, myTime.toString(), 1);
} else if (myTime.equals("fifteenMin")) {
playVideoTimed(R.raw.abs_workout_three, myTime.toString(), 2);
}
// playVideo(R.raw.abs_workout_three, myTime.toString());
}
return v;
}
public void playVideoTimed(int videoPath, String mins, int repeats) {
long timeElapsed = 0;
if (mins.equals("fiveMin")) {
repeats = 0;
mRepeats = 0;
timeElapsed = 300000;
} else if (mins.equals("tenMin")) {
repeats = 1;
mRepeats = 1;
timeElapsed = 600000;
} else if (mins.equals("fifteenMin")) {
repeats = 2;
mRepeats = 2;
timeElapsed = 900000;
}
downCounter = new MyCounter(timeElapsed, 1000);
downCounter.start();
Uri uri = Uri.parse(VIDEO_PATH + getActivity().getPackageName() + "/"
+ videoPath);
mc = new MediaController(getActivity());
videoPlayer.setMediaController(null); // used to be mc being passed to
// show controls
videoPlayer.setVideoURI(uri);
videoPlayer.requestFocus();
videoPlayer.start();
videoPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (mRepeats == 1) {
mp.setLooping(false);
mp.seekTo(0);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.setLooping(false);
//mp.seekTo(0);
//mp.stop();
try{
mp.stop();
mp.reset();
mp.release();
mp = null;
}catch(IllegalStateException e) {
e.printStackTrace();
}
}
});
} // end if
else if (mRepeats == 2) {
mp.seekTo(0);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
try{
mp.setLooping(false);
mp.seekTo(0);
mp.start();
}catch (IllegalStateException e) {
e.printStackTrace();
}
mp.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
try{
mp.setLooping(false);
mp.stop();
mp.reset();
mp.release();
mp = null;
}catch (IllegalStateException e) {
e.printStackTrace();
}
}
});
}
});
}// end final IF
} // END FUNCTION
});
}
public void playVideo(int videoPath, String mins) {
long timeElapsed = 0;
if (mins.equals("fiveMin")) {
timeElapsed = 300000;
} else if (mins.equals("tenMin")) {
timeElapsed = 600000;
} else if (mins.equals("fifteenMin")) {
timeElapsed = 900000;
}
downCounter = new MyCounter(timeElapsed, 1000);
downCounter.start();
Uri uri = Uri.parse(VIDEO_PATH + getActivity().getPackageName() + "/"
+ videoPath);
mc = new MediaController(getActivity());
videoPlayer.setMediaController(null); // used to be mc being passed to
// show controls
videoPlayer.setVideoURI(uri);
videoPlayer.requestFocus();
videoPlayer.start();
}
public void playDoneSound() {
soundPlayer = MediaPlayer.create(getActivity(),
R.raw.well_done_workout_completed);
soundPlayer.start();
}
public void killSounds() {
if (soundPlayer != null) {
soundPlayer.stop();
soundPlayer.release();
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.pauseButton:
videoPlayer.pause();
playButton.setVisibility(View.VISIBLE);
pauseButton.setVisibility(View.INVISIBLE);
downCounter.cancel();
break;
case R.id.playButton:
videoPlayer.seekTo(videoPlayer.getCurrentPosition());
videoPlayer.start(); // little hack to get the video to play from
// where it stopped
pauseButton.setVisibility(View.VISIBLE);
playButton.setVisibility(View.INVISIBLE);
downCounter = new MyCounter(leftTime, 1000);
downCounter.start();
// downCounter
break;
}
}
// inner class for our timer
/**
*
* @author http://stackoverflow.com/questions/16584328/track-each-minute-in-
* countdown-timer
*
*/
public String formatTime(long millis) {
output = "";
seconds = millis / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;
seconds = seconds % 60;
minutes = minutes % 60;
hours = hours % 60;
String secondsD = String.valueOf(seconds);
String minutesD = String.valueOf(minutes);
String hoursD = String.valueOf(hours);
if (hours > 10)
secondsD = "0" + seconds;
if (minutes < 10)
minutesD = "0" + minutes;
if (hours < 10)
hoursD = "0" + hours;
if (seconds < 10)
secondsD = "0" + seconds;
// output = hoursD+" : " +minutesD + " : " + secondsD;
output = minutesD + " : " + secondsD;
return output;
}
public class MyCounter extends CountDownTimer {
Context mContext;
public MyCounter(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@Override
public void onFinish() {
counter.setText("Done!");
playDoneSound();
downCounter.cancel();
downCounter = null;
//if (mRepeats == 0) {
openCompletedWorkout();
//}
}
@Override
public void onTick(long millisUntilFinished) {
leftTime = millisUntilFinished;
counter.setText(formatTime(millisUntilFinished));
}
public void openCompletedWorkout() {
handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
final Intent mainIntent = new Intent(getActivity(), CompletedWorkoutActivity.class);
getActivity().startActivity(mainIntent);
getActivity().finish();
}
}, 5000);
}
}
}
And here is the logCat:
10-14 13:15:29.273: E/MediaPlayer(18712): [MediaPlayer.java:767:setDataSource()] setDataSource() uri: android.resource://com.pocketworkouts.armsworkout/2130968576
10-14 13:25:29.669: E/MediaPlayer(18712): [MediaPlayer.java:1198:release()] release() 10-14 13:25:34.874: W/dalvikvm(18712): threadid=1: thread exiting with uncaught exception (group=0x4001d560) 10-14 13:25:34.904: E/AndroidRuntime(18712): FATAL EXCEPTION: main 10-14 13:25:34.904: E/AndroidRuntime(18712): java.lang.IllegalStateException 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.media.MediaPlayer._reset(Native Method) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.media.MediaPlayer.reset(MediaPlayer.java:1228) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.widget.VideoView.release(VideoView.java:505) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.widget.VideoView.access$2100(VideoView.java:49) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.widget.VideoView$6.surfaceDestroyed(VideoView.java:495) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:596) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.SurfaceView.updateWindow(SurfaceView.java:490) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:215) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.View.dispatchWindowVisibilityChanged(View.java:4098) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.ViewRoot.performTraversals(ViewRoot.java:786) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.view.ViewRoot.handleMessage(ViewRoot.java:1863) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.os.Handler.dispatchMessage(Handler.java:99) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.os.Looper.loop(Looper.java:130) 10-14 13:25:34.904: E/AndroidRuntime(18712): at android.app.ActivityThread.main(ActivityThread.java:3683) 10-14 13:25:34.904: E/AndroidRuntime(18712): at java.lang.reflect.Method.invokeNative(Native Method) 10-14 13:25:34.904: E/AndroidRuntime(18712): at java.lang.reflect.Method.invoke(Method.java:507) 10-14 13:25:34.904: E/AndroidRuntime(18712): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 10-14 13:25:34.904: E/AndroidRuntime(18712): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:647) 10-14 13:25:34.904: E/AndroidRuntime(18712): at dalvik.system.NativeStart.main(Native Method)
Any help will be highly appreciated.
Thanks.