Support headset buttons in background
This commit is contained in:
parent
9653f082a3
commit
4c61dfef62
|
@ -196,7 +196,12 @@
|
|||
|
||||
<service
|
||||
android:name=".core.services.CallService"
|
||||
android:exported="false" />
|
||||
android:exported="false" >
|
||||
<!-- in order to get headset button events -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".core.services.VectorSyncService"
|
||||
|
@ -226,6 +231,16 @@
|
|||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
<!--
|
||||
A media button receiver receives and helps translate hardware media playback buttons,
|
||||
such as those found on wired and wireless headsets, into the appropriate callbacks in your app.
|
||||
-->
|
||||
<receiver android:name="androidx.media.session.MediaButtonReceiver" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Providers -->
|
||||
|
||||
<provider
|
||||
|
|
|
@ -20,7 +20,10 @@ package im.vector.riotx.core.services
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import android.view.KeyEvent
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.media.session.MediaButtonReceiver
|
||||
import im.vector.riotx.core.extensions.vectorComponent
|
||||
import im.vector.riotx.features.call.WebRtcPeerConnectionManager
|
||||
import im.vector.riotx.features.call.telecom.CallConnection
|
||||
|
@ -34,23 +37,27 @@ class CallService : VectorService(), WiredHeadsetStateReceiver.HeadsetEventListe
|
|||
|
||||
private val connections = mutableMapOf<String, CallConnection>()
|
||||
|
||||
/**
|
||||
* call in progress (foreground notification)
|
||||
*/
|
||||
// private var mCallIdInProgress: String? = null
|
||||
|
||||
private lateinit var notificationUtils: NotificationUtils
|
||||
private lateinit var webRtcPeerConnectionManager: WebRtcPeerConnectionManager
|
||||
|
||||
/**
|
||||
* incoming (foreground notification)
|
||||
*/
|
||||
// private var mIncomingCallId: String? = null
|
||||
|
||||
private var callRingPlayer: CallRingPlayer? = null
|
||||
|
||||
private var wiredHeadsetStateReceiver: WiredHeadsetStateReceiver? = null
|
||||
|
||||
// A media button receiver receives and helps translate hardware media playback buttons,
|
||||
// such as those found on wired and wireless headsets, into the appropriate callbacks in your app
|
||||
private var mediaSession : MediaSessionCompat? = null
|
||||
private val mediaSessionButtonCallback = object : MediaSessionCompat.Callback() {
|
||||
override fun onMediaButtonEvent(mediaButtonEvent: Intent?): Boolean {
|
||||
val keyEvent = mediaButtonEvent?.getParcelableExtra<KeyEvent>(Intent.EXTRA_KEY_EVENT) ?: return false
|
||||
if (keyEvent.keyCode == KeyEvent.KEYCODE_HEADSETHOOK) {
|
||||
webRtcPeerConnectionManager.headSetButtonTapped()
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
notificationUtils = vectorComponent().notificationUtils()
|
||||
|
@ -64,22 +71,36 @@ class CallService : VectorService(), WiredHeadsetStateReceiver.HeadsetEventListe
|
|||
callRingPlayer?.stop()
|
||||
wiredHeadsetStateReceiver?.let { WiredHeadsetStateReceiver.unRegister(this, it) }
|
||||
wiredHeadsetStateReceiver = null
|
||||
mediaSession?.release()
|
||||
mediaSession = null
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Timber.v("## VOIP onStartCommand $intent")
|
||||
if (mediaSession == null) {
|
||||
mediaSession = MediaSessionCompat(applicationContext, CallService::class.java.name).apply {
|
||||
setCallback(mediaSessionButtonCallback)
|
||||
}
|
||||
}
|
||||
if (intent == null) {
|
||||
// Service started again by the system.
|
||||
// TODO What do we do here?
|
||||
return START_STICKY
|
||||
}
|
||||
mediaSession?.let {
|
||||
// This ensures that the correct callbacks to MediaSessionCompat.Callback
|
||||
// will be triggered based on the incoming KeyEvent.
|
||||
MediaButtonReceiver.handleIntent(it, intent)
|
||||
}
|
||||
|
||||
when (intent.action) {
|
||||
ACTION_INCOMING_RINGING_CALL -> {
|
||||
mediaSession?.isActive = true
|
||||
callRingPlayer?.start()
|
||||
displayIncomingCallNotification(intent)
|
||||
}
|
||||
ACTION_OUTGOING_RINGING_CALL -> {
|
||||
mediaSession?.isActive = true
|
||||
callRingPlayer?.start()
|
||||
displayOutgoingRingingCallNotification(intent)
|
||||
}
|
||||
|
@ -221,6 +242,7 @@ class CallService : VectorService(), WiredHeadsetStateReceiver.HeadsetEventListe
|
|||
private fun hideCallNotifications() {
|
||||
val notification = notificationUtils.buildCallEndedNotification()
|
||||
|
||||
mediaSession?.isActive = false
|
||||
// It's mandatory to startForeground to avoid crash
|
||||
startForeground(NOTIFICATION_ID, notification)
|
||||
|
||||
|
|
|
@ -326,10 +326,14 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
|
|||
}
|
||||
|
||||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_HEADSETHOOK -> {
|
||||
callViewModel.handle(VectorCallViewActions.HeadSetButtonPressed)
|
||||
return true
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
// for newer version, it will be passed automatically to active media session
|
||||
// in call service
|
||||
when (keyCode) {
|
||||
KeyEvent.KEYCODE_HEADSETHOOK -> {
|
||||
callViewModel.handle(VectorCallViewActions.HeadSetButtonPressed)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event)
|
||||
|
|
|
@ -184,6 +184,19 @@ class WebRtcPeerConnectionManager @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun headSetButtonTapped() {
|
||||
Timber.v("## VOIP headSetButtonTapped")
|
||||
val call = currentCall?.mxCall ?: return
|
||||
if (call.state is CallState.LocalRinging) {
|
||||
// accept call
|
||||
acceptIncomingCall()
|
||||
}
|
||||
if (call.state is CallState.Connected) {
|
||||
// end call?
|
||||
endCall()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPeerConnectionFactory() {
|
||||
if (peerConnectionFactory != null) return
|
||||
Timber.v("## VOIP createPeerConnectionFactory")
|
||||
|
|
Loading…
Reference in New Issue