web-dev-qa-db-ja.com

Android "O"(Oreo、8)メディアボタンの問題

Text-to-Speechアプリで使用するヘッドセットのメディアボタンを処理するためのコードは、Android API 22〜25(古いバージョンのAndroid =他の、現在は減価償却されている手段で処理されます。ただし、Android 8 "Oreo"、パブリックベータ版と最終リリースの両方では機能しません。関連するコードは次のとおりです。

サービスが開始したら、MediaSessionCompactオブジェクトを作成します。

        mSession = new MediaSessionCompat(getApplicationContext(), "my.package.name._player_session");
        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mSession.setActive(true);
        mSession.setCallback(myMediaSessionCallback);
        PlaybackStateCompat state = new PlaybackStateCompat.Builder()
                .setActions(ACTION_PLAY_PAUSE | ACTION_PLAY | ACTION_PAUSE |
                        ACTION_SKIP_TO_NEXT | ACTION_SKIP_TO_PREVIOUS |
                        ACTION_FAST_FORWARD | ACTION_REWIND
                )
                .setState(PlaybackStateCompat.STATE_PAUSED, 0 /*PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN*/, 1f)
                .build();
        mSession.setPlaybackState(state);

もちろん、セッションメディアコールバックが定義されています。

private MediaSessionCompat.Callback myMediaSessionCallback = new MediaSessionCompat.Callback() {
    @Override
    public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
        // The log output below never appears on "Oreo", nothing comes here.
        Log.d(TAG, "callback onMediaButtonEvent() Compat");
        MediaButtonIntentReceiver.handleIntent(mediaButtonIntent.getAction(), (KeyEvent) mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT));
        return true;
    }

    @Override
    public void onSkipToNext() {
        //...
    }
    // etc. other overrides
};

また、MediaButtonReceiver.buildMediaButtonPendingIntent()を使用して、PendingIntentを試し、関心のあるすべてのアクションにmSession.setMediaButtonReceiver(pendingIntent)を設定してから、サービスonStartCommand()でMediaButtonReceiver.handleIntent(mSession、intent)を呼び出します。

// still in the same service:            
mSession.setMediaButtonReceiver(
            MediaButtonReceiver.buildMediaButtonPendingIntent(
                this,
                mMediaButtonReceiverComponentName,
                ACTION_PLAY));


mSession.setMediaButtonReceiver(
            MediaButtonReceiver.buildMediaButtonPendingIntent(
                this,
                mMediaButtonReceiverComponentName,
                ACTION_PAUSE));


mSession.setMediaButtonReceiver(
            MediaButtonReceiver.buildMediaButtonPendingIntent(
                this,
                mMediaButtonReceiverComponentName,
                ACTION_PLAY_PAUSE));

およびサービスonStartCommand():

@Override 
public int onStartCommand(Intent intent, int flags, int startId) {
    // ...
    if (intent != null) {
        MediaButtonReceiver.handleIntent(mSession, intent);
        // ...
    }
    return START_NOT_STICKY;
}

何も、それはメディアボタンがイベントを押すのに完全にばかげています。 「O」またはそこにある私のコードの何が問題になっていますか?私は完全に困惑しています。

2017年8月32日更新

また、問題を示す些細な、しかし機能するアプリプロジェクトを作成しました。 https://github.com/gregko/PlayerServiceSample を参照してください。このプロジェクトは、ヘッドセットのメディアボタンがAndroid 5.xから7.xで押されたときに、LogCat出力を表示しますが、Android 8 "Oreo "。

2017年9月1日更新Android Issue Trackerに、私が提出した未解決の問題があります。 at https://issuetracker.google.com/issues/65175978 。それでも、メディアボタンはOreoでテストしたいくつかの音楽プレーヤーアプリで機能しますが、それらがどのように異なるのか理解できません。それらを機能させる...私のアプリのコンテキストは音楽を再生していませんが、テキスト読み上げサービスでテキストを読み上げるため、ミュージックプレーヤーの例の多くのコードは適用されません。

12
gregko

解決しました。 " Android 8.0の動作の変更 " Googleページに次のテキストがあります:

Android 8.0(APIレベル26)では、メディアボタンイベントの処理が異なります。

  1. UIアクティビティでのメディアボタンの処理は変更されていません。メディアボタンイベントの処理では、フォアグラウンドアクティビティが引き続き優先されます。
  2. フォアグラウンドアクティビティがメディアボタンイベントを処理しない場合、システムはイベントを、最後にローカルでオーディオを再生したアプリにルーティングします。メディアセッションのアクティブステータス、フラグ、および再生状態は、どのアプリがメディアボタンイベントを受信するかを決定するときに考慮されません。
  3. アプリのメディアセッションが解放されている場合、システムはメディアボタンイベントをアプリのMediaButtonReceiverに送信します(ある場合)。
  4. それ以外の場合はすべて、システムはメディアボタンイベントを破棄します。

ささいなサンプルを機能させるために私がしなければならなかったのは、MediaPlayerでサウンドを再生することだけでした。どうやらText-to-SpeechAPIでサウンドを再生することは資格がありません、それは私の意見ではバグです。

これは、Rawリソースディレクトリから非常に簡潔でサイレントなWAVファイルを再生して、それを機能させるために簡単なサンプルに追加したコードです。

    final MediaPlayer mMediaPlayer;
    mMediaPlayer = MediaPlayer.create(this, R.raw.silent_sound);
    mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            mMediaPlayer.release();
        }
    });
    mMediaPlayer.start();

更新

バグレポートをAndroid Issue Tracker at https://issuetracker.google.com/issues/65344811 に送信しました

更新2、2017年10月10日

Googleは現在、この点でのOreoの動作は「設計による」ものであり、修正しないと述べています。上記の課題追跡システムの投稿の終わり近くにある返信を読んでください。私はがっかりしていると言わなければなりません。

9
gregko