diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml
index 64299ff1ae..eafe99f86b 100644
--- a/vector/src/main/AndroidManifest.xml
+++ b/vector/src/main/AndroidManifest.xml
@@ -196,7 +196,12 @@
+ android:exported="false" >
+
+
+
+
+
+
+
+
+
+
+
+
()
- /**
- * 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(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)
diff --git a/vector/src/main/java/im/vector/riotx/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/riotx/features/call/VectorCallActivity.kt
index de0d3151a9..2c1c909a97 100644
--- a/vector/src/main/java/im/vector/riotx/features/call/VectorCallActivity.kt
+++ b/vector/src/main/java/im/vector/riotx/features/call/VectorCallActivity.kt
@@ -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)
diff --git a/vector/src/main/java/im/vector/riotx/features/call/WebRtcPeerConnectionManager.kt b/vector/src/main/java/im/vector/riotx/features/call/WebRtcPeerConnectionManager.kt
index 8b2e1ef74c..9fbc38d816 100644
--- a/vector/src/main/java/im/vector/riotx/features/call/WebRtcPeerConnectionManager.kt
+++ b/vector/src/main/java/im/vector/riotx/features/call/WebRtcPeerConnectionManager.kt
@@ -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")