Implement foreground service for Android Q and later.

This commit is contained in:
Onuray Sahin 2022-04-21 11:23:25 +03:00
parent fa3476d6cd
commit f9ee06cd2a
10 changed files with 106 additions and 14 deletions

View file

@ -68,7 +68,7 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetC
}
views.callControlsShareScreen.views.bottomSheetActionClickableZone.debouncedClicks {
callViewModel.handle(VectorCallViewActions.InitiateScreenSharing)
callViewModel.handle(VectorCallViewActions.ToggleScreenSharing)
dismiss()
}
}
@ -100,5 +100,6 @@ class CallControlsBottomSheet : VectorBaseBottomSheetDialogFragment<BottomSheetC
views.callControlsToggleHoldResume.leftIcon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_call_hold_action)
}
views.callControlsTransfer.isVisible = state.canOpponentBeTransferred
views.callControlsShareScreen.title = getString(if (state.isSharingScreen) R.string.call_stop_screen_sharing else R.string.call_start_screen_sharing)
}
}

View file

@ -58,6 +58,7 @@ import im.vector.app.features.call.dialpad.DialPadFragment
import im.vector.app.features.call.transfer.CallTransferActivity
import im.vector.app.features.call.utils.EglUtils
import im.vector.app.features.call.webrtc.ScreenCaptureService
import im.vector.app.features.call.webrtc.ScreenCaptureServiceConnection
import im.vector.app.features.call.webrtc.WebRtcCall
import im.vector.app.features.call.webrtc.WebRtcCallManager
import im.vector.app.features.displayname.getBestName
@ -96,6 +97,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
@Inject lateinit var callManager: WebRtcCallManager
@Inject lateinit var avatarRenderer: AvatarRenderer
@Inject lateinit var screenCaptureServiceConnection: ScreenCaptureServiceConnection
private val callViewModel: VectorCallViewModel by viewModel()
@ -528,6 +530,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
}
is VectorCallViewEvents.FailToTransfer -> showSnackbar(getString(R.string.call_transfer_failure))
is VectorCallViewEvents.ShowScreenSharingPermissionDialog -> handleShowScreenSharingPermissionDialog()
is VectorCallViewEvents.StopScreenSharingService -> handleStopScreenSharingService()
else -> Unit
}
}
@ -640,6 +643,7 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
this,
Intent(this, ScreenCaptureService::class.java)
)
screenCaptureServiceConnection.bind()
}
}
}
@ -650,6 +654,12 @@ class VectorCallActivity : VectorBaseActivity<ActivityCallBinding>(), CallContro
}
}
private fun handleStopScreenSharingService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
screenCaptureServiceConnection.stopScreenCapturing()
}
}
companion object {
private const val EXTRA_MODE = "EXTRA_MODE"
private const val FRAGMENT_DIAL_PAD_TAG = "FRAGMENT_DIAL_PAD_TAG"

View file

@ -40,6 +40,6 @@ sealed class VectorCallViewActions : VectorViewModelAction {
object CallTransferSelectionCancelled : VectorCallViewActions()
data class CallTransferSelectionResult(val callTransferResult: CallTransferResult) : VectorCallViewActions()
object TransferCall : VectorCallViewActions()
object InitiateScreenSharing : VectorCallViewActions()
object ToggleScreenSharing : VectorCallViewActions()
object StartScreenSharing : VectorCallViewActions()
}

View file

@ -31,6 +31,7 @@ sealed class VectorCallViewEvents : VectorViewEvents {
object ShowCallTransferScreen : VectorCallViewEvents()
object FailToTransfer : VectorCallViewEvents()
object ShowScreenSharingPermissionDialog : VectorCallViewEvents()
object StopScreenSharingService : VectorCallViewEvents()
// data class CallAnswered(val content: CallAnswerContent) : VectorCallViewEvents()
// data class CallHangup(val content: CallHangupContent) : VectorCallViewEvents()
// object CallAccepted : VectorCallViewEvents()

View file

@ -256,7 +256,10 @@ class VectorCallViewModel @AssistedInject constructor(
override fun handle(action: VectorCallViewActions) = withState { state ->
when (action) {
VectorCallViewActions.EndCall -> call?.endCall()
VectorCallViewActions.EndCall -> {
call?.endCall()
_viewEvents.post(VectorCallViewEvents.StopScreenSharingService)
}
VectorCallViewActions.AcceptCall -> {
setState {
copy(callState = Loading())
@ -337,21 +340,38 @@ class VectorCallViewModel @AssistedInject constructor(
VectorCallViewActions.TransferCall -> {
handleCallTransfer()
}
is VectorCallViewActions.SwitchCall -> {
is VectorCallViewActions.SwitchCall -> {
setState { VectorCallViewState(action.callArgs) }
setupCallWithCurrentState()
}
is VectorCallViewActions.InitiateScreenSharing -> {
_viewEvents.post(
VectorCallViewEvents.ShowScreenSharingPermissionDialog
)
is VectorCallViewActions.ToggleScreenSharing -> {
handleToggleScreenSharing(state.isSharingScreen)
}
is VectorCallViewActions.StartScreenSharing -> {
call?.shareScreen()
is VectorCallViewActions.StartScreenSharing -> {
call?.startSharingScreen()
setState {
copy(isSharingScreen = true)
}
}
}
}
private fun handleToggleScreenSharing(isSharingScreen: Boolean) {
if (isSharingScreen) {
call?.stopSharingScreen()
setState {
copy(isSharingScreen = false)
}
_viewEvents.post(
VectorCallViewEvents.StopScreenSharingService
)
} else {
_viewEvents.post(
VectorCallViewEvents.ShowScreenSharingPermissionDialog
)
}
}
private fun handleCallTransfer() {
viewModelScope.launch {
val currentCall = call ?: return@launch

View file

@ -42,7 +42,8 @@ data class VectorCallViewState(
val callInfo: CallInfo? = null,
val formattedDuration: String = "",
val canOpponentBeTransferred: Boolean = false,
val transferee: TransfereeState = TransfereeState.NoTransferee
val transferee: TransfereeState = TransfereeState.NoTransferee,
val isSharingScreen: Boolean = false
) : MavericksState {
sealed class TransfereeState {

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.call.webrtc
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import javax.inject.Inject
class ScreenCaptureServiceConnection @Inject constructor(
private val context: Context
) : ServiceConnection {
private var isBound = false
private var screenCaptureService: ScreenCaptureService? = null
fun bind() {
if (!isBound) {
Intent(context, ScreenCaptureService::class.java).also { intent ->
context.bindService(intent, this, 0)
}
}
}
fun stopScreenCapturing() {
screenCaptureService?.stopService()
}
override fun onServiceConnected(className: ComponentName, binder: IBinder) {
screenCaptureService = (binder as ScreenCaptureService.LocalBinder).getService()
isBound = true
}
override fun onServiceDisconnected(className: ComponentName) {
isBound = false
screenCaptureService = null
}
}

View file

@ -770,7 +770,11 @@ class WebRtcCall(
return currentCaptureFormat
}
fun shareScreen() {
fun startSharingScreen() {
// TODO. Will be handled within the next PR.
}
fun stopSharingScreen() {
// TODO. Will be handled within the next PR.
}

View file

@ -11,7 +11,7 @@
android:id="@+id/callControlsShareScreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:actionTitle="@string/call_share_screen"
app:actionTitle="@string/call_start_screen_sharing"
app:leftIcon="@drawable/ic_share_screen"
app:tint="?vctr_content_primary"
app:titleTextColor="?vctr_content_primary" />

View file

@ -480,7 +480,8 @@
<string name="call_camera_back">Back</string>
<string name="call_format_turn_hd_off">Turn HD off</string>
<string name="call_format_turn_hd_on">Turn HD on</string>
<string name="call_share_screen">Share screen</string>
<string name="call_start_screen_sharing">Share screen</string>
<string name="call_stop_screen_sharing">Stop screen sharing</string>
<string name="option_send_files">Send files</string>
<string name="option_send_sticker">Send sticker</string>