How I can stop thread in RecyclerView ViewHolder when activity finished? - android

I make an activity with a RecyclerView;
In the RecyclerView, I made a song list with a seekbar and play button.
In seekbar, this moved with music current position using thread
But change activity, music is stop but error
I want when i change the activity, music is stop and not error
Please help me
//seekbar change listener
seekbar.setMax(music.getDuration());
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
if(fromUser)
music.seekTo(progress);
}
});
//music playing
public void button(View v){
if(music.isPlaying()){
music.stop();
try {
music.prepare();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
music.seekTo(0);
button.setText(R.string.start);
seekbar.setProgress(0);
}else{
music.start();
button.setText(R.string.stop);
Thread();
}
}
//Thread
public void Thread(){
Runnable task = new Runnable(){
public void run(){
while(music.isPlaying()){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
seekbar.setProgress(music.getCurrentPosition());
}
}
};
Thread thread = new Thread(task);
thread.start();
}

The thread only can be kill in Activity or Fragment. Use this class to override your recyclerview click listener.
Create new java file and name it RecyclerItemClickListener.java
public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
private GestureDetector mGestureDetector;
public RecyclerItemClickListener(Context context, OnItemClickListener listener) {
mListener = listener;
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
});
}
#Override
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
View childView = view.findChildViewUnder(e.getX(), e.getY());
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
}
return false;
}
#Override
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
// do nothing
}
}
In your activity/fragment
yourRecyclerviewId.addOnItemTouchListener(new RecyclerItemClickListener(this, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view1, int position) {
//view1 - is clicked view
//position - position of the clicked list
//put your method in here
}
}));
Now, you can use OnPause() and OnStop() method to kill the thread or services

Related

How do i setMediaPlayer inside of a fragment?

I have a fragment where i am using media player and using my own custom controller class. I am not being able to set controller.setMediaPlayer inside fragment. I have implemented VideoControllerView.MediaPlayerControl class in fragment.
My fragment class is :
public class HomeFragment extends Fragment implements SurfaceHolder.Callback, VideoControllerView.MediaPlayerControl {
#BindView(R.id.videoSurfaceContainer)
FrameLayout videoContainer;
#BindView(R.id.videoSurface)
SurfaceView videoSurface;
#BindView(R.id.progress)
ProgressBar progressBar;
#BindView(R.id.errorTv)
RelativeLayout relativeLayout;
#BindView(R.id.errorTextView)
TextView errorTextView;
public MediaPlayer player;
public VideoControllerView controller;
private Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_home, container, false);
ButterKnife.bind(this, v);
player = new MediaPlayer();
controller = new VideoControllerView(getActivity());
SurfaceHolder videoHolder = videoSurface.getHolder();
videoHolder.addCallback(this);
progressBar.setVisibility(View.VISIBLE);
playVideo("http://202.166.200.170:8081/otv/aastha.stream/playlist.m3u8");
relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
relativeLayout.setVisibility(View.GONE);
player.reset();
progressBar.setVisibility(View.VISIBLE);
playVideo("http://202.166.200.170:8081/otv/aastha.stream/playlist.m3u8");
} catch (Exception e) {
e.printStackTrace();
}
}
});
return v;
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
player.setDisplay(surfaceHolder);
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
public void playVideo(String link) {
try {
videoSurface.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (controller.isShowing())
controller.hide();
else
controller.show();
return false;
}
});
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
controller.setMediaPlayer();
controller.setAnchorView((FrameLayout) getActivity().findViewById(R.id.videoSurfaceContainer));
player.start();
progressBar.setVisibility(View.GONE);
if (relativeLayout.isShown())
relativeLayout.setVisibility(View.GONE);
}
});
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(getActivity(), Uri.parse(link));
try {
player.prepareAsync();
} catch (Exception e) {
e.printStackTrace();
}
player.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
progressBar.setVisibility(View.GONE);
errorMessage("Streaming Error");
player.reset();
errorTextView.setText(getResources().getString(R.string.error_msg_video));
return false;
}
});
player.setScreenOnWhilePlaying(true);
Log.d("after click", "last try");
} catch (Exception e) {
e.printStackTrace();
}
}
public void errorMessage(String message) {
try {
relativeLayout.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void start() {
}
#Override
public void pause() {
}
#Override
public int getDuration() {
return 0;
}
#Override
public int getCurrentPosition() {
return 0;
}
#Override
public void seekTo(int pos) {
}
#Override
public boolean isPlaying() {
return false;
}
#Override
public boolean canPause() {
return false;
}
#Override
public boolean isFullScreen() {
return false;
}
#Override
public void toggleFullScreen() {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = activity;
}
if you see inside playVideo method inside setOnpreparedListener i am getting error in controller.setMediaPlayer() because i am not being able to pass the context here.
what can be done here to solve the error?
This is how we can use controller.setMediaPlayer()
// Implement MediaPlayer.OnPreparedListener
#Override
public void onPrepared(MediaPlayer mp) {
controller.setMediaPlayer(this);
controller.setAnchorView((FrameLayout)
findViewById(R.id.videoSurfaceContainer));
player.start();
}
// End MediaPlayer.OnPreparedListener
This is example to use costume controller
If you want, you could get the context from there using HomeFragment.this.getContext(), like:
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
controller.setMediaPlayer(HomeFragment.this.getContext());
controller.setAnchorView((FrameLayout) getActivity().findViewById(R.id.videoSurfaceContainer));
player.start();
progressBar.setVisibility(View.GONE);
if (relativeLayout.isShown())
relativeLayout.setVisibility(View.GONE);
}
});
I just moved controller.setMediaPlayer(this); to onCreateView and it worked.

Audio Playing from URI Inside Listview , But Seekbar is not Updating in Android Listview item

I am Playing a Audio from Uri Its Working Fine.
Clicking a Button from Each Listview item.
Problem :Audio is Playing in the Listview ,but still Seekbar is not Moving(Updating).
EDIT:1
1.Audio is Playing in the Each Listview Item Perfectly,But Seekbar is Not Working(Not Updating).
Please Help me top solve this Issue.
My Listview Array adapter Class:
Adapter.class
private static final int UPDATE_FREQUENCY = 500;
int progress=0;
public View getView(final int position, View view, ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.audio_listview, null, true);
ListenAUdioButton = (Button) rowView.findViewById(R.id.ListenAudiobuttonxml);
seek_bar_view = (SeekBar) rowView.findViewById(R.id.seek_bar);
ListenAUdioButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// text_shown.setText("Playing...");
try {
try {
// get Internet status
isInternetPresent = cd1.isConnectingToInternet();
// check for Internet status
if (isInternetPresent) {
if (!itemname3_AUDIO_FILE[position].equals("") || !itemname3_AUDIO_FILE[position].equals("null")) {
System.out.println(" AUDIO FILE :-)" + itemname3_AUDIO_FILE[position]);
player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(context, Uri.parse(itemname3_AUDIO_FILE[position]));
player.prepareAsync();
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
try {
mp.start();
seek_bar_view.setMax(player.getDuration());
updatePosition();
} catch (Exception e) {
e.printStackTrace();
}
}
});
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
stopPlay();
}
});
MediaPlayer.OnErrorListener onError = new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// returning false will call the OnCompletionListener
return false;
}
};
} else {
Toast.makeText(getContext(), "Audio Not Found..!", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getContext(), "Please Check Your Internet Connection..!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getContext(), "Audio Not Found..!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
return rowView;
}
private void stopPlay() {
player.stop();
player.reset();
// playButton.setImageResource(android.R.drawable.ic_media_play);
handler.removeCallbacks(updatePositionRunnable);
seek_bar_view.setProgress(0);
// isStarted = false;
}
private final Handler handler = new Handler();
private final Runnable updatePositionRunnable = new Runnable() {
public void run() {
updatePosition();
}
};
private void updatePosition()
{
handler.removeCallbacks(updatePositionRunnable);
seek_bar_view.setProgress(progress);
progress=getProgressPercentage(player.getCurrentPosition(),player.getDuration();
notifyDataSetChanged();
handler.postDelayed(updatePositionRunnable, UPDATE_FREQUENCY);
}
you need to update your seekbar position(value) at every second..
To set seekbar Max value..
seek_bar_view.setMax((int) player.getDuration());
and update it every second to show progress
Handler mHandler = new Handler();
runOnUiThread(new Runnable() {
#Override
public void run() {
seek_bar_view.setProgress((int) player.getCurrentPosition());
}
mHandler.postDelayed(this,1000);
}
);
See this:
seek_bar_view.setProgress(player.getCurrentPosition());
here player.getCurrentPosition() returns the time in millis , you need to convert this to int and then set the progress to seekBar.
Try this:
public static int getProgressPercentage(long currentDuration, long totalDuration){
Double percentage = (double) 0;
long currentSeconds = (int) (currentDuration / 1000);
long totalSeconds = (int) (totalDuration / 1000);
// calculating percentage
percentage =(((double)currentSeconds)/totalSeconds)*100;
// return percentage
return percentage.intValue();
}
and now get the percentage for your SeekBar like this:
int currentProgress=getProgressPercentage(player.getCurrentPosition(), player.getDuration());
seek_bar_view.setProgress(currentProgress);
Edited:
For your specific case, inside a ListView item:
You will need to notify the adapter each time you change the position of seekbar.
For this, the simplest approach would be to take a variable inside the POJO class you are using to set the adapter.
Inside your POJO class
int progress=0;
In your adapter,set the seekbar progress
seekbar.setProgress(progress);
In your adapter,change the value of progress and notifyadapter
progress=getProgressPercentage(player.getCurrentPosition(), player.getDuration());
notifyDataSetChanged()
//Re-Edited:
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
// TODO Auto-generated method stub
notifyDataSetChanged();
}
});

Android Media Controller hides when loses focus

I'm using a media controller associated with a media player to play a sound. The issue is that the media controller is hiding as soon as it loses focus. I have a button which when pressed, the sound is played and the media controller shows up at the bottom of the screen.
But when life pause is pressed, after like 5 seconds, the media controller itself hides.
here are part of my codes. I'm stopping the media player as soon as the media controller hides so that the sound is not continually played
All the codes for the media controller are:
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(currentFragment);
mediaController = new MediaController(getActivity()){
#Override
public void hide()
{
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
super.hide();
}
};
try {
mediaPlayer.setDataSource(sound.getSound());
mediaPlayer.prepareAsync();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mediaPlayer.start();
#Override
public void onPrepared(MediaPlayer mp) {
Log.d("media status", "onPrepared");
handler.post(new Runnable() {
public void run() {
launchMediaController();
progress.dismiss();
}
});
}
void launchMediaController(){
mediaController.setEnabled(true);
mediaPlayer.start();
mediaController.setMediaPlayer(soundController);
mediaController.setAnchorView(getView());
mediaController.show(0);
}
private class SoundController implements MediaController.MediaPlayerControl{
public void start() {
mediaPlayer.start();
}
public void pause() {
mediaPlayer.pause();
}
public int getDuration() {
return mediaPlayer.getDuration();
}
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
public void seekTo(int i) {
mediaPlayer.seekTo(i);
}
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
public int getBufferPercentage() {
return 0;
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
// TODO Auto-generated method stub
return 0;
}
}
Edits:
Based on the answer of Libin, I did the following with no success:
Extends MediaController and overrides touch event
private class MyMediaController extends MediaController{
public MyMediaController(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}
}
Use extended class
mediaController = new MyMediaController(getActivity()){
#Override
public void hide()
{
if(mediaPlayer.isPlaying()){
mediaPlayer.stop();
}
super.hide();
}
};
launchMediaController() is actually what launches the media controller.
My question, why does the media controller hides by itself after some seconds after the user touches it? Is there any solution to this?
when you call show() , you can set a duration to show the controller on screen. so the controller will automatically hide after 'timeout' milliseconds of inactivity.
You can set the timeout as 0 , to show the controller until the hide is explicitly called.
controller.show(0);
Use 0 to show the controller until hide() is called.
If you use show() method without argument , the default timeout is 3 seconds
Here is some code from show(int timeOut) method call
Message msg = mHandler.obtainMessage(FADE_OUT);
if (timeout != 0) {
mHandler.removeMessages(FADE_OUT);
mHandler.sendMessageDelayed(msg, timeout);
}
The handler is send a delayed message if the timeout id not 0, and in handler if the message is FADE_OUT the hide method is called
EDIT
There is bug in MediaController code. In the onTouchEvent the default timeout is set , which will override the timeout 0.
#Override
public boolean onTouchEvent(MotionEvent event) {
show(sDefaultTimeout);
return true;
}
You can fix this by creating a custom MediaController and override the onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent event) {
return true;
}

Audio Streaming Seekbar Hides while song is playing

I can't find a way to stop hiding the seekbar. As soon as the song plays the seekbar hides after 2-3 sec. I am really new into this so not really sure how I can approach to this issue. I tried putting mediaController.show() into my methods when the song is playing but no luck. I found this code from a Youtube Channel below is the code:
public class MainActivity extends ListActivity implements OnPreparedListener,
MediaController.MediaPlayerControl {
private static final String TAG = "AudioPlayer";
private ListView list;
private MainArrayAdapter adapter;
private MediaPlayer mediaPlayer;
private MediaController mediaController;
private String audioFile;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = getListView();
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(this);
mediaController = new MediaController(this);
ArrayList<String> array_list_music = new ArrayList<String>();
array_list_music.add("Sammy Kaye And His Orchestra" + " ### "
+ "Minka (1941)" + " ### "
+ "http://incoming.jazz-on-line.com/a/mp3w/1941_149.mp3");
adapter = new MainArrayAdapter(MainActivity.this, array_list_music);
setListAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
Object item = getListView().getItemAtPosition(arg2);
String the_list_item = item.toString();
Toast.makeText(MainActivity.this,
"You clicked " + the_list_item, Toast.LENGTH_LONG)
.show();
String[] aux = the_list_item.split(" ### ");
String url_to_play = aux[2];
playAudio(url_to_play);
}
});
}
private void playAudio(String url_to_play) {
//----- stop & reset
try {
mediaPlayer.stop();
mediaPlayer.reset();
} catch (Exception e) {
// TODO: handle exception
}
try {
mediaPlayer.setDataSource(url_to_play);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception e) {
Log.e(TAG, "Could not open file " + url_to_play + " for playback.",
e);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mediaController.show();
return true;
}
#Override
protected void onStop() {
super.onStop();
mediaController.hide();
mediaPlayer.stop();
mediaPlayer.release();
}
#Override
public boolean canPause() {
return true;
}
#Override
public boolean canSeekBackward() {
return true;
}
#Override
public boolean canSeekForward() {
return true;
}
#Override
public int getBufferPercentage() {
// TODO Auto-generated method stub
return 0;
}
#Override
public int getCurrentPosition() {
return mediaPlayer.getCurrentPosition();
}
#Override
public int getDuration() {
return mediaPlayer.getDuration();
}
#Override
public boolean isPlaying() {
return mediaPlayer.isPlaying();
}
#Override
public void pause() {
mediaPlayer.pause();
}
#Override
public void seekTo(int arg0) {
mediaPlayer.seekTo(arg0);
}
#Override
public void start() {
mediaPlayer.start();
}
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d(TAG, "onPrepared");
mediaController.setMediaPlayer(this);
mediaController.setAnchorView(list);
mediaController.show();
handler.post(new Runnable() {
public void run() {
mediaController.setEnabled(true);
mediaController.show();
}
});
}
}

How to show seekbar along with the custom mediaplayer

i have build a custom media player and i want to show the seekbar also.
The seekbar is showing for now but is not functional i.e. it is not progressing when the song is played. Let me know where am i wrong . Following is the code
public class myPlayer extends Activity implements Runnable,SeekBar.OnSeekBarChangeListener {
MediaPlayer mPlayer;
Button play,stop;
SeekBar seekbar;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
seekbar = (SeekBar)findViewById(R.id.seekbar);
mPlayer = MediaPlayer.create(this,R.raw.sajnave);
play=(Button)findViewById(R.id.play);
stop=(Button)findViewById(R.id.stop);
Toast.makeText(myPlayer.this, ""+mPlayer.getDuration(), Toast.LENGTH_SHORT).show();
play.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
mPlayer.start();
}
});
stop.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(myPlayer.this, ""+mPlayer.getCurrentPosition(), Toast.LENGTH_SHORT).show();
mPlayer.stop();
}
});
}
#Override
public void run() {
// TODO Auto-generated method stub
int currentPosition = 0;
int total = mPlayer.getDuration();
seekbar.setMax(total);
while (mPlayer != null && currentPosition < total) {
try {
Thread.sleep(1000);
currentPosition = mPlayer.getCurrentPosition();
} catch (InterruptedException e) {
return;
} catch (Exception e) {
return;
}
seekbar.setProgress(currentPosition);
}
}
#Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
// TODO Auto-generated method stub
mPlayer.seekTo(arg1);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
Call updatePosition() method after mediplayer starts..It works for me.
private final Handler handler = new Handler();
private final Runnable updatePositionRunnable = new Runnable() {
public void run() {
updatePosition();
}
};
private void updatePosition() {
handler.removeCallbacks(updatePositionRunnable);
if (player != null) seekbar.setProgress(player.getCurrentPosition());
handler.postDelaye(updatePositionRunnable, 500);
}
#Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
// TODO Auto-generated method stub
player.seekTo(arg1);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
SurfaceView mPreview=(SurfaceView)findViewById(R.id.surface);
mPreview.postDelayed(runnable,200);
Runnable runnable = new Runnable() {
#Override
public void run() {
if (mMediaPlayer != null) {
if (isPlaying) {
// converting current position into seconds so dividing by
// 1000
try {
currentPosition = mMediaPlayer.getCurrentPosition();
mVideoProgress
.setProgress((int) ((currentPosition / (float) mMediaPlayer
.getDuration()) * 100f));
} catch (Exception e) {
e.printStackTrace();
}
mPreview.postDelayed(runnable, 150);
}
}
}
};

Categories

Resources