AnhVoLeDuy AnhVoLeDuy - 2 months ago 9
Android Question

Android: Can not set text for TextView on runOnUiThread

In my music player app, i have a method to configure for a TextView and a SeekBar. In the Runnable, i check for onCompletion in the Service instance. So that, when a song is completed, the TextView and SeekBar can be reset. It's ok in the firs time i open the Activity. But, when i destroyed this activity, i unbind the Service instance, so, when i started new Activity, it connected to the previous Service, the below method is called again. In this case, the TextView and the SeekBar can not be reset. A checked it by make two Toast. It show the new song title like i want. But it's not be set on TextView and SeekBar.


This is my Activity


public class SongsPlayerActivity extends AppCompatActivity {
private ImageView
iv_background;
private ImageView
iv_start_and_pause, iv_next, iv_previous, iv_hate, iv_love;
private TextView
tv_song_title;
private SeekBar sb_song_duration;

private Bundle bundle;
private String al_id,
al_path,
ar_path;
private Bitmap bitmap;
private ArrayList<Song> songs;
private Runnable getSongsInAlbum = new Runnable() {
@Override
public void run() {
new AlbumImageLoader().execute(Variables.IP_ADDRESS +
"/RESOURCES" +
"/ALBUMS" +
"/" + ar_path +
"/" + al_path +
"/image.png");

try {
new SongsLoader().execute(Variables.IP_ADDRESS +
"/Project_1_Web_Service" +
"/rest" +
"/Song" +
"/getSongsInAlbum" +
"/" + al_id).get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
private MusicService musicService;
private Intent intent;
private boolean musicBound = false;
public ServiceConnection musicConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
MusicService.MusicBinder musicBinder = (MusicService.MusicBinder) iBinder;
musicService = musicBinder.getService();
musicService.setAndPlay(ar_path, al_path, songs);

setAndUpdateUI();

musicBound = true;
if(musicService.getSongPaused()){
iv_start_and_pause.setImageResource(R.drawable.start);
}
else {
iv_start_and_pause.setImageResource(R.drawable.pause);
}
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
musicBound = false;
}
};

private Handler handler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_songs_player);

iv_background = (ImageView) findViewById(R.id.iv_background);
iv_next = (ImageView) findViewById(R.id.iv_next);
iv_previous = (ImageView) findViewById(R.id.iv_previous);
iv_start_and_pause = (ImageView) findViewById(R.id.iv_start_and_pause);
iv_hate = (ImageView) findViewById(R.id.iv_hate);
iv_love = (ImageView) findViewById(R.id.iv_love);
tv_song_title = (TextView) findViewById(R.id.tv_song_title);
sb_song_duration = (SeekBar) findViewById(R.id.sb_song_duration);

getAlbumInfo();

loadSongsInAlbum();

iv_next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
playNextSong();
}
});

iv_previous.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
playPreviousSong();
}
});

iv_start_and_pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startAndPauseSong();
}
});

sb_song_duration.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(fromUser){
musicService.seekTo(progress * 1000);
}
}
});
}

@Override
protected void onStart() {
super.onStart();
if(intent == null){
intent = new Intent(this, MusicService.class);
startService(intent);
bindService(intent,
musicConnection,
Context.BIND_AUTO_CREATE);
}
}

@Override
protected void onDestroy(){
unbindService(musicConnection);
super.onDestroy();
}

public class AlbumImageLoader extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... strings) {
try {
URL u = new URL(strings[0]);
bitmap = BitmapFactory.decodeStream(u.openConnection().getInputStream());
//bitmap = ImageHelper.blurBitmap(getBaseContext(), bitmap, 2f);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

@Override
protected void onPostExecute(String s) {
iv_background.setImageBitmap(bitmap);
}
}

public class SongsLoader extends AsyncTask<String, Integer, String>{

@Override
protected String doInBackground(String... strings) {
FileReader fileReader = new FileReader();
String s = fileReader.readFile(strings[0]);
return s;
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
JSONArray albumJSONArray = new JSONArray(s);
for(int i = 0; i < albumJSONArray.length(); i++){
JSONObject jsonObject = albumJSONArray.getJSONObject(i);
songs.add(new Song(
jsonObject.getString("s_title"),
jsonObject.getString("ar_path"),
jsonObject.getString("al_path"),
jsonObject.getString("s_path")
));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}

private void getAlbumInfo(){
bundle = getIntent().getExtras();
al_id = bundle.getString("al_id");
al_path = bundle.getString("al_path");
ar_path = bundle.getString("ar_path");
}

private void loadSongsInAlbum(){
songs = new ArrayList<>();
runOnUiThread(getSongsInAlbum);
}

private void playNextSong(){
musicService.playNextSong();
iv_start_and_pause.setImageResource(R.drawable.pause);

setAndUpdateUI();
}

private void playPreviousSong(){
musicService.playPreviousSong();
iv_start_and_pause.setImageResource(R.drawable.pause);

setAndUpdateUI();
}

private void startAndPauseSong(){
if(musicService.getSongPaused()){
musicService.startSong();
musicService.setSongPaused(false);
iv_start_and_pause.setImageResource(R.drawable.pause);
}
else {
musicService.pauseSong();
musicService.setSongPaused(true);
iv_start_and_pause.setImageResource(R.drawable.start);
}
}

private void setAndUpdateUI(){
sb_song_duration.setMax(musicService.getSongDuration()/1000);
tv_song_title.setText(musicService.getSongTitle());
runOnUiThread(new Runnable() {
@Override
public void run() {
sb_song_duration.setProgress(musicService.getCurrentPosition() / 1000);
if(musicService.getSongCompleted()){
sb_song_duration.setMax(musicService.getSongDuration() / 1000);
tv_song_title.setText(musicService.getSongTitle());
musicService.setSongCompleted(false);
}
handler.postDelayed(this, 1000);
}
});
}

Answer

Try using this approach

private Runnable updateUI = new Runnable() {
            @Override
            public void run() {

                sb_song_duration.setMax(musicService.getSongDuration() / 1000);
                tv_song_title.setText(musicService.getSongTitle());
                sb_song_duration.setProgress(musicService.getCurrentPosition() / 1000);

                if(musicService.getSongCompleted()){
                    musicService.setSongCompleted(false);
                }
                handler.postDelayed(this, 1000);
            }
        };


private void setAndUpdateUI(){
    runOnUiThread(updateUI);
}