Search code examples
androidkotlinwebviewandroid-permissionsandroid-camera2

Webview can not open camera when return back and open webview again


I have project that load webview and open camera to scan QR code. But sometimes I return from page and enter again it shows gray play button in the page. When I open in emulator it works oftenly when return and get that from log when it works well the logcat has this line:

W/m.migrosmagazam: Long monitor contention with owner VideoCaptureCamera2_CameraThread (6680) at void android.hardware.camera2.impl.CameraDeviceImpl.close()(CameraDeviceImpl.java:1433) waiters=0 in void android.hardware.camera2.impl.CameraDeviceImpl$CameraDeviceCallbacks.onCaptureStarted(android.hardware.camera2.impl.CaptureResultExtras, long) for 237ms D/FA: Connected to remote service V/FA: Processing queued up service tasks: 1 D/EGL_emulation: app_time_stats: avg=24.30ms min=3.44ms max=390.79ms count=29 D/EGL_emulation: eglCreateContext: 0x723d53444e10: maj 2 min 0 rcv 2 D/EGL_emulation: app_time_stats: avg=467.91ms min=2.15ms max=1398.04ms count=3 D/EGL_emulation: app_time_stats: avg=62.40ms min=12.81ms max=794.05ms count=17 V/FA: Inactivity, disconnecting from the service D/EGL_emulation: app_time_stats: avg=912.88ms min=5.76ms max=6756.47ms count=8 E/WebView - Logger: Uncaught Cannnot transition to a new state, already under transition : 2 : Uncaught Cannnot transition to a new state, already under transition E/WebView - Logger: Uncaught Cannnot transition to a new state, already under transition : 2 : Uncaught Cannnot transition to a new state, already under transition D/EGL_emulation: eglCreateContext: 0x723d530d1550: maj 2 min 0 rcv 2 E/cr_VideoCapture: CameraDevice.StateCallback onOpened

screen

How can solve this problem?

override fun onCreateFinished() {
        binding.webView.settings.javaScriptEnabled = true
        binding.webView.settings.domStorageEnabled = true
        binding.webView.settings.mediaPlaybackRequiresUserGesture = false
        binding.webView.settings.allowFileAccessFromFileURLs = true
        binding.webView.settings.allowUniversalAccessFromFileURLs = true
        binding.webView.settings.allowContentAccess = false
        binding.webView.settings.useWideViewPort = true
        binding.webView.settings.loadWithOverviewMode = true
        binding.webView.settings.cacheMode = WebSettings.LOAD_NO_CACHE
        binding.webView.loadUrl("https://izlenebilirlik.migros.com.tr/urun_izle_ms.aspx")

        if (ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ErrorDialog(
                ErrorType.CUSTOM_MESSAGE,
                ::onClickWarningMessage,
                getString(R.string.you_must_allow_camera_permission_to_read_qr)
            ).show(
                childFragmentManager,
                ErrorDialog.TAG
            )
        } else {
            binding.webView.loadUrl("https://izlenebilirlik.migros.com.tr/urun_izle_ms.aspx")
        }

        binding.webView.webChromeClient = object : WebChromeClient() {
            override fun onPermissionRequest(request: android.webkit.PermissionRequest?) {
                if (request?.resources?.contains("android.permission.CAMERA") == true || request?.resources?.contains("android.webkit.resource.VIDEO_CAPTURE") == true) {
                    if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                        // Permission is not granted, so request it
                        ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.CAMERA), 100)
                    } else {
                        request.grant(request.resources)
                    }
                } else {
                    super.onPermissionRequest(request)
                }
            }

            override fun onConsoleMessage(consoleMessage: ConsoleMessage?): Boolean {
                Log.e ("WebView - Logger", consoleMessage?.message () + " : " + consoleMessage?.lineNumber () + " : " + consoleMessage?.message ());
                return true
            }
        }
    }

    private fun onClickWarningMessage() {
        ActivityCompat.requestPermissions(requireActivity(), arrayOf(android.Manifest.permission.CAMERA), 100)
    }

Solution

  • I solved problem. It happens because camera open but not closed in some devices. So I closed camera in onDestroyView.

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onDestroyView() {
        binding.webView.evaluateJavascript(
            """
    var videoElement = document.querySelector('video');
    if (videoElement) {
        videoElement.srcObject.getTracks().forEach(track => track.stop());
    }
    """,
            null
        )
        binding.webView.clearCache(true)
        binding.webView.clearHistory()
        binding.webView.onPause()
        binding.webView.removeAllViews()
        binding.webView.destroyDrawingCache()
        binding.webView.settings.cacheMode = WebSettings.LOAD_NO_CACHE
        super.onStop()
        super.onDestroyView()
    }