【问题标题】:Android: SeekBar is not updated using a Handler on 4.1.2 DeviceAndroid:未使用 4.1.2 设备上的处理程序更新 SeekBar
【发布时间】:2013-08-21 15:44:31
【问题描述】:

朋友们,我正在开发一个播放小型 mp3 配乐(播客)的应用程序。现在,我在下面显示的代码可以在 Android 3.2 上正常运行。但是在 Android 4.1.2 上,SeekBar 没有被处理程序实例更新。我在 SeekBar 中读到了一个 bug 导致这个问题,但它应该从 Android 3.2 开始修复。任何帮助或建议将不胜感激。这是我的代码:

public class PodcastDetailFragment extends BaseFragment {
    private MediaPlayer mediaPlayer = null;
    private Button playPauseButton = null;
    private SeekBar seekBar = null;
    private TextView timeView = null;
    private int totalDuration = 0;
    private Bundle data;

    private Handler handler=new Handler();

    private Runnable runnable  = new Runnable() {
        public void run() {
            int progress = mediaPlayer.getCurrentPosition();

            seekBar.setProgress(progress);

            int hours = ((progress/1000)/60)/60;
            int minutes = ((progress/1000)/60)%60;
            int seconds = ((progress/1000)%60)%60;
            String hoursString = (hours<10)?"0":"";
            String minutesString = (minutes<10)?"0":"";
            String secondsString = (seconds<10)?"0":"";

            timeView.setText(hoursString+hours+":"+minutesString+minutes+":"+secondsString+seconds);
            handler.postDelayed(this, 100);

        }
    };

    public static PodcastDetailFragment newInstance(Bundle bundle) {
        PodcastDetailFragment f = new PodcastDetailFragment();
        f.setArguments(bundle);
        return f;
    }

    /**
     * When creating, retrieve this instance's number from its arguments.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        data = getArguments();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {

        getView().findViewById(R.id.preparing_track_progress_bar).setVisibility(View.VISIBLE);

        super.onActivityCreated(savedInstanceState);

    }

    @Override
    public void onPause() {
        super.onPause();
        if (mediaPlayer != null) {
            LogUtils.d("Podcast MediaPlayer", "stop() inside the onPause() was called");
            mediaPlayer.stop();
        }
    }

    @Override
    public void onDestroy() {
        LogUtils.d("Podcast MediaPlayer", "release() was called");
        mediaPlayer.release();
        super.onDestroy();
    }



    /**
     * The Fragment's UI is just a simple text view showing its instance number.
     */
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.podcasts_details, container, false);


        TextView dv = (TextView) v.findViewById(R.id.durationView);
            dv.setText(data.getString("duration"));

        timeView = (TextView) v.findViewById(R.id.timeView);
            timeView.setText("00:00:00");

            playPauseButton = (Button) v.findViewById(R.id.playPauseButtonView);
            playPauseButton.setOnClickListener(new OnClickListener() {
                public void onClick(View arg0) {
                    if (mediaPlayer.isPlaying()) {
                        mediaPlayer.pause();
                        playPauseButton.setText(getResources().getString(
                                R.string.play));
                    } else {

                        mediaPlayer.start();
                        playPauseButton.setText(getResources().getString(
                                R.string.pause));
                    }
                }
            });
            seekBar = (SeekBar) v.findViewById(R.id.seekBarView);
            seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
                public void onStopTrackingTouch(SeekBar seekBar) {
                }

                public void onStartTrackingTouch(SeekBar seekBar) {
                }

                public void onProgressChanged(SeekBar seekBar, int progress,
                        boolean fromUser) {
                    if (fromUser) {
                        mediaPlayer.seekTo(progress);

                    }
                }
            });

            mediaPlayer =new MediaPlayer();

            mediaPlayer
                    .setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                        public void onPrepared(MediaPlayer mp) {
                            totalDuration = mp.getDuration();
                            seekBar.setMax(totalDuration);
                            playPauseButton.setEnabled(true);
                            try{
                            getView().findViewById(R.id.preparing_track_progress_bar).setVisibility(View.INVISIBLE);
                            }catch(Exception ex){
                                ex.printStackTrace();
                            }
                            handler.postDelayed(runnable, 100);

                        }

                    });
            mediaPlayer.setDataSource(Uri.parse(data.getString("podcast_url")).toString());
            playPauseButton.setEnabled(false);
            mediaPlayer.prepareAsync();






        return v;




    }




}

【问题讨论】:

    标签: android media-player handler progress seekbar


    【解决方案1】:

    您应该使用 AsyncTask 或 Service(以防音乐在后台播放)而不是带有 Handler 的 Worker Thread。 AsyncTask 的 onProgressUpdate 方法非常有用,您可以使用它来根据音频文件的进度更新 Bar。

    这是一个 AsyncTask 的基本示例以及您应该如何使用它:

    private class TestAsyncTask extends AsyncTask<Void, Integer, Void> {
    
    @Override
    protected Void doInBackground(Void... arg0) {
        for(int i=0; i<songDuration; i++){
          doSomething();
          publishProgress(i);
        }
        return null;
    }
    
    @Override
    protected void onProgressUpdate(Integer... progress) {
        //UPDATE BAR
    }
    
    @Override
    protected void onPostExecute(Void result) {
        //DO SOMETHING WHEN FINISHED PLAYING
    }
    }
    

    无论如何,这是官方文档:http://developer.android.com/reference/android/os/AsyncTask.html

    【讨论】:

    • 我想每 100 毫秒更新一次 seekBar 以显示曲目正在播放的时间,那么您想如何通过使用一次的 AsyncTask 来实现它?
    • asynctask 可以随心所欲地存在。您需要每 100 毫秒发布一次进度。异步任务只存在一次的事实与此无关。
    • 如您所见,使用 Handler 的方法一点也不假。
    【解决方案2】:

    我已经解决了这个问题。 SeekBar 还可以。只是当您下载整首曲目时才给出曲目的长度的问题。因此,要正确显示 SeekBar 上的进度,您需要知道轨道的长度。因此,您获取轨道的长度,然后调用 seekBar.setMax(lenghtOfTrack) 并通过方法 setProgress(progress) 更新进度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-23
      • 2018-08-09
      相关资源
      最近更新 更多