android MediaSession `setActive(false)` not work

huangapple go评论75阅读模式
英文:

android MediaSession setActive(false) not work

问题

我使用 MediaSession 来响应耳机媒体按钮,并且希望在活动暂停时停止声音。我还希望在活动暂停时不激活耳机媒体按钮。

根据安卓文档,它说 setActive 方法用于**“设置此会话当前是否处于活动状态并且准备好接收命令”**。但这似乎没有起作用,我仍然可以在活动暂停时使用耳机继续播放音乐。我是否误解了此方法的功能?

我的代码如下:

@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()

        mediaSession = MediaSession(this, "test_log").apply {
            setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS or MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS)
            setMediaButtonReceiver(null)

            val stateBuilder = PlaybackState.Builder()
                .setActions(PlaybackState.ACTION_PLAY or PlaybackState.ACTION_PAUSE or PlaybackState.ACTION_PLAY_PAUSE)
            setPlaybackState(stateBuilder.build())

            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
    }

    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))
    }
}

如果您对代码有任何问题,请随时问我。

英文:

I use MediaSession to respond to headset media buttons, and want to stop the sound when activity is paused. I also want to make the headset media buttons not active when activity is paused.

From the android documentation, it said the setActive method is use to "set if this session is currently active and ready to receive commands". But it not worked, I can still use head resume the music when activity is paused. Do I misunderstand the function of this method?

My code is as followed:

@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

得分: 2

以下是翻译好的部分:

【文档】1中提到:

> 设置此会话是否当前处于活动状态并且准备好接收命令。如果设置为false,则可能无法发现会话的控制器。在会话开始接收媒体按钮事件或传输命令之前,必须将会话设置为活动状态。

文档没有提到您应该将其设置为false以停止接收命令。我猜想,如果控制器已经被发现,那么这个值就不再重要。

因此,根据这份文档,您应该使用release或者setCallback(null)

英文:

The documentation says:

> Set if this session is currently active and ready to receive commands. If set to false your session's controller may not be discoverable. You must set the session to active before it can start receiving media button events or transport commands.

It does not say that you should set it to false to stop receiving commands. I guess if the controller is already discovered, the value doesn't matter anymore.

So instead you should use release or setCallback(null) according to this documentation.

答案2

得分: 1

以下是翻译好的部分:

<application>

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

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

        </service>

        <!-- 这是多余的接收器,请不要这样做 ;-) -->
        <receiver android:name="androidx.media.session.MediaButtonReceiver">
            <intent-filter>
                <action android:name="android.intent.action.MEDIA_BUTTON" />
            </intent-filter>
        </receiver>
    </application>
英文:

Just for the record: For me setCallback(null) was not working, since I by mistake added two MEDIA_BUTTON.BroadcastReceiver to Manifest.xml. This somehow started the Service in the background without attached 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>

</details>



huangapple
  • 本文由 发表于 2020年9月29日 12:11:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/64112772.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定