Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't access camera from Android webView (chrome frame) in context of webRTC

App is based on webRTC vs websocket . Android studio 2.3.2 last version.

I already use:

https protocol , autoplay , android version 7.0 (min > android 5.0) . App works on all supported browsers only android webview generate error.

This is first lines of errors log in logcat (android studio last ver):

E/chromium: [ERROR:audio_manager_android.cc(264)] Unable to select audio device! E/cr_VideoCapture: allocate: manager.openCamera: SecurityException: validateConnectLocked:1112: Caller "com.testwebrtc.nikola.myapplication" cannot open camera "1" without camera permission at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:628) at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:347) at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:450) at org.chromium.media.VideoCaptureCamera2.startCapture(VideoCaptureCamera2.java:661)

Other variant for error:

[ERROR:web_contents_delegate.cc(199)] WebContentsDelegate::CheckMediaAccessPermission: Not supported.

This is error log from chrome/webview (from errorCallBack - getUserMedia ):

      An error occcurred [CODE NotAllowedError]

      other error variant: 

      trackstarterror

Android Code looks like:

package com.project.TEST.xxx;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.webkit.PermissionRequest;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.container, PlaceholderFragment.newInstance(1) )
                .commit();

    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {
        /**
         * The fragment argument representing the section number for this
         * fragment.
         */
        private static final String ARG_SECTION_NUMBER = "section_number";

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        public static PlaceholderFragment newInstance(int sectionNumber) {
            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        private WebView mWebRTCWebView;

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            mWebRTCWebView = (WebView) rootView.findViewById(R.id.fragment_main_webview);

            setUpWebViewDefaults(mWebRTCWebView);

            mWebRTCWebView.loadUrl("https://example.com/");

            mWebRTCWebView.setWebChromeClient(new WebChromeClient() {

                @Override
                public void onPermissionRequest(final PermissionRequest request) {
                    Log.d(TAG, "onPermissionRequest");
                    getActivity().runOnUiThread(new Runnable() {
                        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
                        @Override
                        public void run() {

                            request.grant(request.getResources());

                        }
                    });
                }

            });

            return rootView;
        }

        @Override
        public void onStop() {
            super.onStop();

            /**
             * When the application falls into the background we want to stop the media stream
             * such that the camera is free to use by other apps.
             */
            mWebRTCWebView.evaluateJavascript("if(window.localStream){window.localStream.stop();}", null);
        }

        /*
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            ((MainActivity) activity).onSectionAttached(
                    getArguments().getInt(ARG_SECTION_NUMBER));
        }
*/

        @Override
        public void onAttach(Context context) {
            super.onAttach(context);

            Activity a;

            if (context instanceof Activity){
                a=(Activity) context;

            }

        }

        /**
         * Convenience method to set some generic defaults for a
         * given WebView
         *
         * @param webView
         */
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        private void setUpWebViewDefaults(WebView webView) {
            WebSettings settings = webView.getSettings();

            // Enable Javascript
            settings.setJavaScriptEnabled(true);

            // Use WideViewport and Zoom out if there is no viewport defined
            settings.setUseWideViewPort(true);
            settings.setLoadWithOverviewMode(true);

            // Enable pinch to zoom without the zoom buttons
            settings.setBuiltInZoomControls(true);

            // Allow use of Local Storage
            settings.setDomStorageEnabled(true);

            if(Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB) {
                // Hide the zoom controls for HONEYCOMB+
                settings.setDisplayZoomControls(false);
            }

            // Enable remote debugging via chrome://inspect
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                WebView.setWebContentsDebuggingEnabled(true);
            }

            webView.setWebViewClient(new WebViewClient());

            // AppRTC requires third party cookies to work
            CookieManager cookieManager = CookieManager.getInstance();
            cookieManager.setAcceptThirdPartyCookies(mWebRTCWebView, true);
        }
    }


}

Build.gradle-project :

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

gradle - module:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.project.test.xxx"
        minSdkVersion 21
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-fexceptions"
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
}

Android Manifest.xml :

....
  <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />
    <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="true" />
    <uses-feature android:name="android.hardware.camera.front" android:required="true" />
    <uses-feature android:name="android.hardware.camera" android:required="true" />
    <uses-feature android:name="android.hardware.camera.level.full" android:required="true" />
    <uses-feature android:name="android.hardware.camera.capability.raw" android:required="true" />
    <uses-feature android:name="android.hardware.camera.any" android:required="true" />
    <uses-feature android:name="android.hardware.microphone" android:required="true" />
    <uses-feature android:name="android.hardware.camera2" android:required="true" />

...
like image 451
Nikola Lukic Avatar asked May 25 '17 12:05

Nikola Lukic


People also ask

Does Android WebView support WebRTC?

Using WebRTC as a WebView in your app. WebView lets you get a browser-like interface right within your mobile application. The WebView allows users to display web content directly within an application.

Does Chrome use Android WebView?

No, Chrome for Android is separate from WebView. They're both based on the same code, including a common JavaScript engine and rendering engine.

How do you access the camera from WebView flutter?

In order to be able to use camera, for example, for taking images through <input type="file" accept="image/*" capture> HTML tag, you need to ask camera permission. If you need to capture video and audio, you need to ask also microphone permission.

Why is my WebView not working?

You might often face issues in updating the chrome and Android System Webview. To fix this problem, you can reboot your device, check your internet connection, stop auto-updating all apps, clear Google Playstore cache, and storage, leave the beta testing program, and manually update Android WebView app from Playstore.


2 Answers

its problems for reload the webview , after too much research , found this code and create this below code :-

 mwebView.setWebChromeClient(new WebChromeClient() {
    @Override
    public void onPermissionRequest(final PermissionRequest request) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            myRequest = request;
            for (String permission : request.getResources()) {
                if (permission.equals("android.webkit.resource.AUDIO_CAPTURE")) {
                    demandForPermission(request.getOrigin().toString(), Manifest.permission.RECORD_AUDIO, MY_PERMISSIONS_REQUEST_RECORD_AUDIO);
                } else {
                    myRequest.grant(request.getResources());
                }
            }
        }
    }

    @Override
    public void onPermissionRequestCanceled(PermissionRequest request) {
        super.onPermissionRequestCanceled(request);
    }

more info in this page Android Webview

like image 127
Simranjit Singh Avatar answered Oct 12 '22 01:10

Simranjit Singh


Grant permissions in this way:

yourWebView.setWebChromeClient(new WebChromeClient() {
                @Override
                public void onPermissionRequest(PermissionRequest request) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        request.grant(request.getResources());
                    }
                }
            });
like image 22
Amos Avatar answered Oct 12 '22 01:10

Amos