Android - 音乐持续时间小于MediaPlayer持续时间

时间:2017-04-21 08:57:22

标签: android media-player android-mediaplayer seekbar duration

我正在尝试制作一个带有绑定服务的基本音乐播放器。问题是MP播放的时间越短。我比较了MP完成的时间,看到了发生了什么,但无法弄清楚原因。有人可以帮忙吗?

当MP完成时,这是我的logcat。

@Override
    public void onCompletion(MediaPlayer mp) {
        Toast.makeText(this, "Media Completed", Toast.LENGTH_SHORT).show();
        Log.i("TEST", "TOTAL DUR: " + mp.getDuration() + " CURRENT DUR: " + mp.getCurrentPosition() + "");
    }

I/TEST: TOTAL DUR: 193131 CURRENT DUR: 186932

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener, SeekBar.OnSeekBarChangeListener{


    private String msg = "Android : ";

    private TextView tvTime;
    private Button btnPlay, btnPause, btnRestart;
    private LocalService mService;
    private boolean mBound = false;

    // ----- seekbar variables -----------
    private SeekBar seekBar;
    private int seekMax;
    private boolean mBroadcastIsRegistered;

    // ---- broadcast action and intent for fromuser seekbar
    public static final String BROADCAST_SEEKBAR_FROMUSER = "ysfcyln.musicplayerdemo.send_seekbar_fromUser";
    Intent mIntent;



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

        tvTime = (TextView) findViewById(R.id.textView);

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

        btnPlay = (Button) findViewById(R.id.btn_play);
        btnPause = (Button) findViewById(R.id.btn_pause);
        btnRestart = (Button) findViewById(R.id.btn_restart);

        seekBar.setOnSeekBarChangeListener(this);

        btnPlay.setOnClickListener(this);
        btnPause.setOnClickListener(this);
        btnRestart.setOnClickListener(this);

        Log.d(msg, "The onCreate() event");
        Intent intent = new Intent(this, LocalService.class);
        startService(intent);

        // set up seekbar intent for broadcasting new position to service
        mIntent = new Intent(BROADCAST_SEEKBAR_FROMUSER);

    }


    /** Called when the activity is about to become visible. */
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(msg, "The onStart() event");
        Intent intent = new Intent(this, LocalService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    /** Called when the activity has become visible. */
    @Override
    protected void onResume() {
        // ---- register broadcast -----
        goRegisterBroadcast();

        super.onResume();
        Log.d(msg, "The onResume() event");

    }

    /** Called when another activity is taking focus. */
    @Override
    protected void onPause() {
        // ---- unregister broadcast ----
        unRegisterBroadcast();

        super.onPause();
        Log.d(msg, "The onPause() event");
    }

    /** Called when the activity is no longer visible. */
    @Override
    protected void onStop() {
        super.onStop();
        Log.d(msg, "The onStop() event");

    }

    /** Called just before the activity is destroyed. */
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(msg, "The onDestroy() event");
        Log.d("mbound value", mBound + "");
        if (mBound) {
            Intent intent=new Intent(this,LocalService.class);
            stopService(intent);
            unbindService(mConnection);
            mBound = false;
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_play:
                //do something
                if (mBound)
                mService.playSong2("http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood-piano.mp3");
                break;
            case R.id.btn_pause:
                //do something
                if (mBound)
                mService.pauseSong();
                break;
            case R.id.btn_restart:
                //do something
                if (mBound)
                mService.restartSong();
                break;

            default:
                break;
        }

    }

    /** Defines callbacks for service binding, passed to bindService() */
    public ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                                       IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    @Override
    public void onBackPressed(){
        // this moves to activity to the back of the stack, effectively pausing it
        moveTaskToBack(true);
    }


    // ---- updating position of seekbar from service
    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            updateUI(intent);
        }
    };

    private void updateUI(Intent intent){
        String counter = intent.getStringExtra("counter");
        String mediamax = intent.getStringExtra("mediamax");

        int seekProgress = Integer.parseInt(counter);
        seekMax = Integer.parseInt(mediamax);

        seekBar.setMax(seekMax);
        seekBar.setProgress(seekProgress);

        final int HOUR = 60*60*1000;
        final int MINUTE = 60*1000;
        final int SECOND = 1000;

        int durationInMillis = seekMax;
        int curVolume = seekProgress;

        int durationHour = durationInMillis/HOUR;
        int durationMint = (durationInMillis%HOUR)/MINUTE;
        int durationSec = (durationInMillis%MINUTE)/SECOND;

        int currentHour = curVolume/HOUR;
        int currentMint = (curVolume%HOUR)/MINUTE;
        int currentSec = (curVolume%MINUTE)/SECOND;

        if(durationHour > 0){
            tvTime.setText(" 1 = "+String.format("%02d:%02d:%02d/%02d:%02d:%02d",
                    currentHour,currentMint,currentSec, durationHour,durationMint,durationSec));
        }else{
            tvTime.setText(" 1 = "+String.format("%02d:%02d/%02d:%02d",
                    currentMint,currentSec, durationMint,durationSec));
        }
    }

    // --- unregister receiver for seekbar ---
    private void unRegisterBroadcast(){
        if(mBroadcastIsRegistered){
            try {
                unregisterReceiver(broadcastReceiver);
                mBroadcastIsRegistered = false;
            } catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    // --- register receiver for seekbar ---
    private void goRegisterBroadcast(){
        registerReceiver(broadcastReceiver, new IntentFilter(mService.BROADCAST_ACTION));
        mBroadcastIsRegistered = true;
    }

    // Override methods for seekbar on change listener
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if (fromUser){
            int seekPos = seekBar.getProgress();
            mIntent.putExtra("seekpos", seekPos);
            sendBroadcast(mIntent);
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {

    }

}

LocalService.java

public class LocalService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener{

    private MediaPlayer player;


    public LocalService() {
    }

    // Returns the MyService instance
    public class LocalBinder extends Binder {

        public LocalService getService(){
            return LocalService.this;
        }

    }

    private IBinder mBinder = new LocalBinder();

    // ---- SeekBar Variables --------------
    int mediaPosition;
    int mediaMax;
    private final Handler handler = new Handler();
    public static final String BROADCAST_ACTION = "ysfcyln.musicplayerdemo.seekprogress";
    Intent seekIntent;


    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        //throw new UnsupportedOperationException("Not yet implemented");
        Log.i("Service Demo", "In onBind");
        return mBinder;
    }

    /** Called when the service is being created. */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("Service Demo", "Service Created");

        player = new MediaPlayer();
        initMusicPlayer();

        // ----- Setup intent for seekbar -----------
        seekIntent = new Intent(BROADCAST_ACTION);

        // --- register for fromuser seekbar ----
        registerReceiver(broadcastReceiver, new IntentFilter(MainActivity.BROADCAST_SEEKBAR_FROMUSER));
    }

    /** The service is starting, due to a call to startService() */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        //return super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }


    /** Called when The service is no longer used and is being destroyed */
    @Override
    public void onDestroy() {
        // stop the seekbar handler from sending updates to UI
        handler.removeCallbacks(sendUpdatesToUI);
        // unregister receiver to user input from seekbar
        unregisterReceiver(broadcastReceiver);

        super.onDestroy();
        Log.i("Service Demo", "Service Destroyed");
    }


    /** Called when all clients have unbound with unbindService() */
    @Override
    public boolean onUnbind(Intent intent) {
        Log.i("Service Demo", "In onUnbind");
        player.stop();
        player.reset();
        player.release();
        return super.onUnbind(intent);
    }

    /** Called when a client is binding to the service with bindService()*/
    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }


    // to initialize the media class
    public void initMusicPlayer(){

        player.setWakeMode(getApplicationContext(),
                PowerManager.PARTIAL_WAKE_LOCK);
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);

        player.setOnPreparedListener(this);
        player.setOnCompletionListener(this);

    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        //start playback
        mp.start();
        // ---- set up seekbar handler ----
        setUpHandler();
    }

    // -------- Send seekbar info to Activity ------
    private void setUpHandler(){
        handler.removeCallbacks(sendUpdatesToUI);
        handler.postDelayed(sendUpdatesToUI, 1000); // 1 Second
    }

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

            LogMediaPosition();
            handler.postDelayed(this,1000); // 1 Second

        }
    };

    private void LogMediaPosition(){
        if(player.isPlaying()){
            mediaPosition = player.getCurrentPosition();
            mediaMax = player.getDuration();

            seekIntent.putExtra("counter", String.valueOf(mediaPosition));
            seekIntent.putExtra("mediamax", String.valueOf(mediaMax));
            sendBroadcast(seekIntent);
        }
    }


    //  ---------- Receive seekbar position if it has been changed by the user in the activity ----
    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            updateSeekPos(intent);
        }
    };

    private void updateSeekPos(Intent intent){
        int seekPos = intent.getIntExtra("seekpos", 0);
        if(player.isPlaying()){
            handler.removeCallbacks(sendUpdatesToUI);
            player.seekTo(seekPos);
            setUpHandler();
        }
    }

    public void playSong(){
        //play a song
        player.reset();

        String songUrl = "http://www.mfiles.co.uk/mp3-downloads/edvard-grieg-peer-gynt1-morning-mood-piano.mp3";

        try{
            player.setDataSource(getApplicationContext(), Uri.parse(songUrl));
        }
        catch(Exception e){
            Log.e("MUSIC SERVICE", "Error setting data source", e);
        }

        player.prepareAsync();
    }

    public void pauseSong(){
        if(player.isPlaying()){
            player.pause();
        } else {
            player.start();
        }
    }

    public void restartSong(){
        if(player.isPlaying()){
            player.stop();
            player.release();
        } else {
            player.release();
        }
    }

    // With input
    public void playSong2(String songUrl){
        //play a song
        player.reset();

        try{
            player.setDataSource(getApplicationContext(), Uri.parse(songUrl));
        }
        catch(Exception e){
            Log.e("MUSIC SERVICE", "Error setting data source", e);
        }

        player.prepareAsync();
    }

    @Override
    public void onCompletion(MediaPlayer mp) {
        Toast.makeText(this, "Media Completed", Toast.LENGTH_SHORT).show();
        Log.i("TEST", "TOTAL DUR: " + mp.getDuration() + "CURRENT DUR: " + mp.getCurrentPosition() + "");
    }

}

我用两个设备测试了它,三星Galaxy A7和三星Galaxy S4。歌曲持续时间是3:13,A7完成3:12,S4完成3:06

0 个答案:

没有答案