#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>