簡體   English   中英

Android-SeekBar和MediaPlayer

[英]Android - SeekBar and MediaPlayer

我需要在我的App中將SeekBarMediaPlayer連接起來。

我通過xml這樣設置了SeekBar:

<SeekBar
        android:id="@+id/song_seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"/>

並按照這個答案來實現它。

這是我的代碼:

public class Song_main extends AppCompatActivity {
private final int SONG_REQUEST_CODE = 1;

private Uri song;
private TextView selectSong;
private SeekBar seekBar;
private Handler handler;
private MediaPlayer mediaPlayer;


private boolean repeatPressedTwice = false;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.app_bar_song_main);

    Toolbar toolbar = (Toolbar) findViewById(R.id.song_main_toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayShowTitleEnabled(false);

    seekBar = (SeekBar) findViewById(R.id.song_seekbar);
    handler = new Handler();

    notSelected();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.song, menu);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if (id == R.id.song_plus) {
        Intent selectIntent = new Intent(Intent.ACTION_GET_CONTENT);
        selectIntent.setType("audio/*");
        startActivityForResult(selectIntent, SONG_REQUEST_CODE);
    }

    return true;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == SONG_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        if ((data != null) && (data.getData()!=null)) {
            song = data.getData();
            setup();
        }
    }
}

private void notSelected() {
    selectSong = (TextView) findViewById(R.id.select_song_textview);
    selectSong.setText(getResources().getString(R.string.song_not_selected));
}

public void onPlayButtonClicked(View v) {
    ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
    if (!mediaPlayer.isPlaying()) {
        mediaPlayer.start();
        pb.setImageResource(R.drawable.pause);

        updateSeekBar();

    } else {
        mediaPlayer.pause();
        pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
    }
}

public void onControlsClicked(View v) {
    if (v.getId() == R.id.fast_forward) {
        int pos = mediaPlayer.getCurrentPosition();
        pos += 1500;
        mediaPlayer.seekTo(pos);
    }
    else if (v.getId() == R.id.fast_backward) {
        int pos = mediaPlayer.getCurrentPosition();
        pos -= 1500;
        mediaPlayer.seekTo(pos);
    }
    else if (v.getId() == R.id.skip_backward) {
        mediaPlayer.seekTo(0);
    }
}

public void onRepeatClicked(View v) {
    if (!repeatPressedTwice) {
        // TODO: change visual color of repeat button
        mediaPlayer.setLooping(true);
        Toast.makeText(this, "repeat enabled", Toast.LENGTH_SHORT).show();
        repeatPressedTwice = true;
    } else {
        mediaPlayer.setLooping(false);
    }

}

private void setup() {
    /* the song has been select setup the interface */


    /* displays song name in title */
    TextView titleView = (TextView) findViewById(R.id.song_appbar_title);
    String songName;

    ContentResolver contentResolver = this.getContentResolver();
    Cursor cursor = contentResolver.query(song, null, null, null, null);

    if (cursor != null && cursor.moveToFirst()) {
        songName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
        titleView.setText(songName);
    }


    /* removes the notSelected String */
    selectSong.setVisibility(View.GONE);

    /* setup media player */
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    try {
        mediaPlayer.setDataSource(getApplicationContext(), song);
        mediaPlayer.prepareAsync();
    } catch (IOException e) {
        Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show();
    }

    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            /* show media player layout */
            RelativeLayout mpl = (RelativeLayout) findViewById(R.id.media_player_layout);
            mpl.setVisibility(View.VISIBLE);

            mediaPlayer.start();
            ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
            pb.setImageResource(R.drawable.pause);

        }
    });

    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
            pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
        }
    });



    seekBar = (SeekBar) findViewById(R.id.song_seekbar);
    seekBar.setMax(mediaPlayer.getDuration()); 

    updateSeekBar();


}

private void updateSeekBar() {
    seekBar.setProgress(mediaPlayer.getCurrentPosition()/1000);
    handler.postDelayed(runnable, 1000);
}

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        updateSeekBar();
    }
};


@Override
public void onStop() {
    super.onStop();
    if (mediaPlayer!=null)
        mediaPlayer.stop();
}
}

該過程從onOptionsItemSelected方法開始。

seekBar的行為正確,每秒增加一次。 現在的問題是,它在歌曲完成之前就完成了。

我嘗試添加

seekBar.setMax(mediaPlayer.getDuration());

setup方法中,但這會導致欄完全不移動。

您需要定義單獨的Runnable並在MediaPlayer啟動后每隔x毫秒(取決於您)觸發一次。

定義一個函數updateSeekbar

private void updateSeekBar() {
    audioSeek.setProgress(player.getCurrentPosition());
    txtCurrentTime.setText(milliSecondsToTimer(player.getCurrentPosition()));
    seekHandler.postDelayed(runnable, 50);
}

Runnable

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        updateSeekBar();
    }
};

現在,您只需要在播放開始時調用一次updateSeekbar 在您的情況下:

public void onPlayButtonClicked(View v) {
    ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
    if (!mediaPlayer.isPlaying()) {
        mediaPlayer.start();
        pb.setImageResource(R.drawable.pause);

        updateSeekBar();

    } else {
        mediaPlayer.pause();
        pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
    }
}

FYI

函數milliSecondsToTimer工作原理如下

private String milliSecondsToTimer(long milliseconds) {
    String finalTimerString = "";
    String secondsString = "";

    // Convert total duration into time
    int hours = (int) (milliseconds / (1000 * 60 * 60));
    int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
    int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000);
    // Add hours if there
    if (hours > 0) {
        finalTimerString = hours + ":";
    }

    // Prepending 0 to seconds if it is one digit
    if (seconds < 10) {
        secondsString = "0" + seconds;
    } else {
        secondsString = "" + seconds;
    }

    finalTimerString = finalTimerString + minutes + ":" + secondsString;

    // return timer string
    return finalTimerString;
}

UPDATE

您在錯誤的位置調用了setMax 更新setup()函數,如下所示

private void setup() {
    /* the song has been select setup the interface */
    /* displays song name in title */
    TextView titleView = (TextView) findViewById(R.id.song_appbar_title);
    String songName;

    ContentResolver contentResolver = this.getContentResolver();
    Cursor cursor = contentResolver.query(song, null, null, null, null);

    if (cursor != null && cursor.moveToFirst()) {
        songName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
        titleView.setText(songName);
    }


    /* removes the notSelected String */
    selectSong.setVisibility(View.GONE);

    /* setup media player */
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    try {
        mediaPlayer.setDataSource(getApplicationContext(), song);
        mediaPlayer.prepareAsync();
    } catch (IOException e) {
        Toast.makeText(this, "file not found", Toast.LENGTH_SHORT).show();
    }

    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
        /* show media player layout */
            seekBar.setMax(mediaPlayer.getDuration());

            RelativeLayout mpl = (RelativeLayout) findViewById(R.id.media_player_layout);
            mpl.setVisibility(View.VISIBLE);
            mediaPlayer.start();

            updateSeekBar();


            ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
            pb.setImageResource(R.drawable.pause);

        }
    });

    mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mp) {
            ImageButton pb = (ImageButton) findViewById(R.id.song_play_button);
            pb.setImageResource(R.drawable.ic_play_arrow_white_24dp);
        }
    });

}

播放歌曲時需要更新搜索欄

public void updateProgressBar() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mHandler.postDelayed(mUpdateTimeTask, 100);
            }
        });

    }  

下面的Runnable方法來更新seekbar

private Runnable mUpdateTimeTask = new Runnable() {
        public void run() {
            if (MusicService.isRunning()) {
                duration = MusicService.getDur();
                long currSongPosition = MusicService.getPosn();
                totTime.setText(Utility.milliSecondsToTimer(duration));
                fromTime.setText(Utility.milliSecondsToTimer(currSongPosition));
                int progress = Utility.getProgressPercentage(currSongPosition, duration);
            songProgressBar.setProgress(progress);
            updateProgressBar();
        }
    }
};

使用以下功能,您可以從歌曲當前位置和歌曲持續時間獲得進度百分比

 public static int getProgressPercentage(long currentDuration, long totalDuration) {
        Double percentage;
        long currentSeconds = (int) (currentDuration / 1000);
        long totalSeconds = (int) (totalDuration / 1000);
        percentage = (((double) currentSeconds) / totalSeconds) * 100;
        return percentage.intValue();
    }

您已經實現了OnSeekBarChangeListener並在onCreate()添加以下行:

seekBar = (SeekBar) findViewById(R.id.seekBar);

並覆蓋onProgressChanged()方法,在此方法中,您可以使用以下行在搜尋欄中設置進度:

mPlayer.seekTo(progress); 
seekBar.setProgress(progress);

要么

在初始化MediaPlayer並例如按下播放按鈕之后,您應該創建一個處理程序並發布可運行文件,以便可以使用MediaPlayer的當前位置來更新SeekBar(在UI線程本身中),如下所示:

private Handler mHandler = new Handler();
//Make sure you update Seekbar on UI thread
MainActivity.this.runOnUiThread(new Runnable(){
    @Override
    public void run() {
        if(mMediaPlayer != null){
            int mCurrentPosition = mMediaPlayer.getCurrentPosition() / 1000;
            mSeekBar.setProgress(mCurrentPosition);
        }
    mHandler.postDelayed(this, 1000);
    }
});

並每秒更新一次該值。

如果在用戶拖動SeekBar時需要更新MediaPlayer的位置,則應將OnSeekBarChangeListener添加到SeekBar並在其中進行操作:

mSeekBar.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(mMediaPlayer != null && fromUser){
             mMediaPlayer.seekTo(progress * 1000);
     }
  }
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM