mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Jitsi call: fix PiP
This commit is contained in:
parent
6b6fb03dce
commit
7f74278a73
1 changed files with 54 additions and 62 deletions
|
@ -16,22 +16,22 @@
|
||||||
|
|
||||||
package im.vector.app.features.call.conference
|
package im.vector.app.features.call.conference
|
||||||
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
import androidx.lifecycle.Lifecycle
|
||||||
import com.airbnb.mvrx.Fail
|
import com.airbnb.mvrx.Fail
|
||||||
import com.airbnb.mvrx.MvRx
|
import com.airbnb.mvrx.MvRx
|
||||||
import com.airbnb.mvrx.Success
|
import com.airbnb.mvrx.Success
|
||||||
import com.airbnb.mvrx.viewModel
|
import com.airbnb.mvrx.viewModel
|
||||||
|
import com.facebook.react.bridge.JavaOnlyMap
|
||||||
import com.facebook.react.modules.core.PermissionListener
|
import com.facebook.react.modules.core.PermissionListener
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
|
@ -40,7 +40,9 @@ import im.vector.app.core.extensions.exhaustive
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.databinding.ActivityJitsiBinding
|
import im.vector.app.databinding.ActivityJitsiBinding
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import org.jitsi.meet.sdk.BroadcastEmitter
|
||||||
import org.jitsi.meet.sdk.BroadcastEvent
|
import org.jitsi.meet.sdk.BroadcastEvent
|
||||||
|
import org.jitsi.meet.sdk.JitsiMeet
|
||||||
import org.jitsi.meet.sdk.JitsiMeetActivityDelegate
|
import org.jitsi.meet.sdk.JitsiMeetActivityDelegate
|
||||||
import org.jitsi.meet.sdk.JitsiMeetActivityInterface
|
import org.jitsi.meet.sdk.JitsiMeetActivityInterface
|
||||||
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions
|
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions
|
||||||
|
@ -71,13 +73,6 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||||
injector.inject(this)
|
injector.inject(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk#listening-for-broadcasted-events
|
|
||||||
private val broadcastReceiver = object : BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
|
||||||
intent?.let { onBroadcastReceived(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
@ -94,8 +89,48 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||||
JitsiCallViewEvents.LeaveConference -> handleLeaveConference()
|
JitsiCallViewEvents.LeaveConference -> handleLeaveConference()
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
|
lifecycle.addObserver(JitsiBroadcastEventObserver(this, this::onBroadcastEvent))
|
||||||
|
}
|
||||||
|
|
||||||
registerForBroadcastMessages()
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
JitsiMeetActivityDelegate.onHostResume(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initUiAndData() {
|
||||||
|
super.initUiAndData()
|
||||||
|
jitsiMeetView = JitsiMeetView(this)
|
||||||
|
val params = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
|
||||||
|
views.jitsiLayout.addView(jitsiMeetView, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
JitsiMeetActivityDelegate.onHostPause(this)
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
val currentConf = JitsiMeet.getCurrentConference()
|
||||||
|
jitsiMeetView?.leave()
|
||||||
|
jitsiMeetView?.dispose()
|
||||||
|
// Fake emitting CONFERENCE_TERMINATED event when currentConf is not null (probably when closing the PiP screen).
|
||||||
|
if (currentConf != null) {
|
||||||
|
val broadcastEventData = JavaOnlyMap.of("url", currentConf)
|
||||||
|
BroadcastEmitter(this).sendBroadcast(BroadcastEvent.Type.CONFERENCE_TERMINATED.name, broadcastEventData)
|
||||||
|
}
|
||||||
|
JitsiMeetActivityDelegate.onHostDestroy(this)
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBackPressed() {
|
||||||
|
JitsiMeetActivityDelegate.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUserLeaveHint() {
|
||||||
|
super.onUserLeaveHint()
|
||||||
|
if (packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
|
||||||
|
jitsiMeetView?.enterPictureInPicture()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleLeaveConference() {
|
private fun handleLeaveConference() {
|
||||||
|
@ -116,14 +151,16 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||||
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean,
|
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean,
|
||||||
newConfig: Configuration) {
|
newConfig: Configuration) {
|
||||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
|
||||||
|
checkIfActivityShouldBeFinished()
|
||||||
Timber.w("onPictureInPictureModeChanged($isInPictureInPictureMode)")
|
Timber.w("onPictureInPictureModeChanged($isInPictureInPictureMode)")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initUiAndData() {
|
private fun checkIfActivityShouldBeFinished() {
|
||||||
super.initUiAndData()
|
// OnStop is called when PiP mode is closed directly from the ui
|
||||||
jitsiMeetView = JitsiMeetView(this)
|
// If stopped is called and PiP mode is not active, we should finish the activity and remove the task as Android creates a new one for PiP.
|
||||||
val params = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) && !isInPictureInPictureMode) {
|
||||||
views.jitsiLayout.addView(jitsiMeetView, params)
|
finishAndRemoveTask()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderState(viewState: JitsiCallViewState) {
|
private fun renderState(viewState: JitsiCallViewState) {
|
||||||
|
@ -167,34 +204,6 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||||
jitsiMeetView?.join(jitsiMeetConferenceOptions)
|
jitsiMeetView?.join(jitsiMeetConferenceOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
JitsiMeetActivityDelegate.onHostPause(this)
|
|
||||||
super.onStop()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
JitsiMeetActivityDelegate.onHostResume(this)
|
|
||||||
super.onResume()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
JitsiMeetActivityDelegate.onBackPressed()
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
JitsiMeetActivityDelegate.onHostDestroy(this)
|
|
||||||
unregisterForBroadcastMessages()
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUserLeaveHint() {
|
|
||||||
super.onUserLeaveHint()
|
|
||||||
if (packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
|
|
||||||
jitsiMeetView?.enterPictureInPicture()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
JitsiMeetActivityDelegate.onNewIntent(intent)
|
JitsiMeetActivityDelegate.onNewIntent(intent)
|
||||||
|
|
||||||
|
@ -217,24 +226,7 @@ class VectorJitsiActivity : VectorBaseActivity<ActivityJitsiBinding>(), JitsiMee
|
||||||
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerForBroadcastMessages() {
|
private fun onBroadcastEvent(event: BroadcastEvent) {
|
||||||
val intentFilter = IntentFilter()
|
|
||||||
for (type in BroadcastEvent.Type.values()) {
|
|
||||||
intentFilter.addAction(type.action)
|
|
||||||
}
|
|
||||||
tryOrNull("Unable to register receiver") {
|
|
||||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, intentFilter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun unregisterForBroadcastMessages() {
|
|
||||||
tryOrNull("Unable to unregister receiver") {
|
|
||||||
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onBroadcastReceived(intent: Intent) {
|
|
||||||
val event = BroadcastEvent(intent)
|
|
||||||
Timber.v("Broadcast received: ${event.type}")
|
Timber.v("Broadcast received: ${event.type}")
|
||||||
when (event.type) {
|
when (event.type) {
|
||||||
BroadcastEvent.Type.CONFERENCE_TERMINATED -> onConferenceTerminated(event.data)
|
BroadcastEvent.Type.CONFERENCE_TERMINATED -> onConferenceTerminated(event.data)
|
||||||
|
|
Loading…
Reference in a new issue