4

我正在创建一个音乐流媒体应用程序。根据android's MediaPlayer guide,我正在从服务控制 MediaPlayer。这一切都很好,现在我正在尝试添加一个 MediaController 来控制播放。为此,我让我的服务实现 MediaController.MediaPlayerControl,并将我的 Activity 绑定到我的服务,然后使用来自 ServiceConnection 的服务上下文从 Activity 实例化 MediaController。

播放器.java

public class Player extends Activity implements OnClickListener, OnItemClickListener, MediaController.MediaPlayerControl {
    private MediaController mediaController;
    private ServiceConnection mConnection = new ServiceConnection() {    
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            LocalBinder binder = (LocalBinder) service;
            mService = binder.getService();
            mBound = true;
            showMediaController();
        }    
        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_player);

        startService(
            new Intent(this, PlayerService.class)
            .setAction("com.limastreamer.action.NEXTSHOW"));

        bindService(
            new Intent(this, PlayerService.class),
            mConnection,
            Context.BIND_AUTO_CREATE);
    }

    public void showMediaController() {
        if (mBound) {
            mediaController = new MediaController(this);
            mediaController.setAnchorView(
                findViewById(R.id.player)
                );
            mediaController.setMediaPlayer(mService);
            mediaController.setEnabled(true);
            mediaController.show(0);
        }
    }
}

PlayerService.java

public class PlayerService extends Service implements MediaController.MediaPlayerControl {
    private MediaPlayer mMediaPlayer;

    public class LocalBinder extends Binder {
        PlayerService getService() {
            return PlayerService.this;
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);
        String action = intent.getAction();
        if (action.equals("com.limastreamer.action.NEXTSHOW")) {
            if (mMediaPlayer == null)
            {
                mMediaPlayer = new MediaPlayer();
                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mMediaPlayer.setLooping(false);         
            }
            try
            {
                mMediaPlayer.reset();
                mMediaPlayer.setDataSource(url);
                mMediaPlayer.prepareAsync(); // prepare async to not block main thread
            }
            catch (Exception ex)
            {
                Toast.makeText(getApplicationContext(), "Failed to prepare MediaPlayer", Toast.LENGTH_SHORT).show();
            }
        }
    }

    @Override
    public boolean canPause() {
        return true;
    }

    @Override
    public boolean canSeekBackward() {
        return true;
    }

    @Override
    public boolean canSeekForward() {
        return true;
    }

    @Override
    public int getBufferPercentage() {
        return 0;
        }

    @Override
    public int getCurrentPosition() {
        if (mMediaPlayer != null && mMediaPlayer.isPlaying())
            return mMediaPlayer.getCurrentPosition();
        else
            return 0;
    }

    @Override
    public int getDuration() {
        if (mMediaPlayer != null && mMediaPlayer.isPlaying())
            return mMediaPlayer.getDuration();
        else
            return 0;
    }

    @Override
    public boolean isPlaying() {
        if (mMediaPlayer != null)
            return mMediaPlayer.isPlaying();
        else
            return false;
    }

    @Override
    public void pause() {
        if (mMediaPlayer != null)
            mMediaPlayer.pause();
    }

    @Override
    public void seekTo(int msec) {
        if (mMediaPlayer != null)
            mMediaPlayer.seekTo(msec);
    }

    @Override
    public void start() {
        if (mMediaPlayer != null)
            mMediaPlayer.start();       
    }
}

R.id.player 指的是我的 xml 布局的根元素。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/player"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".Player" >

在调用mediaController.show();应用程序时出现异常:Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

从查看关于 SO(例如)的其他问题来看,这似乎是由于在此处使用了错误的上下文引起的:mediaController = new MediaController(this);,即使用了 Activity 上下文以外的其他内容。但据我所知,我使用的是 Activity 上下文。

我试过了:

  1. 使用布局中的其他视图作为锚视图(即使文档说您可以使用 Activity 的主视图)
  2. 将 MediaController 放在一个片段中,并使用 getActivity() 作为上下文,如下所示
  3. 将 MediaController 放在 xml 布局中,而不是以编程方式对其进行实例化。
  4. 将 VideoView 设置为锚视图(有人说它仅适用于 VideoView)。
  5. 创建一个扩展 VideoView 并实现 MediaPlayerControl 的新类,并在该类中实例化 MediaController,使用在初始化为上下文时传递给该类的保存的上下文,并this作为锚视图。
4

1 回答 1

1

您的活动应实现 MediaPlayer.OnPreparedListener 并将服务的 mediaPlayer 的 onPreparedListener 设置为播放器活动。

public class MyMediaPlayer extends Activity implements 
MediaController.MediaPlayerControl,MediaPlayer.OnPreparedListener {
...
public void onCreate(Bundle savedInstanceState) {
...
    //this mediaPlayer is the reference of your media player inside your service
    mediaPlayer.setOnPreparedListener(this);
...
}
...
}

您还必须在创建活动后启动您的服务

 Intent in=new Intent(MainPlayer.this,MyMediaPlayer.class);
        startActivity(in);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //START YOUR SERVICE TO PREPARE YOUR PLAYER

这对我有用。

于 2015-09-01T08:39:38.230 回答