App基于webRTC vs websocket。 Android studio 2.3.2最新版本。
我已经使用:
https协议,自动播放,android版本7.0(min> android 5.0)。 App适用于所有支持的浏览器,只有android webview生成错误 。
这是第一行错误登录 logcat (android studio last ver):
E / chromium:[错误:audio_manager_android.cc(264)]无法选择音频设备! E / cr_VideoCapture:allocate:manager.openCamera: SecurityException:validateConnectLocked:1112:Caller " com.testwebrtc.nikola.myapplication"不能 打开相机" 1"没有相机许可 在 android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:628) 在 android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:347) 在 android.hardware.camera2.CameraManager.openCamera(CameraManager.java:450) 在 org.chromium.media.VideoCaptureCamera2.startCapture(VideoCaptureCamera2.java:661)
错误的其他变体:
[ERROR:web_contents_delegate.cc(199)] WebContentsDelegate :: CheckMediaAccessPermission:不支持。
这是chrome / webview的错误日志 (来自errorCallBack - getUserMedia):
An error occcurred [CODE NotAllowedError]
other error variant :
trackstarterror
Android代码看起来像:
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 - modula:
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" />
...
答案 0 :(得分:4)
WebView
请求来自应用程序的权限,但未向用户授予应用程序的这些权限。
您应该向用户调用App的权限请求,如this document中所述。
现在我发现WebRTC所需的权限是:
onPermissionRequest: android.webkit.resource.VIDEO_CAPTURE
onPermissionRequest: android.webkit.resource.AUDIO_CAPTURE
答案 1 :(得分:1)
您需要这些权限才能访问相机和麦克风
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="true"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
// don't miss this one
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
接下来您需要向您的 webview 授予权限,查看此 link 以了解更多详细信息:
webView.setWebChromeClient(new WebChromeClient(){
@Override
public void onPermissionRequest(PermissionRequest request) {
runOnUiThread(() -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String[] PERMISSIONS = {
PermissionRequest.RESOURCE_AUDIO_CAPTURE,
PermissionRequest.RESOURCE_VIDEO_CAPTURE
};
request.grant(PERMISSIONS);
}
});
}
});
如果音频播放不起作用,请使用:
webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
答案 2 :(得分:0)
您的应用在使用相机之前需要获得请求权限
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
答案 3 :(得分:0)
以这种方式授予权限:
yourWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onPermissionRequest(PermissionRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
request.grant(request.getResources());
}
}
});