android MediaSession SetActive (false) не работает

#java #android #kotlin

#java #Android #kotlin

Вопрос:

Я использую MediaSession для ответа на мультимедийные кнопки гарнитуры и хочу остановить звук, когда действие приостановлено. Я также хочу, чтобы мультимедийные кнопки гарнитуры не были активными, когда действие приостановлено.

Из документации Android в нем говорится setActive , что метод используется для «установки, активен ли этот сеанс в данный момент и готов ли он к приему команд». Но это не сработало, я все еще могу использовать head для возобновления музыки, когда действие приостановлено. Я неправильно понимаю функцию этого метода?

Мой код выглядит следующим образом:

 @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class MainActivity : AppCompatActivity() {

private lateinit var mediaSession: MediaSession
private var mediaPlayer: MediaPlayer? = null

public override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)

    mediaPlayer = MediaPlayer.create(this, R.raw.lapple)
    mediaPlayer?.isLooping = true
    mediaPlayer?.start()
    // Create a MediaSessionCompat

    mediaSession = MediaSession(this, "test_log").apply {

        // Enable callbacks from MediaButtons and TransportControls
        setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS or MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS)

        // Do not let MediaButtons restart the player when the app is not visible
        setMediaButtonReceiver(null)

        // Set an initial PlaybackState with ACTION_PLAY, so media buttons can start the player
        val stateBuilder = PlaybackState.Builder()
            .setActions(PlaybackState.ACTION_PLAY or PlaybackState.ACTION_PAUSE or PlaybackState.ACTION_PLAY_PAUSE)
        setPlaybackState(stateBuilder.build())

        // MySessionCallback has methods that handle callbacks from a media controller
        setCallback(object : MediaSession.Callback() {
            override fun onPlay() {
                Toast.makeText(
                    this@MainActivity,
                    "${this@MainActivity.hashCode()}: onPlay",
                    Toast.LENGTH_SHORT
                ).show()
                mediaPlayer?.start()
            }

            override fun onPause() {
                mediaPlayer?.pause()
                Toast.makeText(
                    this@MainActivity,
                    "${this@MainActivity.hashCode()}: onPause",
                    Toast.LENGTH_SHORT
                ).show()
            }

        })
    }

    mediaSession.isActive = true

    //mediaController = MediaController(this, mediaSession.sessionToken)

}

override fun onPause() {
    super.onPause()
    mediaSession.isActive = false
    mediaPlayer?.pause()
}

override fun onResume() {
    super.onResume()
    mediaSession.isActive = true
    mediaPlayer?.start()
}

override fun onDestroy() {
    mediaPlayer?.release()
    super.onDestroy()
}

fun newActivity(view: View) {
    startActivity(Intent(this, MainActivity::class.java))
}
}
  

Ответ №1:

В документации говорится:

Установите, активен ли этот сеанс в данный момент и готов ли он к приему команд. Если установлено значение false, контроллер вашего сеанса может быть недоступен для обнаружения. Вы должны установить сеанс активным, прежде чем он сможет начать получать события кнопки мультимедиа или команды транспортировки.

В нем не говорится, что вы должны установить для него значение false, чтобы прекратить прием команд. Я думаю, если контроллер уже обнаружен, значение больше не имеет значения.

Поэтому вместо этого вы должны использовать release или setCallback(null) в соответствии с этой документацией.

Комментарии:

1. Что делать, если у меня есть два действия, оба имеют MediaSession, и я хочу сделать MediaSession первого действия неактивным. Единственный способ — освободить MediaSession?

2. В документации говорится, что вам лучше использовать один сеанс с сервисом, который используется совместно между действиями

3. нет, два действия не воспроизводят одну и ту же музыку, поэтому ее нельзя использовать совместно

4. Вы можете либо предоставить общий доступ к проигрывателю и переключить дорожку на activity switch, либо иным образом работать с setCallback, как упоминалось выше, если для вас установлено значение null, вы не будете получать обратные вызовы для этого mediasession…

Ответ №2:

Просто для справки: у меня setCallback(null) ничего не получалось, так как я по ошибке добавил два MEDIA_BUTTON.BroadcastReceiver к Manifest.xml . Это каким-то образом запустило Service в фоновом режиме без привязки Activity

  <application>

        <service
            android:name=".service.MyService">

            <intent-filter>
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>

        </service>

        <!-- this was the stupid receiver. DO NOT DO IT ;-) -->
        <receiver android:name="androidx.media.session.MediaButtonReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
        </receiver>
    </application>