html5 getusermedia api を使用して、Android webview アプリで webcamera を初期化しようとしています。コードはブラウザーで完全に機能しますが、ページを Android アプリで webview としてデプロイすると、「Webcam にアクセスできませんでした: NotreadableError: ビデオ ソースを開始できませんでした」というエラーがスローされます。
他のスレッドやドキュメントに基づいて、どこが間違っているのかわかりません。マニフェスト ファイルへのアクセス許可の追加、ライブラリのインポート、mainactivity.java ファイルへの requestpermission 関数の追加など、すべてを実行しました。
ここに MainActivity があります。使用しているJava / AndroidマニフェストファイルとPHPファイル
MainActivity.Java
package com.example.mbracegate;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Build;
import android.graphics.Bitmap;
import java.util.*;
import android.view.View;
import android.webkit.PermissionRequest;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.content.pm.PackageManager;
public class MainActivity extends Activity {
private ProgressBar progressBar;
private WebView webView;
private class WebChromeClientDemo extends WebChromeClient {
private WebChromeClientDemo() {
}
public void onProgressChanged(WebView view, int progress) {
MainActivity.this.progressBar.setProgress(progress);
}
}
private class WebViewClientDemo extends WebViewClient {
private WebViewClientDemo() {
}
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
MainActivity.this.progressBar.setVisibility(8);
MainActivity.this.progressBar.setProgress(100);
}
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
MainActivity.this.progressBar.setVisibility(0);
MainActivity.this.progressBar.setProgress(0);
}
}
@SuppressLint({"SetJavaScriptEnabled"})
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.progressBar = (ProgressBar) findViewById(R.id.progressBar);
this.progressBar.setMax(100);
this.webView = (WebView) findViewById(R.id.simpleWebView);
this.webView.setWebViewClient(new WebViewClientDemo());
this.webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
this.webView.setWebChromeClient(new WebChromeClient() {
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public void onPermissionRequest(final PermissionRequest request) {
request.grant(request.getResources());
}
});
WebSettings settings = this.webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setDatabaseEnabled(true);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasCameraPermission = checkSelfPermission(Manifest.permission.CAMERA);
List<String> permissions = new ArrayList<String>();
if (hasCameraPermission != PackageManager.PERMISSION_GRANTED) {
permissions.add(Manifest.permission.CAMERA);
}
if (!permissions.isEmpty()) {
requestPermissions(permissions.toArray(new String[permissions.size()]), 111);
}
}
CookieManager.getInstance();
this.webView.loadUrl("https://mbracecloud.com/index_camera.php");
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == 4 && this.webView.canGoBack()) {
this.webView.goBack();
return true;
}
finish();
return super.onKeyDown(keyCode, event);
}
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
}
Android マニフェスト
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mbracegate" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<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-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.VIDEO_CAPTURE" />
<uses-permission android:name="android.permission.AUDIO_CAPTURE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<application
android:hardwareAccelerated="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<activity
android:name="com.example.mbracegate.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
PHPファイル
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="css/style.css" rel="stylesheet">
<script type="text/javascript">
function startup() {
video = document.getElementById('video');
canvas = document.getElementById('canvas');
photo = document.getElementById('photo');
startbutton = document.getElementById('startbutton');
// access video stream from webcam
navigator.mediaDevices.getUserMedia({
video: true,
audio: false
})
// on success, stream it in video tag
.then(function(stream) {
video.srcObject = stream;
video.play();
})
.catch(function(err) {
console.log("An error occurred: " + err);
});
video.addEventListener('canplay', function(ev) {
if (!streaming) {
height = video.videoHeight / (video.videoWidth / width);
if (isNaN(height)) {
height = width / (4 / 3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
}, false);
startbutton.addEventListener('click', function(ev) {
takepicture();
ev.preventDefault();
}, false);
clearphoto();
}
</script>
<script type="text/javascript">
// Below code to capture image from Video tag (Webcam streaming)
$("#btnCapture").click(function () {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// Capture the image into canvas from Webcam streaming Video element
context.drawImage(video, 0, 0);
});
// Upload image to server - ajax call - with the help of base64 data as a parameter
$("#btnSave").click(function () {
// Below new canvas to generate flip/mirron image from existing canvas
var destinationCanvas = document.createElement("canvas");
var destCtx = destinationCanvas.getContext('2d');
destinationCanvas.height = 500;
destinationCanvas.width = 500;
destCtx.translate(video.videoWidth, 0);
destCtx.scale(-1, 1);
destCtx.drawImage(document.getElementById("canvas"), 0, 0);
// Get base64 data to send to server for upload
var imagebase64data = destinationCanvas.toDataURL("image/png");
imagebase64data = imagebase64data.replace('data:image/png;base64,', '');
$.ajax({
type: 'POST',
url: '/Home/UploadWebCamImage',
data: '{ "imageData" : "' + imagebase64data + '" }',
contentType: 'application/json; charset=utf-8',
dataType: 'text',
success: function (out) {
alert('Image uploaded successfully..');
}
});
});
</script>
</head>
<body >
<div class="jumbotron" style="margin-top:20px;padding:20px;">
<p><span id="errorMsg"></span></p>
<div class="row">
<div class="col-lg-6">
<!-- Here we streaming video from webcam -->
<h4>
Video coming from Webcam <button class="btn btn-primary" id="btnCapture">Capture to Canvas >></button>
</h4>
<video id="video" playsinline autoplay></video>
</div>
<div class="col-lg-6">
<h4>
Captured image from Webcam <input type="button" class="btn btn-primary" id="btnSave" name="btnSave" value="Save the canvas(image) to server" />
</h4>
<!-- Webcam video snapshot -->
<canvas style="border:solid 1px #ddd;background-color:white;" id="canvas" width="475" height="475"></canvas>
</div>
</div>
</div>
</body>
</html>
この問題を解決する方法についてのアイデアはありますか?