비디오 통화 연결 되고 난 후 앱 권한 설정 하고 올때

카메라 권한이 없는 사용자가 비디오 통화 연결 되고 난 후에 앱 권한 설정 하고 돌아 올때
어떻게 로컬 카메라 비디오 세팅을 할수 있습니까?
권한 획득 후 돌아와서 DirectCall.startVideo()가 호출 됐는데 나오지 않습니다… 어떻게 해야 할까요??

아래는 제 코드입니다

class VideoCallActivity : CallActivity() {

    private var mIsVideoEnabled = false

    private var permissionToRecordAccepted = false
    private var requiredPermissions = arrayListOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA)
    private val PERMISSION_REQUEST_CODE = 100

    private val requestPermissionLauncher: ActivityResultLauncher<String> =
        registerForActivityResult(ActivityResultContracts.RequestPermission()) { permission ->
            Log.d(TAG, ":: registerForActivityResult ")
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED) {

                Log.d(TAG, ":: registerForActivityResult granted permission=$permission mDoLocalVideoStart=$mDoLocalVideoStart mDirectCall=$mDirectCall")
                    if(permission) {
                        if (mDoLocalVideoStart == false) {
                            mDoLocalVideoStart = true
                            return@registerForActivityResult
                        }
                        mDoLocalVideoStart = false
                        if (mDirectCall != null) {
                            Log.d(TAG, ":: registerForActivityResult permission = $permission")
//                            mDoLocalVideoStart = false
//                            updateCallService()
                            mDirectCall?.let {
//                                setLocalVideoSettings(it)
//                                mIsVideoEnabled = true
//                                mImageViewVideoOff.isSelected = !mIsVideoEnabled
                            }
//                            initViews()
//                            setViews()
                            setAudioDevice()
                        }
                    }
            }
        }

    private fun checkCameraAndAudioPermission() {
        Log.d(TAG, "checkCameraAndAudioPermission:: 1111 ")
        var rejectedPermissionList = ArrayList<String>()

        for (permission in requiredPermissions) {
            when {
                ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED -> {
                    Log.d(TAG, "checkCameraAndAudioPermission:: checkSelfPermission ")
                    rejectedPermissionList.add(permission)
                }
                shouldShowRequestPermissionRationale(permission) -> {
                    Log.d(TAG, "checkCameraAndAudioPermission:: shouldShowRequestPermissionRationale ")
                    showPermissionDialog()
                }
                else -> {
                    Log.d(TAG, "checkCameraAndAudioPermission:: else ")
                    requestPermissionLauncher.launch(
                        permission
                    )
                }
            }
        }

        if (rejectedPermissionList.isNotEmpty()) {
            val array = arrayOfNulls<String>(rejectedPermissionList.size)
            Log.d(TAG, "checkCameraAndAudioPermission:: 권한 없음 ")
            ActivityCompat.requestPermissions(this, rejectedPermissionList.toArray(array), PERMISSION_REQUEST_CODE)
        } else {
            Log.d(TAG, "checkCameraAndAudioPermission:: 권한 있음 ")
            mDirectCall?.let {
//                setLocalVideoSettings(it)
                it.startVideo()
            }
        }
    }

    var isShowDialog = false
    private fun showPermissionDialog() {
        if (isShowDialog) {
            isShowDialog = false
            return
        }
        MaterialAlertDialogBuilder(this)
            .setTitle(R.string.perm__lab_audio_camera)
            .setMessage(R.string.perm__desc_audio_camera)
            .setPositiveButton(R.string.request_permission) { dialogInterface, _ ->
                dialogInterface.dismiss()
                UIUtil.startInstalledAppDetailSetting(this)
            }
            .setOnDismissListener {
                isShowDialog = false
            }
            .setNegativeButton(R.string.cancel, null)
            .create()
            .show()
        isShowDialog = true
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            PERMISSION_REQUEST_CODE -> {
                if (grantResults.isNotEmpty()) {
                    for ((i, permission) in permissions.withIndex()) {
                        if(grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                            // 권한 획득 실패
                            Log.d(TAG, "onRequestPermissionsResult::  권한 획득 실패 $permission")
                            showPermissionDialog()
                        }
                    }
                }
            }
        }
    }

    //+ Views
    private lateinit var mVideoViewFullScreen: SendBirdVideoView
    private lateinit var mViewConnectingVideoViewFullScreenFg: View
    private lateinit var mRelativeLayoutVideoViewSmall: RelativeLayout
    private lateinit var mVideoViewSmall: SendBirdVideoView
    private lateinit var mImageViewCameraSwitch: ImageView
    private lateinit var mImageViewVideoOff: ImageView

    //- Views
    override val layoutResourceId: Int
        get() = R.layout.activity_video_call

    override fun initViews() {
        super.initViews()
        Log.d(TAG, "[VideoCallActivity] :: initViews()")
        mVideoViewFullScreen = findViewById(R.id.video_view_fullscreen)
        mViewConnectingVideoViewFullScreenFg =
            findViewById(R.id.view_connecting_video_view_fullscreen_fg)
        mRelativeLayoutVideoViewSmall = findViewById(R.id.relative_layout_video_view_small)
        mVideoViewSmall = findViewById(R.id.video_view_small)
        mImageViewCameraSwitch = findViewById(R.id.image_view_camera_switch)
        mImageViewVideoOff = findViewById(R.id.image_view_video_off)
    }

    override fun setViews() {
        super.setViews()
        Log.d(TAG, "[VideoCallActivity] :: setViews() ")
        mVideoViewFullScreen.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT)
        mVideoViewFullScreen.setZOrderMediaOverlay(false)
        mVideoViewFullScreen.setEnableHardwareScaler(true)
        mVideoViewSmall.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT)
        mVideoViewSmall.setZOrderMediaOverlay(true)
        mVideoViewSmall.setEnableHardwareScaler(true)
        val directCall = mDirectCall
        if (directCall != null) {
            if (directCall.myRole == DirectCallUserRole.CALLER && mState == STATE.STATE_OUTGOING) {
                directCall.setLocalVideoView(mVideoViewFullScreen)
                directCall.setRemoteVideoView(mVideoViewSmall)
            } else {
                directCall.setLocalVideoView(mVideoViewSmall)
                directCall.setRemoteVideoView(mVideoViewFullScreen)
            }
        }
        mImageViewCameraSwitch.setOnClickListener { view: View? ->
            directCall?.switchCamera(object : CompletionHandler {
                override fun onResult(e: SendBirdException?) {
                    if (e != null) {
                        Log.d(TAG, "[VideoCallActivity] switchCamera(e: " + e.message + ")")
                    }
                }
            })
        }
        mIsVideoEnabled = if (mDirectCall != null && !mDoLocalVideoStart) {
            directCall?.isLocalVideoEnabled ?: false
        } else {
            true
        }
        Log.d(TAG, "[VideoCallActivity] :: setViews() mIsVideoEnabled=$mIsVideoEnabled ")
        mImageViewVideoOff.isSelected = !mIsVideoEnabled
        mImageViewVideoOff.setOnClickListener { view: View? ->
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                ToastUtils.showToast(this, "카메라 권한 설정이 필요 합니다.")
                return@setOnClickListener
            }
            val call = mDirectCall
            Log.d(TAG, "setViews:: call=$call mIsVideoEnabled=$mIsVideoEnabled")
            if (call != null) {
                if (mIsVideoEnabled) {
                    Log.d(TAG, "[VideoCallActivity] :: stopVideo()")
                    call.stopVideo()
                    mIsVideoEnabled = false
                    mImageViewVideoOff.isSelected = true
                } else {
                    Log.d(TAG, "[VideoCallActivity] :: startVideo()")
                    call.startVideo()
                    mIsVideoEnabled = true
                    mImageViewVideoOff.isSelected = false
                }
            }
        }
        mImageViewBluetooth.isEnabled = false
        mImageViewBluetooth.setOnClickListener { view: View? ->
            mImageViewBluetooth.isSelected = !mImageViewBluetooth.isSelected
            val call = mDirectCall
            if (call != null) {
                if (mImageViewBluetooth.isSelected) {
                    call.selectAudioDevice(
                        AudioDevice.BLUETOOTH,
                        object : CompletionHandler {
                            override fun onResult(e: SendBirdException?) {
                                if (e != null) {
                                    mImageViewBluetooth.isSelected = false
                                }
                            }
                        })
                } else {
                    call.selectAudioDevice(
                        AudioDevice.WIRED_HEADSET,
                        object : CompletionHandler {
                            override fun onResult(e: SendBirdException?) {
                                if (e != null) {
                                    call.selectAudioDevice(AudioDevice.SPEAKERPHONE, null)
                                }
                            }
                        })
                }
            }
        }
    }

    fun setLocalVideoSettings(call: DirectCall) {
        mIsVideoEnabled = call.isLocalVideoEnabled
        Log.d(
            TAG,
            "[VideoCallActivity] :: setLocalVideoSettings() => isLocalVideoEnabled(): $mIsVideoEnabled"
        )
        if (mIsVideoEnabled) {
//            bindCallService()
//            init()
//            initViews()
//            setViews()
//            setAudioDevice()
//            setCurrentState()
            call.stopVideo()
//            setState(STATE.STATE_RECONNECTED, call)
//            initViews()
//            setViews()
//            mDoLocalVideoStart = false
//            updateCallService()
            call.startVideo()
            call.setLocalVideoView(mVideoViewSmall)
            mImageViewVideoOff.isSelected = !mIsVideoEnabled
        }
    }

    override fun setAudioDevice(
        currentAudioDevice: AudioDevice?,
        availableAudioDevices: Set<AudioDevice>?
    ) {
        if (currentAudioDevice == AudioDevice.SPEAKERPHONE) {
            mImageViewBluetooth.isSelected = false
        } else if (currentAudioDevice == AudioDevice.BLUETOOTH) {
            mImageViewBluetooth.isSelected = true
        }
        if (availableAudioDevices?.contains(AudioDevice.BLUETOOTH) == true) {
            mImageViewBluetooth.isEnabled = true
        } else if (!mImageViewBluetooth.isSelected) {
            mImageViewBluetooth.isEnabled = false
        }
    }

    override fun startCall(amICallee: Boolean) {
        val callOptions = CallOptions()
        callOptions.setVideoEnabled(mIsVideoEnabled).setAudioEnabled(mIsAudioEnabled)
        if (amICallee) {
            callOptions.setLocalVideoView(mVideoViewSmall)
                .setRemoteVideoView(mVideoViewFullScreen)
        } else {
            callOptions.setLocalVideoView(mVideoViewFullScreen)
                .setRemoteVideoView(mVideoViewSmall)
        }
        if (amICallee) {
            Log.d(TAG, "[VideoCallActivity] :: accept()")
            val call = mDirectCall
            call?.accept(AcceptParams().setCallOptions(callOptions))
        } else {
            Log.d(TAG, "[VideoCallActivity] :: dial()")
            val calleeId = mCalleeIdToDial
            if (calleeId != null) {

                mDirectCall = SendBirdCall.dial(
                    DialParams(calleeId).setVideoCall(mIsVideoCall).setCallOptions(callOptions),
                    object : DialHandler {
                        override fun onResult(call: DirectCall?, e: SendBirdException?) {
                            if (e != null) {
                                Log.d(TAG, "[VideoCallActivity] :: dial() => e: " + e.message)
                                if (e.message != null) {
                                    ToastUtils.showToast(mContext, e.message)
                                }
                                finishWithEnding(e.message ?: "")
                                return
                            }
                            Log.d(TAG, "[VideoCallActivity] :: dial() => OK")
                            updateCallService()
                        }
                    })
                mDirectCall?.let { setListener(it) }
            }
        }
    }

    @SuppressLint("SourceLockedOrientationActivity")
    @TargetApi(18)
    override fun setState(state: STATE, call: DirectCall?): Boolean {
        if (!super.setState(state, call)) {
            return false
        }
        Log.d(TAG, "[VideoCallActivity] :: state=$state ")
        when (state) {
            STATE.STATE_ACCEPTING -> {
                mVideoViewFullScreen.visibility = View.GONE
                mViewConnectingVideoViewFullScreenFg.visibility = View.GONE
                mRelativeLayoutVideoViewSmall.visibility = View.GONE
                mImageViewCameraSwitch.visibility = View.GONE
            }
            STATE.STATE_OUTGOING -> {
                mVideoViewFullScreen.visibility = View.VISIBLE
                mViewConnectingVideoViewFullScreenFg.visibility = View.VISIBLE
                mRelativeLayoutVideoViewSmall.visibility = View.GONE
                mImageViewCameraSwitch.visibility = View.VISIBLE
                mImageViewVideoOff.visibility = View.VISIBLE
            }
            STATE.STATE_CONNECTED -> {
                mVideoViewFullScreen.visibility = View.VISIBLE
                mViewConnectingVideoViewFullScreenFg.visibility = View.GONE
                mRelativeLayoutVideoViewSmall.visibility = View.VISIBLE
                mImageViewCameraSwitch.visibility = View.VISIBLE
                mImageViewVideoOff.visibility = View.VISIBLE
                mLinearLayoutInfo.visibility = View.GONE
                if (call != null && call.myRole == DirectCallUserRole.CALLER) {
                    call.setLocalVideoView(mVideoViewSmall)
                    call.setRemoteVideoView(mVideoViewFullScreen)
                }
            }
            STATE.STATE_RECONNECTED -> {
                mVideoViewFullScreen.visibility = View.VISIBLE
                mViewConnectingVideoViewFullScreenFg.visibility = View.GONE
                mRelativeLayoutVideoViewSmall.visibility = View.VISIBLE
                mImageViewCameraSwitch.visibility = View.VISIBLE
                mImageViewVideoOff.visibility = View.VISIBLE
                mLinearLayoutInfo.visibility = View.GONE
                if (call != null && call.myRole == DirectCallUserRole.CALLER) {
                    call.setLocalVideoView(mVideoViewSmall)
                    call.setRemoteVideoView(mVideoViewFullScreen)
                }
            }
            STATE.STATE_ENDING, STATE.STATE_ENDED -> {
                mLinearLayoutInfo.visibility = View.VISIBLE
                mVideoViewFullScreen.visibility = View.GONE
                mViewConnectingVideoViewFullScreenFg.visibility = View.GONE
                mRelativeLayoutVideoViewSmall.visibility = View.GONE
                mImageViewCameraSwitch.visibility = View.GONE
            }
        }
        return true
    }

    override fun onStart() {
        super.onStart()
        Log.d(TAG, "[VideoCallActivity] :: onStart()")
        if (mDirectCall != null && mDoLocalVideoStart) {
            checkCameraAndAudioPermission()
            mDoLocalVideoStart = false
            updateCallService()
            mDirectCall?.startVideo()
//            checkPermissions()
        }
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "[VideoCallActivity] :: onStop()")
        if (mDirectCall != null && mDirectCall?.isLocalVideoEnabled == true) {
            mDirectCall?.stopVideo()
            mDoLocalVideoStart = true
            updateCallService()
        }
    }
}
1 Like