java - 安卓开发 : MediaPlayer not working after "hold mode" is on/off

标签 java android android-mediaplayer

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

我的代码一开始工作正常(歌曲响起)。 但是当用户按下保持按钮时,应用无法继续播放(在保持后再次返回屏幕时)。

通过调试,我检查过当你按下保持按钮(重启手机)时,你进入了 onResume(很明显)但是 mediaPlayer.prepare() 抛出java.lang.IllegalStateException(在 catch block 中捕获),消息为:prepareAsync 在状态 0 中调用

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

Attempt to perform seekTo in wrong state

error (-38, 0)

Attempt to call getDuration without a valid mediaplayer

error (-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
        
    }

这是我的 layout.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);
        }
    }   


}

关于java - 安卓开发 : MediaPlayer not working after "hold mode" is on/off,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26651239/

相关文章:

java - 为什么重写的方法不表现出多态行为?

java - 在 API 8 中调用 PreferenceFragment 方法

Android:在媒体播放器 Activity 中正确使用 PrepareAsync()

android - 当手机处于静音状态时,我的应用程序仍会播放声音

android - 一触式读取标签中的 NDEF 消息两次(无需移动手机)

java - Android 音乐播放器不播放选定的歌曲

java - Struts 1到 Spring 迁移-策略

java - 将时间戳转换为相对时间

MapReduce 中的 java.io.IOException

Android 处理程序、计时器和多线程