mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-18 03:48:08 +00:00
Added call recording
This commit is contained in:
parent
95e8ef9fc4
commit
bdca32be49
10 changed files with 71 additions and 8 deletions
|
|
@ -42,6 +42,7 @@ import org.linphone.ui.call.CallActivity
|
|||
import org.linphone.utils.ActivityMonitor
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
class CoreContext @UiThread constructor(val context: Context) : HandlerThread("Core Thread") {
|
||||
companion object {
|
||||
|
|
@ -280,8 +281,9 @@ class CoreContext @UiThread constructor(val context: Context) : HandlerThread("C
|
|||
/*if (LinphoneUtils.checkIfNetworkHasLowBandwidth(context)) {
|
||||
Log.w("[Context] Enabling low bandwidth mode!")
|
||||
params.isLowBandwidthEnabled = true
|
||||
}
|
||||
params.recordFile = LinphoneUtils.getRecordingFilePathForAddress(address)*/
|
||||
}*/
|
||||
|
||||
params.recordFile = LinphoneUtils.getRecordingFilePathForAddress(address)
|
||||
|
||||
if (localAddress != null) {
|
||||
val account = core.accountList.find { account ->
|
||||
|
|
@ -299,10 +301,6 @@ class CoreContext @UiThread constructor(val context: Context) : HandlerThread("C
|
|||
}
|
||||
}
|
||||
|
||||
/*if (corePreferences.sendEarlyMedia) {
|
||||
params.isEarlyMediaSendingEnabled = true
|
||||
}*/
|
||||
|
||||
val call = core.inviteAddressWithParams(address, params)
|
||||
Log.i("$TAG Starting call $call")
|
||||
}
|
||||
|
|
@ -343,7 +341,7 @@ class CoreContext @UiThread constructor(val context: Context) : HandlerThread("C
|
|||
return
|
||||
}
|
||||
|
||||
// params.recordFile = LinphoneUtils.getRecordingFilePathForAddress(call.remoteAddress)
|
||||
params.recordFile = LinphoneUtils.getRecordingFilePathForAddress(call.remoteAddress)
|
||||
|
||||
/*if (LinphoneUtils.checkIfNetworkHasLowBandwidth(context)) {
|
||||
Log.w("$TAG Enabling low bandwidth mode!")
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ class CallActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun showGreenToast(message: String, @DrawableRes icon: Int, duration: Long = 4000) {
|
||||
fun showGreenToast(message: String, @DrawableRes icon: Int, duration: Long = 4000) {
|
||||
val greenToast = AppUtils.getGreenToast(this, binding.toastsArea, message, icon)
|
||||
binding.toastsArea.addView(greenToast.root)
|
||||
|
||||
|
|
|
|||
|
|
@ -228,6 +228,15 @@ class ActiveCallFragment : GenericCallFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
callViewModel.isRecording.observe(viewLifecycleOwner) { recording ->
|
||||
val text = if (recording) {
|
||||
getString(R.string.toast_call_recording_started)
|
||||
} else {
|
||||
getString(R.string.toast_call_recording_stopped)
|
||||
}
|
||||
(requireActivity() as CallActivity).showGreenToast(text, R.drawable.record)
|
||||
}
|
||||
|
||||
actionsBottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
when (newState) {
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val isOutgoing = MutableLiveData<Boolean>()
|
||||
|
||||
val isRecording = MutableLiveData<Boolean>()
|
||||
|
||||
val isMicrophoneMuted = MutableLiveData<Boolean>()
|
||||
|
||||
val isSpeakerEnabled = MutableLiveData<Boolean>()
|
||||
|
|
@ -503,6 +505,23 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleRecording() {
|
||||
coreContext.postOnCoreThread {
|
||||
if (::currentCall.isInitialized) {
|
||||
if (currentCall.params.isRecording) {
|
||||
Log.i("$TAG Stopping call recording")
|
||||
currentCall.stopRecording()
|
||||
} else {
|
||||
Log.i("$TAG Starting call recording")
|
||||
currentCall.startRecording()
|
||||
}
|
||||
val recording = currentCall.params.isRecording
|
||||
isRecording.postValue(recording)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleFullScreen() {
|
||||
if (fullScreenMode.value == false && isVideoEnabled.value == false) return
|
||||
|
|
@ -611,6 +630,11 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
isOutgoing.postValue(call.dir == Call.Dir.Outgoing)
|
||||
|
||||
if (call.params.isRecording) {
|
||||
// Do not set it to false to prevent the "no longer recording" toast to be displayed
|
||||
isRecording.postValue(true)
|
||||
}
|
||||
|
||||
val address = call.remoteAddress.clone()
|
||||
address.clean()
|
||||
displayedAddress.postValue(address.asStringUriOnly())
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ package org.linphone.utils
|
|||
import androidx.annotation.AnyThread
|
||||
import androidx.annotation.IntegerRes
|
||||
import androidx.annotation.WorkerThread
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.core.Account
|
||||
|
|
@ -37,6 +41,8 @@ class LinphoneUtils {
|
|||
companion object {
|
||||
private const val TAG = "[Linphone Utils]"
|
||||
|
||||
private const val RECORDING_DATE_PATTERN = "dd-MM-yyyy-HH-mm-ss"
|
||||
|
||||
@WorkerThread
|
||||
fun getDefaultAccount(): Account? {
|
||||
return coreContext.core.defaultAccount ?: coreContext.core.accountList.firstOrNull()
|
||||
|
|
@ -192,6 +198,17 @@ class LinphoneUtils {
|
|||
return "${localSipUri.asStringUriOnly()}~${remoteSipUri.asStringUriOnly()}"
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getRecordingFilePathForAddress(address: Address): String {
|
||||
val displayName = getDisplayName(address)
|
||||
val dateFormat: DateFormat = SimpleDateFormat(
|
||||
RECORDING_DATE_PATTERN,
|
||||
Locale.getDefault()
|
||||
)
|
||||
val fileName = "${displayName}_${dateFormat.format(Date())}.mkv"
|
||||
return FileUtils.getFileStoragePath(fileName).absolutePath
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun callStateToString(state: Call.State): String {
|
||||
return when (state) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/shape_round_in_call_disabled_button_background" />
|
||||
<item android:state_selected="true"
|
||||
android:drawable="@drawable/shape_round_in_call_selected_button_background" />
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/shape_round_in_call_pressed_button_background" />
|
||||
<item
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<size android:width="55dp" android:height="55dp" />
|
||||
<solid android:color="@color/red_danger_500"/>
|
||||
</shape>
|
||||
|
|
@ -147,12 +147,14 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/record_call"
|
||||
android:onClick="@{() -> viewModel.toggleRecording()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/call_button_size"
|
||||
android:layout_marginTop="@dimen/call_extra_button_top_margin"
|
||||
android:background="@drawable/in_call_button_background"
|
||||
android:padding="@dimen/call_button_icon_padding"
|
||||
android:src="@drawable/record"
|
||||
android:selected="@{viewModel.isRecording()}"
|
||||
app:layout_constraintDimensionRatio="1:1"
|
||||
app:layout_constraintEnd_toEndOf="@id/record_call_label"
|
||||
app:layout_constraintStart_toStartOf="@id/record_call_label"
|
||||
|
|
@ -232,6 +234,7 @@
|
|||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/in_call_extra_action_label_style"
|
||||
android:id="@+id/record_call_label"
|
||||
android:onClick="@{() -> viewModel.toggleRecording()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="15dp"
|
||||
|
|
|
|||
|
|
@ -147,12 +147,14 @@
|
|||
|
||||
<ImageView
|
||||
android:id="@+id/record_call"
|
||||
android:onClick="@{() -> viewModel.toggleRecording()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/call_button_size"
|
||||
android:layout_marginTop="@dimen/call_extra_button_top_margin"
|
||||
android:padding="@dimen/call_button_icon_padding"
|
||||
android:background="@drawable/in_call_button_background"
|
||||
android:src="@drawable/record"
|
||||
android:selected="@{viewModel.isRecording()}"
|
||||
app:tint="@color/white"
|
||||
app:layout_constraintDimensionRatio="1:1"
|
||||
app:layout_constraintTop_toBottomOf="@id/calls_list_label"
|
||||
|
|
@ -228,6 +230,7 @@
|
|||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/in_call_extra_action_label_style"
|
||||
android:id="@+id/record_call_label"
|
||||
android:onClick="@{() -> viewModel.toggleRecording()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="15dp"
|
||||
|
|
|
|||
|
|
@ -301,6 +301,8 @@
|
|||
<string name="toast_call_transfer_in_progress">Call is being transferred to %s</string>
|
||||
<string name="toast_call_transfer_successful">Call has been transferred to %s</string>
|
||||
<string name="toast_call_transfer_failed">Call transfer to %s failed!</string>
|
||||
<string name="toast_call_recording_started">Call is being recorded</string>
|
||||
<string name="toast_call_recording_stopped">Call is no longer being recorded</string>
|
||||
|
||||
<!-- Keep <u></u> in following strings translations! -->
|
||||
<string name="welcome_carousel_skip"><u>Skip</u></string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue