mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-18 02:10:59 +03:00
Fix/android voice call (#16180)
* fix(android): handle missing audio permission in voice calls - Avoid stop errors when voice capture was never started - Dispatch voice call error dialogs on the main thread - Explain how to enable Audio capture on the Screen share page Signed-off-by: fufesou <linlong1266@gmail.com> * fix(android): restore audio after failed voice call switches * fix: translations Signed-off-by: fufesou <linlong1266@gmail.com> * fix: translatin Signed-off-by: fufesou <linlong1266@gmail.com> * fix(i18n): match UI label capitalization in translated messages Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com> Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
This commit is contained in:
@@ -51,6 +51,7 @@ class AudioRecordHandle(private var context: Context, private var isVideoStart:
|
||||
private var minBufferSize = 0
|
||||
private var audioRecordStat = false
|
||||
private var audioThread: Thread? = null
|
||||
private var playbackCapturePending = false
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
fun createAudioRecorder(inVoiceCall: Boolean, mediaProjection: MediaProjection?): Boolean {
|
||||
@@ -193,6 +194,17 @@ class AudioRecordHandle(private var context: Context, private var isVideoStart:
|
||||
return audioRecorder?.audioSource == MediaRecorder.AudioSource.VOICE_COMMUNICATION
|
||||
}
|
||||
|
||||
fun getVoiceCallStartError(): String {
|
||||
return if (ActivityCompat.checkSelfPermission(
|
||||
context,
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
) != PackageManager.PERMISSION_GRANTED) {
|
||||
"To start a voice call, enable \"Audio capture\" on the \"Screen share\" page."
|
||||
} else {
|
||||
"Failed to start voice call."
|
||||
}
|
||||
}
|
||||
|
||||
fun onVoiceCallStarted(mediaProjection: MediaProjection?): Boolean {
|
||||
if (!isSupportVoiceCall()) {
|
||||
return false
|
||||
@@ -220,6 +232,7 @@ class AudioRecordHandle(private var context: Context, private var isVideoStart:
|
||||
if (it.getAudioSource() == MediaRecorder.AudioSource.VOICE_COMMUNICATION) {
|
||||
return true
|
||||
}
|
||||
playbackCapturePending = true
|
||||
}
|
||||
audioRecordStat = false
|
||||
audioThread?.join()
|
||||
@@ -234,11 +247,10 @@ class AudioRecordHandle(private var context: Context, private var isVideoStart:
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.M)
|
||||
fun switchOutVoiceCall(mediaProjection: MediaProjection?): Boolean {
|
||||
audioRecorder?.let {
|
||||
if (it.getAudioSource() != MediaRecorder.AudioSource.VOICE_COMMUNICATION) {
|
||||
return true
|
||||
}
|
||||
if (!isVoiceCallActive() && !playbackCapturePending) {
|
||||
return true
|
||||
}
|
||||
playbackCapturePending = true
|
||||
audioRecordStat = false
|
||||
audioThread?.join()
|
||||
|
||||
@@ -246,7 +258,11 @@ class AudioRecordHandle(private var context: Context, private var isVideoStart:
|
||||
Log.e(logTag, "createAudioRecorder fail")
|
||||
return false
|
||||
}
|
||||
return startAudioRecorder()
|
||||
val started = startAudioRecorder()
|
||||
if (started) {
|
||||
playbackCapturePending = false
|
||||
}
|
||||
return started
|
||||
}
|
||||
|
||||
fun tryReleaseAudio() {
|
||||
@@ -256,6 +272,7 @@ class AudioRecordHandle(private var context: Context, private var isVideoStart:
|
||||
audioRecordStat = false
|
||||
audioThread?.join()
|
||||
audioThread = null
|
||||
playbackCapturePending = false
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
|
||||
@@ -969,7 +969,7 @@ class MainActivity : FlutterActivity() {
|
||||
flutterMethodChannel?.invokeMethod("msgbox", mapOf(
|
||||
"type" to "custom-nook-nocancel-hasclose-error",
|
||||
"title" to "Voice call",
|
||||
"text" to "Failed to start voice call."))
|
||||
"text" to audioRecordHandle.getVoiceCallStartError()))
|
||||
} else {
|
||||
Log.d(logTag, "onVoiceCallStarted success")
|
||||
}
|
||||
|
||||
@@ -153,19 +153,13 @@ class MainService : Service() {
|
||||
} else {
|
||||
if (!switchOutVoiceCall()) {
|
||||
Log.e(logTag, "switchOutVoiceCall fail")
|
||||
MainActivity.flutterMethodChannel?.invokeMethod("msgbox", mapOf(
|
||||
"type" to "custom-nook-nocancel-hasclose-error",
|
||||
"title" to "Voice call",
|
||||
"text" to "Failed to switch out voice call."))
|
||||
showVoiceCallError("Failed to switch out voice call.")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!switchToVoiceCall()) {
|
||||
Log.e(logTag, "switchToVoiceCall fail")
|
||||
MainActivity.flutterMethodChannel?.invokeMethod("msgbox", mapOf(
|
||||
"type" to "custom-nook-nocancel-hasclose-error",
|
||||
"title" to "Voice call",
|
||||
"text" to "Failed to switch to voice call."))
|
||||
showVoiceCallError(audioRecordHandle.getVoiceCallStartError())
|
||||
}
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
@@ -507,6 +501,15 @@ class MainService : Service() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showVoiceCallError(message: String) {
|
||||
Handler(Looper.getMainLooper()).post {
|
||||
MainActivity.flutterMethodChannel?.invokeMethod("msgbox", mapOf(
|
||||
"type" to "custom-nook-nocancel-hasclose-error",
|
||||
"title" to "Voice call",
|
||||
"text" to message))
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun startMicrophoneCapture(startAudio: () -> Boolean): Boolean {
|
||||
if (!setMicrophoneForegroundService(true)) {
|
||||
|
||||
Reference in New Issue
Block a user