У меня есть FirestoreRecyclerAdapter
внутри фрагмента. Сначала я заполняю элементы в моем FirestoreRecyclerAdapter
из Firestore
, затем для каждого элемента в моем RecyclerView
у меня есть от Url
до FirebaseStorage
, где я храню записанное звуковое сообщение. Как я могу воспроизвести это сообщение, когда пользователь нажимает кнопку внутри моего элемента RecyclerView
, и у него есть AsyncTask
, связанный с воспроизведением этого аудио-обновления, SeekBar
, найденный в том же элементе RecyclerView?
Мне удалось воспроизвести звук, используя MediaPlayer
, но я не могу получить AsyncTask
для обновления моего UI
. Вот 'мой AsyncTask
:
открытый класс MyTask расширяет AsyncTask {
private MediaPlayer mPlayer;
private Callback mCb;
private FirebaseFirestore db;
private StorageReference storageRef;
private SeekBar seekBar;
private Post post;
public interface Callback {
void onDataLoaded(Integer result);
}
public MyTask (final Post post, Callback cb, SeekBar seekBar){
this.post = post;
this.mCb = cb;
this.seekBar = seekBar;
// Initialize media player
mPlayer = new MediaPlayer();
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
db = FirebaseFirestore.getInstance();
DocumentReference postRef = db.collection("Posts")
.document(post.getPost_Id());
Map<String, Object> map = new HashMap<>();
map.put("score", FieldValue.increment(2));
map.put("listens", FieldValue.increment(1));
postRef.update(map);
}
});
}
@Override
protected String doInBackground(String... strings) {
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try{ mPlayer.setDataSource(strings[0]);} catch (Exception e) {e.printStackTrace();}
// wait for media player to get prepare
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
// Get the current audio stats
for(int i =0; i<mp.getDuration(); i = mp.getCurrentPosition()) {
//int duration = mPlayer.getDuration() / 1000; // In milliseconds
//int due = (mPlayer.getDuration() - mPlayer.getCurrentPosition()) / 1000;
//int pass = duration - due;
int mCurrentPosition = mp.getCurrentPosition(); // In milliseconds
//seekBar.setProgress(mCurrentPosition);
publishProgress(mCurrentPosition);
try {
Thread.sleep(1);
} catch (Exception e){
e.printStackTrace();
}
}
}
});
mPlayer.prepareAsync();
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
//Using the callback, I get data logged on the console but the
//item on the RecyclerView is not updated
mCb.onDataLoaded(values[0]);
//Pass the Seekbar to the AsyncTas doesnt update
//seekBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
} }
Я реализую Callback
интерфейс в ViewHolder
моего FirestoreRecyclerAdapter
. Вот мой адаптер:
private class PostViewHolder extends RecyclerView.ViewHolder implements MyTask.Callback {
private PostViewHolder holder;
private LinearLayout root, llp,;
private RelativeLayout rlp;
private TextView tv_due, tv_pass;
private Button btn_play;
private SeekBar seekBar;
private FirebaseFirestore db;
private final StorageReference storageRef;
public PostViewHolder(@NonNull View itemView) {
super(itemView);
root = itemView.findViewById(R.id.list_root);
llp = root.findViewById(R.id.llp);
rlp = root.findViewById(R.id.rlp);
btn_play = llp.findViewById(R.id.btn_play);
tv_due = rlp.findViewById(R.id.tv_due);
tv_pass = rlp.findViewById(R.id.tv_pass);
seekBar = rlp.findViewById(R.id.seek_bar);
db = FirebaseFirestore.getInstance();
storageRef = FirebaseStorage.getInstance().getReference();
}
@Override
public void onDataLoaded(Integer result) {
Log.d("NEW TAG", result.toString());
holder.seekBar.setProgress(result);
}
void setData(final Post post, final PostViewHolder holder) {
this.holder = holder;
btn_play.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (btn_play.getText().equals("Play")) {
playMusic(seekBar, tv_pass, tv_due, post, mPlayer, holder);
}
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if(mPlayer!=null && b){
mPlayer.seekTo(i*1000);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
А playMusic()
выглядит следующим образом:
private void playMusic(final Post post, final MediaPlayer mPlayer, final MyTask.Callback cb) {
final FirebaseStorage storage = FirebaseStorage.getInstance();
StorageReference storageRef = storage.getReference().child("/" + post.getAudio());
storageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
final String url = uri.toString();
MyTask task = new MyTask(post, cb, seekBar);
task.execute(url);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i("TAG", e.getMessage());
}
});
}