My app recyclerview having audio, imageview, textview as items. When scrolling the recyclerview, it is scrolled properly without any issue if item is not updated. But scrolling the recyclerview is not smooth while playing a audio item of recyclerview, it behaves as below attached gif image. While playing an audio, i am updating audio current playing time in textview. I am not sure what is issue is here. Kindly help me. Thanks.
Here is my code.
public class MessageAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
ArrayList<SessionHistoryMesssage> messageArrayList;
MediaPlayer mPlayer = null;
LocalService mService;
boolean mBound = false;
private RelativeLayout.LayoutParams params;
int currentlyPlayingPosition = -1;
public String mBasePath = "", imageDirectory = "", mSessionId = "", audioDirectory = "";
private ProgressDialog progressDialog;
public RetrofitRestAdapter retrofitRestAdapter;
private MessageAdapter messageListAdapter;
private SessionHistoryResponse sessionHistoryResponse;
public Context mContext;
private int mSelectionPosition = -1;
private int num = 0;
public boolean isSessionStarted=false;
public static Handler mHandler;
public int playposition = -1, sessionstartPosition = -1, alreadystartPosition = -1, sessionendPosition = -1;
public MessageAdapter(Context mContext
, ArrayList<SessionHistoryMesssage> messageArrayList, String mBasePath) {
this.mContext = mContext;
this.messageArrayList = messageArrayList;
this.mBasePath = mBasePath;
mHandler = new Handler();
Intent intent = new Intent(mContext, LocalService.class);
this.mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
// 1. Type a) SEND b) RECEIVE
// 2. Message a) AUDIO b) IMAGE
@Override
public int getItemViewType(int position) {
// Just as an example, return 0 or 2 depending on position
// Note that unlike in ListView adapters, types don't have to be contiguous
Log.i("ViewType", messageArrayList.get(position).getmMediaType() + "");
Log.i("sent by", messageArrayList.get(position).getmSentBy() + "");
return Integer.parseInt(messageArrayList.get(position).getmSentBy());
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
VHItemAudio dataObjectHolder = null;
if (Integer.parseInt(Utility.readPatientId(mContext)) == viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_a_conversation_item, parent, false);
dataObjectHolder = new VHItemAudio(view);
return dataObjectHolder;
} else {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.layout_b_conversation_item, parent, false);
dataObjectHolder = new VHItemAudio(view);
return dataObjectHolder;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
final VHItemAudio vhItemHolder = (VHItemAudio) holder;
vhItemHolder.bind(messageArrayList.get(position), position);
}
public class VHItemAudio extends RecyclerView.ViewHolder {
ImageView playPauseImageView, imgDownloadAudio, imgDownloadImage;
TextView txtImageSendTime, runningTimerTextView, txtAudioSendTime, txtSessionStart;
SeekBar seekBar;
ImageView imageView;
RelativeLayout layoutAudio, layoutImage, layoutdownloadImage, layoutSessionStart;
ProgressBar progressImageDownload, progressAudioDownload;
private ImageView imageShareImageView,recordAudioImageView,imgEndSession;
public VHItemAudio(View itemView) {
super(itemView);
playPauseImageView = (ImageView) itemView.findViewById(R.id.playPauseImageView);
txtImageSendTime = (TextView) itemView.findViewById(R.id.txtImageSendTime);
runningTimerTextView = (TextView) itemView.findViewById(R.id.runningTimerTextView);
seekBar = (SeekBar) itemView.findViewById(R.id.seekBar);
imgDownloadAudio = (ImageView) itemView.findViewById(R.id.imgDownloadAudio);
imgDownloadImage = (ImageView) itemView.findViewById(R.id.imgDownloadImage);
imageView = (ImageView) itemView.findViewById(R.id.imageView);
txtAudioSendTime = (TextView) itemView.findViewById(R.id.txtAudioSendTime);
layoutAudio = (RelativeLayout) itemView.findViewById(R.id.layoutAudio);
layoutImage = (RelativeLayout) itemView.findViewById(R.id.layoutImage);
layoutdownloadImage = (RelativeLayout) itemView.findViewById(R.id.layoutdownloadImage);
progressImageDownload = (ProgressBar) itemView.findViewById(R.id.progressImageDownload);
progressAudioDownload = (ProgressBar) itemView.findViewById(R.id.progressAudioDownload);
layoutSessionStart = (RelativeLayout) itemView.findViewById(R.id.layoutSessionStart);
txtSessionStart = (TextView) itemView.findViewById(R.id.txtSessionStart);
Log.i("", "Adding Listener");
imageShareImageView= (ImageView) ((PatientActivity)PatientActivity.patientContext).findViewById(R.id.imageShareImageView);
recordAudioImageView= (ImageView) ((PatientActivity) PatientActivity.patientContext).findViewById(R.id.recordAudioImageView);
imgEndSession= (ImageView) ((PatientActivity) PatientActivity.patientContext).findViewById(R.id.imgEndSession);
}
public void bind(final SessionHistoryMesssage sessionHistoryMesssage, final int position) {
if (sessionHistoryMesssage.getmSessionStart().equalsIgnoreCase("yes")
&& Integer.parseInt(sessionHistoryMesssage.getmTransToId())
== Integer.parseInt(Utility.readPatientId(mContext))) {
sessionstartPosition = position;
isSessionStarted=true;
} else if (sessionHistoryMesssage.getmSessionStart().equalsIgnoreCase("already started")) {
alreadystartPosition = position;
} else if (sessionHistoryMesssage.getmSessionStart().equalsIgnoreCase("end")) {
sessionendPosition = position;
} else {
}
if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("audio")) {
layoutAudio.setVisibility(View.VISIBLE);
layoutImage.setVisibility(View.GONE);
seekBar.setFocusable(false);
txtAudioSendTime.setText(Utility.convertDateTime(sessionHistoryMesssage.getmSentTime()));
audioDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/A/Audio/";
File file = new File(Environment.getExternalStorageDirectory()
+ "/A/Audio/" + messageArrayList.get(position).getmMediaValue());
if (file.exists()) {
imgDownloadAudio.setVisibility(View.GONE);
playPauseImageView.setVisibility(View.VISIBLE);
playPauseImageView.setImageResource(R.drawable.play_icon);
} else {
imgDownloadAudio.setVisibility(View.VISIBLE);
playPauseImageView.setVisibility(View.GONE);
imgDownloadAudio.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
imgDownloadAudio.setVisibility(View.GONE);
Log.v("basepath", mBasePath);
new DownloadFile(mBasePath + messageArrayList.get(position).getmMediaPath() +
messageArrayList.get(position).getmMediaValue(),
audioDirectory + messageArrayList.get(position).getmMediaValue()
, imgDownloadAudio, progressAudioDownload).execute();
}
});
}
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (playposition == position) {
int seekBarPosition = seekBar.getProgress();
mPlayer.seekTo(seekBarPosition);
}
}
});
playPauseImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mService.isPlaying()) {
playposition = position;
mService.playAudio(audioDirectory + messageArrayList.get(position).getmMediaValue());
notifyDataSetChanged();
} else {
if (playposition == position) {
playposition = -1;
mHandler.removeCallbacks(null);
mService.stopAudio();
notifyDataSetChanged();
} else {
playposition = position;
mService.playAudio(audioDirectory + messageArrayList.get(position).getmMediaValue());
notifyDataSetChanged();
}
}
}
});
} else if (messageArrayList.get(position).getmMediaType().equalsIgnoreCase("photo")) {
layoutImage.setVisibility(View.VISIBLE);
layoutAudio.setVisibility(View.GONE);
txtImageSendTime.setText(Utility.convertDateTime(messageArrayList.get(position).getmSentTime()));
imageDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/A/Image/";
Log.v("image path123", mBasePath + messageArrayList.get(position).getmMediaPath()
+ messageArrayList.get(position).getmMediaValue());
try {
File file = new File(Environment.getExternalStorageDirectory()
+ "/A/Image/" + messageArrayList.get(position).getmMediaValue());
if (!file.exists()) {
layoutdownloadImage.setVisibility(View.VISIBLE);
imageView.setVisibility(View.GONE);
} else {
layoutdownloadImage.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
imageView.setImageBitmap(BitmapFactory.decodeFile(file.getAbsolutePath()));
}
layoutdownloadImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mSessionId = messageArrayList.get(position).getmSessionId();
imgDownloadImage.setVisibility(View.GONE);
new DownloadImage(mBasePath + messageArrayList.get(position).getmMediaPath()
+ sessionHistoryMesssage.getmMediaValue(),
sessionHistoryMesssage.getmMediaValue(),
imgDownloadImage, progressImageDownload
).execute();
}
});
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showImageDialog(position);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
if (sessionstartPosition == position) {
layoutSessionStart.setVisibility(View.VISIBLE);
layoutAudio.setVisibility(View.GONE);
layoutImage.setVisibility(View.GONE);
txtSessionStart.setText("Start session");
if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("audio")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutAudio);
} else if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("photo")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutImage);
} else {
}
if(!isSessionStarted) {
imageShareImageView.setVisibility(View.GONE);
recordAudioImageView.setVisibility(View.GONE);
imgEndSession.setVisibility(View.GONE);
isSessionStarted=true;
}
txtSessionStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
retrofitRestAdapter = new RetrofitRestAdapter();
Map<String, String> sessionstartParams = new HashMap<String, String>();
sessionstartParams.put("session_id", sessionHistoryMesssage.getmSessionId());
final ProgressDialog progressDialog = new ProgressDialog(mContext);
progressDialog.setTitle("Please wait...");
progressDialog.show();
retrofitRestAdapter.sessionStart(sessionstartParams, new Callback<SessionHistoryResponse>() {
@Override
public void onResponse(Call<SessionHistoryResponse> call, Response<SessionHistoryResponse> response) {
Log.v("session start response", new Gson().toJson(response.body()));
progressDialog.dismiss();
txtSessionStart.setEnabled(false);
txtSessionStart.setClickable(false);
imageShareImageView.setVisibility(View.VISIBLE);
recordAudioImageView.setVisibility(View.VISIBLE);
imgEndSession.setVisibility(View.VISIBLE);
}
@Override
public void onFailure(Call<SessionHistoryResponse> call, Throwable t) {
t.printStackTrace();
progressDialog.dismiss();
imageShareImageView.setVisibility(View.GONE);
recordAudioImageView.setVisibility(View.GONE);
imgEndSession.setVisibility(View.GONE);
}
});
}
});
} else {
}
if (position == alreadystartPosition) {
layoutSessionStart.setClickable(false);
txtSessionStart.setClickable(false);
imageShareImageView.setVisibility(View.VISIBLE);
recordAudioImageView.setVisibility(View.VISIBLE);
imgEndSession.setVisibility(View.VISIBLE);
} else {
}
if (position == sessionendPosition) {
layoutSessionStart.setClickable(false);
txtSessionStart.setClickable(false);
// layoutSessionStart.setVisibility(View.VISIBLE);
txtSessionStart.setText("End session");
if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("audio")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutAudio);
} else if (sessionHistoryMesssage.getmMediaType().equalsIgnoreCase("photo")) {
params = (RelativeLayout.LayoutParams) layoutSessionStart.getLayoutParams();
params.addRule(RelativeLayout.BELOW, R.id.layoutImage);
} else {
}
imageShareImageView.setVisibility(View.GONE);
recordAudioImageView.setVisibility(View.GONE);
imgEndSession.setVisibility(View.GONE);
} else {
}
if (position == playposition) {
if (mBound) {
Log.v("service", "bound");
mHandler.removeCallbacks(null);
seekBar.setMax(mService.getrunningTime() / 1000);
Log.v("duration", mService.getrunningTime() + "");
playPauseImageView.setImageResource(R.drawable.stop_icon);
((PatientActivity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
if (mService.isPlaying()) {
num = mService.getDuration();
seekBar.setProgress(num / 1000);
runningTimerTextView.setText(convertMilliToMinutes(num));
// vhItemHolder.seekBar.setFocusable(false);
mHandler.postDelayed(this, 50);
} else {
playposition = -1;
mHandler.removeCallbacks(null);
seekBar.setProgress(0);
seekBar.setFocusable(false);
runningTimerTextView.setText("00:00");
playPauseImageView.setImageResource(R.drawable.play_icon);
}
}
});
} else {
Log.v("service", "not bound");
}
} else {
mHandler.removeCallbacks(null);
playPauseImageView.setImageResource(R.drawable.play_icon);
runningTimerTextView.setText("00:00");
seekBar.setMax(0);
}
}
}
Service class
public class LocalService extends Service {
boolean mBound = false;
private final IBinder mBinder = new LocalBinder();
private int timer;
private MediaPlayer mediaPlayer = new MediaPlayer();
private boolean isStopped = true;
// Random number generator
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
public LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
public int getrunningTime() {
return mediaPlayer.getDuration();
}
public int getDuration() {
// Log.v("player duration",timer+"");
if (mediaPlayer != null) {
if (!isStopped) {
Log.v("playing", (mediaPlayer.getCurrentPosition()) + "");
return mediaPlayer.getCurrentPosition();
} else {
// mediaPlayer.reset();
mHandler.removeCallbacks(null);
return 0;
}
} else {
Log.v("not playing", (mediaPlayer.getCurrentPosition()) + "");
mHandler.removeCallbacks(null);
return 0;
}
}
@Override
public void onCreate() {
super.onCreate();
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
isStopped = false;
//playAudio();
Log.v("max duration", timer + "");
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//mediaPlayer.stop();
isStopped = true;
mediaPlayer.reset();
//mediaPlayer.release();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isPlaying() {
if (mediaPlayer != null) {
try {
if (mediaPlayer.isPlaying()) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
} else {
return false;
}
}
public void playAudio(String path) {
Log.v("audio path",path);
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.reset();
try {
mediaPlayer.setDataSource(path);
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public void stopAudio() {
if (mediaPlayer != null) {
mediaPlayer.stop();
// mediaPlayer.reset();
isStopped = true;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void unbindService(ServiceConnection conn) {
super.unbindService(conn);
mediaPlayer.reset();
mediaPlayer.release();
}
@Override
public void onDestroy() {
super.onDestroy();
mediaPlayer.reset();
mediaPlayer.release();
}
}