安卓开发:媒体播放器在"hold mode"打开/关闭后无法正常工作



在Hold模式打开/关闭后,我的Android应用程序无法再次播放音乐。

我的代码一开始运行良好(歌曲听起来)。但是当用户按下保持按钮时,应用程序无法继续播放(保持后再次返回屏幕时)。

通过调试,我检查了当你按下保持按钮(重新启动手机)时,你进入了onResume内部(很明显),但mediaPlayer.prepare()抛出了java.lang.IllegalStateException(捕获在捕获块中),并显示消息:prepareSynccalled in state 0

onResume()之后,我调用了方法play(),它抛出了以下错误:

尝试在错误的状态下执行seekTo

错误(-38,0)

尝试在没有有效媒体播放器的情况下调用getDuration

错误(-38,0)

有什么想法吗?:S

这是我的代码:Fragment.java

public class FragmentMediaPlayer extends Fragment implements OnSeekBarChangeListener {
    private MediaPlayer mediaPlayer;
    public TextView duration;
    private double timeElapsed = 0, finalTime = 0;
    private int forwardTime = 5000, backwardTime = 5000;
    private Handler durationHandler = new Handler();
    private SeekBar seekBar;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View rootView = inflater.inflate(R.layout.media_player, container,
                false);
        // initialize views
        initializeViews(rootView);
        return rootView;
    }
    public void initializeViews(View rootView) {
        mediaPlayer = MediaPlayer.create(getActivity(), R.raw.song);
        try {
            mediaPlayer.prepare();
        } catch (IllegalStateException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finalTime = mediaPlayer.getDuration();
        duration = (TextView) rootView.findViewById(R.id.songDuration);
        duration.setText(String.format(
                "%d min, %d sec",
                0,0));
        
        seekBar = (SeekBar) rootView.findViewById(R.id.seekBar);
        seekBar.setMax((int) finalTime);
        seekBar.setOnSeekBarChangeListener(this);
        
        ImageButton playButton = (ImageButton) rootView.findViewById(R.id.media_play);
        playButton.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         play();
                     } 
           }); 
        
        ImageButton media_pause = (ImageButton) rootView.findViewById(R.id.media_pause);
        media_pause.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         pause(v);
                     } 
           }); 
        
        ImageButton media_ff = (ImageButton) rootView.findViewById(R.id.media_ff);
        media_ff.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         forward(v);
                     } 
           }); 
        
        ImageButton media_rew = (ImageButton) rootView.findViewById(R.id.media_rew);
        media_rew.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         rewind(v);
                     } 
           }); 
    }
    // play mp3 song
    public void play() {        
        timeElapsed = mediaPlayer.getCurrentPosition();
        seekBar.setProgress((int) timeElapsed);
        mediaPlayer.seekTo((int) timeElapsed) ;
        mediaPlayer.start();
        durationHandler.postDelayed(updateSeekBarTime, 100);
    }
    // handler to change seekBarTime
    private Runnable updateSeekBarTime = new Runnable() {
        public void run() {
            // get current position
            timeElapsed = mediaPlayer.getCurrentPosition();
            // set seekbar progress
            seekBar.setProgress((int) timeElapsed);
            // set time remaing
            //double timeRemaining = finalTime - timeElapsed;
            duration.setText(String.format(
                    "%d min, %d sec",
                    TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed),
                    TimeUnit.MILLISECONDS.toSeconds((long) timeElapsed)
                            - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
                                    .toMinutes((long) timeElapsed))));
            // repeat yourself that again in 100 miliseconds
            durationHandler.postDelayed(this, 100);         
        }
    };
    
    // pause mp3 song
    public void pause(View view) {
        mediaPlayer.pause();    
        timeElapsed = mediaPlayer.getCurrentPosition();
    }
    // go forward at forwardTime seconds
    public void forward(View view) {
        // check if we can go forward at forwardTime seconds before song endes
        if ((timeElapsed + forwardTime) <= finalTime) {
            timeElapsed = timeElapsed + forwardTime;
            // seek to the exact second of the track
            mediaPlayer.seekTo((int) timeElapsed);
        }
    }
    // go backwards at backwardTime seconds
    public void rewind(View view) {
        // check if we can go back at backwardTime seconds after song starts
        if ((timeElapsed - backwardTime) > 0) {
            timeElapsed = timeElapsed - backwardTime;
            // seek to the exact second of the track
            mediaPlayer.seekTo((int) timeElapsed);
        }
    }   
    @Override
    public void onResume() {
        super.onResume();
        try {
            mediaPlayer.prepare();
        } catch (IllegalStateException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        play();
    }
    
    @Override
    public void onPause() {
        super.onPause();
        mediaPlayer.pause();
    }
    @Override
    public void onStop() {
        // Stop updates and Disconnect from LocationServices
        mediaPlayer.stop();
        durationHandler.removeCallbacks(updateSeekBarTime);
        super.onStop();
    }
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
        if(fromUser) { 
            mediaPlayer.seekTo(progress); 
            seekBar.setProgress(progress);
        }
    }
    
    @Override
    public void onStartTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
        
    }
    @Override
    public void onStopTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
        
    }

这是我的布局.xml:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    android:orientation="vertical" >
<LinearLayout 
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical">
    <TextView
        android:id="@+id/songName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="@string/play_text" />
    <TextView
        android:id="@+id/songDuration"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />
    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="30dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >
        <ImageButton
            android:id="@+id/media_rew"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/rewind"
            android:src="@android:drawable/ic_media_rew" />
        <ImageButton
            android:id="@+id/media_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/pause"
            android:src="@android:drawable/ic_media_pause" />
        <ImageButton
            android:id="@+id/media_play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/play"
            android:src="@android:drawable/ic_media_play" />
        <ImageButton
            android:id="@+id/media_ff"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:contentDescription="@string/forward"
            android:src="@android:drawable/ic_media_ff" />
    </LinearLayout>    
</LinearLayout>
</ScrollView>

我认为这段代码应该可以解决您的问题。

public class FragmentMediaPlayer extends Fragment implements OnSeekBarChangeListener {
    private MediaPlayer mediaPlayer;
    public TextView duration;
    private int timeElapsed = 0, finalTime = 0;
    private int forwardTime = 5000, backwardTime = 5000;
    private Handler durationHandler = new Handler();
    private SeekBar seekBar;
    private boolean pausedFromButton = false;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View rootView = inflater.inflate(R.layout.media_player, container,
                false);
        // Initialize different views from the layout
        duration = (TextView) rootView.findViewById(R.id.songDuration);
        duration.setText(String.format(
                "%d min, %d sec",
                0,0));
        seekBar = (SeekBar) rootView.findViewById(R.id.seekBar);
        seekBar.setOnSeekBarChangeListener(this);
        ImageButton playButton = (ImageButton) rootView.findViewById(R.id.media_play);
        playButton.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         play();
                     } 
           }); 
        ImageButton media_pause = (ImageButton) rootView.findViewById(R.id.media_pause);
        media_pause.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         pause();
                     } 
           }); 
        ImageButton media_ff = (ImageButton) rootView.findViewById(R.id.media_ff);
        media_ff.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         forward();
                     } 
           }); 
        ImageButton media_rew = (ImageButton) rootView.findViewById(R.id.media_rew);
        media_rew.setOnClickListener(new OnClickListener() {
                     @Override
                     public void onClick(View v) {
                         rewind();
                     } 
           }); 
        return rootView;
    }   
    @Override
    public void onResume() {
        super.onResume();   
        prepareMediaPlayer();   
        play();
    }
    @Override
    public void onPause() {
        super.onPause();
        //Not call pause because it's necessaty to distinguish between onPause() and when the user press the pause buttonn
        mediaPlayer.pause();
    }
    @Override
    public void onStop() {
        // Stop updates and Disconnect from Services
        mediaPlayer.stop();
        durationHandler.removeCallbacks(updateSeekBarTime);
        super.onStop();
    }
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
        if(fromUser) { 
            mediaPlayer.seekTo(progress); 
            seekBar.setProgress(progress);
        }
    }
    @Override
    public void onStartTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
    }
    @Override
    public void onStopTrackingTouch(SeekBar arg0) {
        // TODO Auto-generated method stub
    }
    /**
     * Prepare MediaPlayer and recover from bad status
     */
    private void prepareMediaPlayer() {
        mediaPlayer = MediaPlayer.create(getActivity(), R.raw.song);
        finalTime = mediaPlayer.getDuration();
        seekBar.setMax(finalTime);
        mediaPlayer.seekTo(timeElapsed);
        mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();
            }
        });
        mediaPlayer.setOnCompletionListener(new
                OnCompletionListener() {        
                    @Override
                    public void onCompletion(MediaPlayer arg0) {
                        pausedFromButton = true;
                    }
        });
    }
    /**
     * play mp3 song
     */
    public void play() {
        if(pausedFromButton) {
            prepareMediaPlayer();
            pausedFromButton = false;
        }       
        seekBar.setProgress(timeElapsed);
        durationHandler.postDelayed(updateSeekBarTime, 100);
    }
    /**
     * handler to change seekBarTime
     */
    private Runnable updateSeekBarTime = new Runnable() {
        public void run() {
            // get current position
            timeElapsed = mediaPlayer.getCurrentPosition();
            // set seekbar progress
            seekBar.setProgress(timeElapsed);
            // set time remaing
            //double timeRemaining = finalTime - timeElapsed;
            duration.setText(String.format(
                    "%d min, %d sec",
                    TimeUnit.MILLISECONDS.toMinutes((long) timeElapsed),
                    TimeUnit.MILLISECONDS.toSeconds((long) timeElapsed)
                            - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS
                                    .toMinutes((long) timeElapsed))));
            // repeat yourself that again in 100 miliseconds
            durationHandler.postDelayed(this, 100);         
        }
    };

    /**
     * pause mp3 song
     */
    public void pause() {
        mediaPlayer.pause();    
        timeElapsed = mediaPlayer.getCurrentPosition();
        pausedFromButton = true;
    }
    /**
     * go forward at forwardTime seconds
     */
    public void forward() {
        // check if we can go forward at forwardTime seconds before song endes
        if ((timeElapsed + forwardTime) <= finalTime) {
            timeElapsed = timeElapsed + forwardTime;
            // seek to the exact second of the track
            mediaPlayer.seekTo(timeElapsed);
        }
    }
    /**
     * go backwards at backwardTime seconds
     */
    public void rewind() {
        // check if we can go back at backwardTime seconds after song starts
        if ((timeElapsed - backwardTime) > 0) {
            timeElapsed = timeElapsed - backwardTime;
            // seek to the exact second of the track
            mediaPlayer.seekTo(timeElapsed);
        }
    }   

}

最新更新