我正在創建音樂流應用程序。根據android's MediaPlayer guide,我從服務控制MediaPlayer。這一切工作正常,現在我試圖添加一個MediaController來控制播放。爲此,我讓我的服務實現MediaController.MediaPlayerControl,並將我的Activity綁定到我的服務,然後使用ServiceConnection中的服務上下文從Activity中實例化MediaController。調用MediaController.show()時Android應用程序崩潰 - 無法添加窗口 - 令牌null無效
Player.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(for example)尋找其他問題,似乎這是由這裏使用了錯誤的情況下:mediaController = new MediaController(this);
,即使用除活動上下文以外的其他內容。但據我所知,我正在使用Activity上下文。
我已經試過:
- 使用其他視圖佈局爲錨視圖(甚至壽doc說,你可以使用活動的主視圖)
- 把的MediaController的片段,以及使用getActivity()作爲上下文,如圖所示here
- 將MediaController置於xml佈局中,而不是以編程方式實例化它。
- 將VideoView設置爲定位視圖(有人說它只能用於VideoView)。
- 創建一個擴展VideoView並實現MediaPlayerControl的新類,並在該類中實例化MediaController,使用保存的上下文作爲上下文初始化時傳遞給該類的上下文,以及
this
作爲錨點視圖。
你提供的應用程序或活動作爲上下文? – TacB0sS 2013-03-25 23:39:37
我正在提供'this'作爲上下文,這是活動 – 2013-03-26 01:26:29
@MarcCastells您是否曾經解決過這個問題?我有同樣的問題。 – you786 2013-08-27 07:31:22