2013-03-25 65 views
4

我正在創建音樂流應用程序。根據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上下文。

我已經試過:

  1. 使用其他視圖佈局爲錨視圖(甚至壽doc說,你可以使用活動的主視圖)
  2. 把的MediaController的片段,以及使用getActivity()作爲上下文,如圖所示here
  3. 將MediaController置於xml佈局中,而不是以編程方式實例化它。
  4. 將VideoView設置爲定位視圖(有人說它只能用於VideoView)。
  5. 創建一個擴展VideoView並實現MediaPlayerControl的新類,並在該類中實例化MediaController,使用保存的上下文作爲上下文初始化時傳遞給該類的上下文,以及this作爲錨點視圖。
+0

你提供的應用程序或活動作爲上下文? – TacB0sS 2013-03-25 23:39:37

+0

我正在提供'this'作爲上下文,這是活動 – 2013-03-26 01:26:29

+3

@MarcCastells您是否曾經解決過這個問題?我有同樣的問題。 – you786 2013-08-27 07:31:22

回答

0

您的活動應實現MediaPlayer.OnPreparedListener,並將mediaPlayer的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 

這對我的作品後,一點點爲您服務。

相關問題