Added export feature for call recordings
This commit is contained in:
parent
d630f0ceec
commit
61454f5923
8 changed files with 65 additions and 13 deletions
|
@ -19,6 +19,7 @@ Group changes to describe their impact on the project, as follows:
|
|||
- Image & Video in-app viewers allow for full-screen display
|
||||
- Display name can be set during assistant when creating / logging in a sip.linphone.org account
|
||||
- Android 13 support, using new post notifications & media permissions
|
||||
- Call recordings can be exported
|
||||
|
||||
### Changed
|
||||
- In-call views have been re-designed
|
||||
|
|
|
@ -163,6 +163,10 @@ class RecordingData(val path: String, private val recordingListener: RecordingLi
|
|||
}
|
||||
}
|
||||
|
||||
fun export() {
|
||||
recordingListener.onExportClicked(path)
|
||||
}
|
||||
|
||||
private fun initPlayer() {
|
||||
// In case no headphones/headset is connected, use speaker sound card to play recordings, otherwise use earpiece
|
||||
// If none are available, default one will be used
|
||||
|
@ -218,5 +222,6 @@ class RecordingData(val path: String, private val recordingListener: RecordingLi
|
|||
interface RecordingListener {
|
||||
fun onPlayingStarted(videoAvailable: Boolean)
|
||||
fun onPlayingEnded()
|
||||
fun onExportClicked(path: String)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.activities.main.recordings.fragments
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
|
@ -32,6 +34,7 @@ import org.linphone.activities.main.recordings.viewmodels.RecordingsViewModel
|
|||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.RecordingsFragmentBinding
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.FileUtils
|
||||
import org.linphone.utils.RecyclerViewHeaderDecoration
|
||||
|
||||
class RecordingsFragment : MasterFragment<RecordingsFragmentBinding, RecordingsListAdapter>() {
|
||||
|
@ -75,6 +78,25 @@ class RecordingsFragment : MasterFragment<RecordingsFragmentBinding, RecordingsL
|
|||
adapter.submitList(recordings)
|
||||
}
|
||||
|
||||
viewModel.exportRecordingEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { path ->
|
||||
val publicFilePath = FileUtils.getPublicFilePath(requireContext(), "file://$path")
|
||||
Log.i("[Recordings] Exporting file [$path] with public URI [$publicFilePath]")
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
intent.type = " video/x-matroska"
|
||||
intent.putExtra(Intent.EXTRA_STREAM, publicFilePath)
|
||||
intent.putExtra(Intent.EXTRA_TEXT, getString(R.string.recordings_export))
|
||||
|
||||
try {
|
||||
requireActivity().startActivity(Intent.createChooser(intent, getString(R.string.recordings_export)))
|
||||
} catch (anfe: ActivityNotFoundException) {
|
||||
Log.e(anfe)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding.setBackClickListener { goBack() }
|
||||
|
||||
binding.setEditClickListener { listSelectionViewModel.isEditionEnabled.value = true }
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.linphone.LinphoneApplication.Companion.coreContext
|
|||
import org.linphone.activities.main.recordings.data.RecordingData
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.FileUtils
|
||||
|
||||
class RecordingsViewModel : ViewModel() {
|
||||
|
@ -34,6 +35,10 @@ class RecordingsViewModel : ViewModel() {
|
|||
|
||||
val isVideoVisible = MutableLiveData<Boolean>()
|
||||
|
||||
val exportRecordingEvent: MutableLiveData<Event<String>> by lazy {
|
||||
MutableLiveData<Event<String>>()
|
||||
}
|
||||
|
||||
private var recordingPlayingAudioFocusRequest: AudioFocusRequestCompat? = null
|
||||
|
||||
private val recordingListener = object : RecordingData.RecordingListener {
|
||||
|
@ -56,6 +61,10 @@ class RecordingsViewModel : ViewModel() {
|
|||
|
||||
isVideoVisible.value = false
|
||||
}
|
||||
|
||||
override fun onExportClicked(path: String) {
|
||||
exportRecordingEvent.value = Event(path)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
|
@ -93,7 +102,7 @@ class RecordingsViewModel : ViewModel() {
|
|||
val list = arrayListOf<RecordingData>()
|
||||
|
||||
for (f in FileUtils.getFileStorageDir().listFiles().orEmpty()) {
|
||||
Log.i("[Recordings] Found file ${f.path}")
|
||||
Log.d("[Recordings] Found file ${f.path}")
|
||||
if (RecordingData.RECORD_PATTERN.matcher(f.path).matches()) {
|
||||
list.add(
|
||||
RecordingData(
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_toLeftOf="@id/delete"
|
||||
android:layout_toLeftOf="@id/export"
|
||||
android:layout_toRightOf="@id/record_play_pause">
|
||||
|
||||
<LinearLayout
|
||||
|
@ -70,9 +70,9 @@
|
|||
android:layout_alignParentTop="true">
|
||||
|
||||
<TextView
|
||||
android:text="@{data.name}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{data.name}" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -80,9 +80,9 @@
|
|||
android:text=" - " />
|
||||
|
||||
<TextView
|
||||
android:text="@{data.formattedDate}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{data.formattedDate}" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -96,10 +96,10 @@
|
|||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:text="@{data.formattedPosition}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
android:layout_gravity="center"
|
||||
android:text="@{data.formattedPosition}" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -107,27 +107,37 @@
|
|||
android:text="/" />
|
||||
|
||||
<TextView
|
||||
android:text="@{data.formattedDuration}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{data.formattedDuration}" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/record_progression_bar"
|
||||
onProgressChanged="@{(progress) -> data.onProgressChanged(progress)}"
|
||||
android:max="@{data.duration}"
|
||||
android:progress="@{data.position}"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginRight="5dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:max="@{data.duration}"
|
||||
android:progress="@{data.position}"
|
||||
android:progressTint="?attr/accentColor"
|
||||
android:thumbTint="?attr/accentColor" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/export"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:onClick="@{() -> data.export()}"
|
||||
android:src="@drawable/icon_share" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</layout>
|
||||
|
|
|
@ -731,4 +731,6 @@
|
|||
<string name="chat_message_context_menu_turn_on_notifications">Activer les notifications</string>
|
||||
<string name="content_description_muted_chat_room">Les notifications sont désactivées pour cette conversation</string>
|
||||
<string name="chat_room_context_menu_go_to_contact">Voir le contact</string>
|
||||
<string name="recordings_export">Exporter l\'enregistrement avec…</string>
|
||||
<string name="content_description_recording_export">Exporter l\'enregistrement</string>
|
||||
</resources>
|
|
@ -234,6 +234,7 @@
|
|||
|
||||
<!-- Recordings -->
|
||||
<string name="recordings_empty_list">No recordings</string>
|
||||
<string name="recordings_export">Export recording using…</string>
|
||||
|
||||
<!-- Conferencing -->
|
||||
<string name="conference">Meeting</string>
|
||||
|
@ -861,4 +862,5 @@
|
|||
<string name="content_description_participant_is_paused">Participant has momentarily left the group call</string>
|
||||
<string name="content_description_toggle_conference_info_details">Toggle meeting information details visibility</string>
|
||||
<string name="content_description_conference_participants">Group call participants</string>
|
||||
<string name="content_description_recording_export">Export recording</string>
|
||||
</resources>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<files-path name="internal_files" path="." />
|
||||
<files-path name="internal_recordings" path="Download/" />
|
||||
<external-files-path name="pictures" path="Pictures/" />
|
||||
<external-files-path name="downloads" path="Download/" />
|
||||
<external-files-path name="files" path="." />
|
||||
|
|
Loading…
Reference in a new issue