Przeglądaj źródła

feat: 录音权限授予弹窗

DoggyZhang 2 miesięcy temu
rodzic
commit
eb0ea4422a

+ 10 - 3
frame/tuikit/TUIChat/tuichat/src/main/java/com/tencent/qcloud/tuikit/tuichat/component/audio/AudioRecorder.java

@@ -1,5 +1,7 @@
 package com.tencent.qcloud.tuikit.tuichat.component.audio;
 
+import static com.tencent.qcloud.tuicore.TUIConstants.TUICalling.ERROR_MIC_PERMISSION_REFUSED;
+
 import android.Manifest;
 import android.content.pm.PackageManager;
 import android.media.MediaPlayer;
@@ -17,7 +19,6 @@ import com.tencent.qcloud.tuikit.timcommon.util.FileUtil;
 import com.tencent.qcloud.tuikit.tuichat.R;
 import com.tencent.qcloud.tuikit.tuichat.TUIChatService;
 import com.tencent.qcloud.tuikit.tuichat.model.AIDenoiseSignatureManager;
-import com.tencent.qcloud.tuikit.tuichat.util.PermissionHelper;
 import com.tencent.qcloud.tuikit.tuichat.util.TUIChatLog;
 
 public class AudioRecorder {
@@ -74,6 +75,13 @@ public class AudioRecorder {
             return;
         }
 
+        if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(TUIChatService.getAppContext(), Manifest.permission.RECORD_AUDIO)) {
+            if (callback != null) {
+                callback.onFailed(ERROR_MIC_PERMISSION_REFUSED, "no record permission");
+                return;
+            }
+        }
+
         String audioFilePath = TUIConfig.getRecordDir() + System.currentTimeMillis() + ".m4a";
         AudioRecorderInternalCallback internalCallback = new AudioRecorderInternalCallback() {
             @Override
@@ -117,9 +125,8 @@ public class AudioRecorder {
         };
         if (PackageManager.PERMISSION_GRANTED != ActivityCompat.checkSelfPermission(TUIChatService.getAppContext(), Manifest.permission.RECORD_AUDIO)) {
             if (callback != null) {
-                callback.onFailed(TUIConstants.TUICalling.ERROR_MIC_PERMISSION_REFUSED, "no record permission");
+                callback.onFailed(ERROR_MIC_PERMISSION_REFUSED, "no record permission");
             }
-            PermissionHelper.requestPermission(PermissionHelper.PERMISSION_MICROPHONE, null);
         } else {
             if (instance.recorder != null) {
                 instance.recorder.startRecord(audioFilePath, internalCallback);

+ 53 - 3
module/im/src/main/java/com/adealink/weparty/im/session/comp/SessionBottomAudioComp.kt

@@ -1,8 +1,12 @@
 package com.adealink.weparty.im.session.comp
 
+import android.Manifest
 import android.annotation.SuppressLint
+import androidx.fragment.app.FragmentActivity
 import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
 import com.adealink.frame.aab.util.getCompatColor
+import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.log.Log
 import com.adealink.frame.mvvm.view.ViewComponent
 import com.adealink.frame.mvvm.viewmodel.activityViewModels
@@ -18,15 +22,19 @@ import com.adealink.weparty.im.session.comp.input.InputState
 import com.adealink.weparty.im.session.comp.viewmodel.SessionAudioViewModel
 import com.adealink.weparty.im.session.comp.viewmodel.SessionInputViewModel
 import com.adealink.weparty.module.im.data.TAG_IM_AUDIO
-import com.tencent.qcloud.tuicore.TUIConstants
+import com.adealink.weparty.permission.PermissionUtils
+import com.tencent.qcloud.tuicore.TUIConstants.TUICalling
 import com.tencent.qcloud.tuikit.tuichat.bean.ChatInfo
 import com.tencent.qcloud.tuikit.tuichat.component.audio.AudioPlayer
 import com.tencent.qcloud.tuikit.tuichat.component.audio.AudioRecorder
 import com.tencent.qcloud.tuikit.tuichat.component.audio.AudioRecorder.AudioRecorderCallback
 import com.tencent.qcloud.tuikit.tuichat.presenter.ChatPresenter
 import com.tencent.qcloud.tuikit.tuichat.util.ChatMessageBuilder
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.suspendCancellableCoroutine
 import java.util.Timer
 import java.util.TimerTask
+import kotlin.coroutines.resume
 import kotlin.math.max
 import kotlin.math.pow
 import com.adealink.weparty.R as APP_R
@@ -208,9 +216,10 @@ class SessionBottomAudioComp(
                     "startAudioRecord, onFailed, errorCode:$errorCode, errorMessage:$errorMessage"
                 )
                 hideVoiceLayout()
-                if (errorCode == TUIConstants.TUICalling.ERROR_MIC_PERMISSION_REFUSED) {
+                if (errorCode == TUICalling.ERROR_MIC_PERMISSION_REFUSED) {
                     //没有授予权限
-                } else if (errorCode == AudioRecorder.ERROR_CODE_MIC_IS_BEING_USED || errorCode == TUIConstants.TUICalling.ERROR_STATUS_IN_CALL) {
+                    requestPermission()
+                } else if (errorCode == AudioRecorder.ERROR_CODE_MIC_IS_BEING_USED || errorCode == TUICalling.ERROR_STATUS_IN_CALL) {
                     showToast(R.string.im_mic_is_being_used_cant_record)
                 } else {
                     showToast(R.string.im_record_audio_failed)
@@ -246,6 +255,47 @@ class SessionBottomAudioComp(
         })
     }
 
+
+    private fun requestPermission() {
+        val act = activity ?: return
+        viewLifecycleOwner.lifecycleScope.launch {
+            val granted = requestPermission(act)
+            if (granted) {
+                inputViewModel.execute(InputAction.CLICK_AUDIO)
+            } else {
+                inputViewModel.execute(InputAction.EMPTY_CLICKED)
+            }
+        }
+    }
+
+
+    private val permissions = arrayOf(Manifest.permission.RECORD_AUDIO)
+    private suspend fun requestPermission(activity: FragmentActivity): Boolean {
+        return suspendCancellableCoroutine { coroutine ->
+            if (PermissionUtils.hasPermissions(activity, *permissions)) {
+                if (coroutine.isActive) {
+                    coroutine.resume(true)
+                }
+                return@suspendCancellableCoroutine
+            }
+            PermissionUtils.requestPermissions(
+                activity,
+                permissions.toList(),
+                getCompatString(R.string.im_audio_permission_request_tips),
+                onGranted = {
+                    if (coroutine.isActive) {
+                        coroutine.resume(true)
+                    }
+                },
+                onDenied = {
+                    if (coroutine.isActive) {
+                        coroutine.resume(false)
+                    }
+                }
+            )
+        }
+    }
+
     private fun pauseAudioRecord() {
         Log.d(TAG_IM_AUDIO, "pauseAudioRecord")
         voiceBar.vVoiceWave.pause()

+ 3 - 1
module/im/src/main/java/com/adealink/weparty/im/session/comp/viewmodel/SessionInputViewModel.kt

@@ -65,7 +65,9 @@ class SessionInputViewModel : BaseViewModel() {
      * 参考:InputAction
      */
     fun execute(action: InputAction) {
-        stateMachine.execute(action)
+        viewModelScope.launch {
+            stateMachine.execute(action)
+        }
     }
 
     fun registerTransaction(

+ 1 - 0
module/im/src/main/res/values-in/strings.xml

@@ -37,4 +37,5 @@
     <string name="im_playmate_order_apply_refund">Pengembalian dana pengguna sedang diproses, harap kirimkan informasi</string>
     <string name="im_playmate_order_refund">Pengembalian dana pengguna</string>
     <string name="im_playmate_order_note">Komentar: %s</string>
+    <string name="im_audio_permission_request_tips">Izin penggunaan mikrofon diperlukan untuk menggunakan fungsi suara.</string>
 </resources>

+ 1 - 0
module/im/src/main/res/values-zh/strings.xml

@@ -37,4 +37,5 @@
     <string name="im_playmate_order_apply_refund">用户退款中,请提交资料</string>
     <string name="im_playmate_order_refund">用户退款</string>
     <string name="im_playmate_order_note">备注: %s</string>
+    <string name="im_audio_permission_request_tips">使用语音功能需要授予麦克风权限</string>
 </resources>

+ 1 - 0
module/im/src/main/res/values/strings.xml

@@ -38,4 +38,5 @@
     <string name="im_playmate_order_apply_refund">User refund in progress, please submit information</string>
     <string name="im_playmate_order_refund">User refund</string>
     <string name="im_playmate_order_note">Note: %s</string>
+    <string name="im_audio_permission_request_tips">Microphone permissions need to be granted to use the voice function.</string>
 </resources>