7

ACTION_MEDIA_BUTTONインテントを使用してsendOrderedBroadcastを送信すると(ユーザーがBluetoothヘッドセットの再生ボタンをクリックしていることを模倣しています)、Google Playミュージックが開き、フォアグラウンドの音楽再生アプリではなく、最後に再生されたアルバムが再生されます。

sendBroadcastに変更すると、Google Playミュージックと現在の音楽再生アプリ(私の場合はPandora)の両方で再生ボタンが表示されます。

これはAndroid4.0以降でのみ発生します。Play Musicはこの意図を覆い隠していますか(バグ)?次のアドバイスに従って、Pandoraが現在のメディアボタンハンドラーとして登録されていないのではないかと思いますか:http: //android-developers.blogspot.com/2010/06/allowing-applications-to-play-nicer.html

このインテントを現在の音楽再生アプリのみに向ける方法はありますか?

これが私のコードです:

public void broadcastMediaIntent(MediaIntent intentType){

      long eventtime = SystemClock.uptimeMillis(); 

      Intent downIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); 
      Intent upIntent = new Intent(Intent.ACTION_MEDIA_BUTTON, null); 

      KeyEvent downEvent = null;
      KeyEvent upEvent = null;

    switch(intentType){
    case NEXT:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT, 0);

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT, 0); 

        break;
    case PLAY_PAUSE:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, 0); 

        break;
    case PREVIOUS:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS, 0);  
        break;
    case FAST_FORWARD:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, 0);  
        break;
    case REWIND:

          downEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_REWIND, 0); 

          upEvent = new KeyEvent(eventtime, eventtime, 
          KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND, 0);
        break;

    default:
        break;
    }

      downIntent.putExtra(Intent.EXTRA_KEY_EVENT, downEvent); 
      sendOrderedBroadcast(downIntent, null); 

      upIntent.putExtra(Intent.EXTRA_KEY_EVENT, upEvent); 
      sendOrderedBroadcast(upIntent, null); 

}
4

2 に答える 2

6

以下はトリックを行う必要があります。ところで、ロック画面のソースコードはどこにありますか?

   public void handleMediaKeyEvent(KeyEvent keyEvent) {

    /*
     * Attempt to execute the following with reflection. 
     * 
     * [Code]
     * IAudioService audioService = IAudioService.Stub.asInterface(b);
     * audioService.dispatchMediaKeyEvent(keyEvent);
     */
    try {

        // Get binder from ServiceManager.checkService(String)
        IBinder iBinder  = (IBinder) Class.forName("android.os.ServiceManager")
        .getDeclaredMethod("checkService",String.class)
        .invoke(null, Context.AUDIO_SERVICE);

        // get audioService from IAudioService.Stub.asInterface(IBinder)
        Object audioService  = Class.forName("android.media.IAudioService$Stub")
                .getDeclaredMethod("asInterface",IBinder.class)
                .invoke(null,iBinder);

        // Dispatch keyEvent using IAudioService.dispatchMediaKeyEvent(KeyEvent)
        Class.forName("android.media.IAudioService")
        .getDeclaredMethod("dispatchMediaKeyEvent",KeyEvent.class)
        .invoke(audioService, keyEvent);            

    }  catch (Exception e1) {
        e1.printStackTrace();
    }
}
于 2013-01-26T23:18:48.200 に答える
2

これらのインテントの優先受信者になるために使用する必要のあるAPIがありますが、もちろん、システムキーの送信者がそれを処理できます。この投稿ドキュメントを見てください。しかし、この場合、それはパンドラとグーグルの音楽次第なので、おそらくあなた次第ではありません。もちろん、ブロードキャストを特定のパッケージに送信することもできますが(インテントでコンポーネント名を指定することにより)、どのアプリがそれを取得するかを決定します。AudioManagerで非表示のAPIをすばやく検索しましたが、それは有望ではありません。

アクセサリーを試してみましたか?それがうまくいけば、私はその意図がどのように送られるかを調べます。そうでない場合は、インストールされているアプリケーションを確認し、「インテリジェント」な推測を行うか、インテントを送信するアプリをユーザーに尋ねます。おそらく最後の方法は、パブリックAPIを使用し、間違った推測でユーザーを煩わせることがないため、どちらの場合にも最適な方法です:)

編集: これは機能する可能性がありますが、権限と証明書によって保護されている場合もあります。ロック画面では、これがメディアキーの処理方法です。

void handleMediaKeyEvent(KeyEvent keyEvent) {
    IAudioService audioService = IAudioService.Stub.asInterface(
            ServiceManager.checkService(Context.AUDIO_SERVICE));
    if (audioService != null) {
        try {
            audioService.dispatchMediaKeyEvent(keyEvent);
        } catch (RemoteException e) {
            Log.e("KeyguardViewBase", "dispatchMediaKeyEvent threw exception " + e);
        }
    } else {
        Slog.w("KeyguardViewBase", "Unable to find IAudioService for media key event");
    }
}

ただし、APIは非表示になっているため、回避する必要があります。それはおそらく私があなたを助けることができる最高です。別の方法は、イベントを注入することです。そのための1つの方法は、入力メソッドになることですが、それは前向きな方法ではない可能性があります。自分のアクティビティにイベントを注入する方法はいくつかありますが、システムに注入する方法はわかりません。たぶん、インストルメンテーションテストがどのようにそれを行っているかを見ることができます。

于 2012-10-05T19:18:04.637 に答える