だから私はcordovaアプリを作りました、Androidプラットフォームを追加し、入力フィールドを持つ単純なhtmlを作りました
<input type="file" capture="camera" accept="image/*" id="takePictureField">
私が追加しました
<uses-permission Android:name="Android.permission.CAMERA" />
<uses-feature Android:name="Android.hardware.camera" Android:required="false" />
<uses-feature Android:name="Android.hardware.camera.autofocus" />
<feature name="http://api.phonegap.com/1.0/camera" />
マニフェストファイルに。
ボタンを押すと、カメラで新しい写真を撮ることができません。私が逃した許可、または何か他のものはありますか?
コルドバの写真撮影機能は使用できません。純粋なhtmlで実行する必要があります。
少しググリングした後、これは私が結論付けることができるものです:
モバイルブラウザーでのメディアキャプチャには、まだいくつかの問題があるようです。これをチェックしてください リンク 。抜粋は言う:
実際、現在の実装は
capture
属性にまったく依存しておらず、type
およびaccept
属性にのみ依存しているようです。ブラウザにダイアログボックスが表示されます。ユーザーは、ファイルを取得する必要がある場所を選択できます。キャプチャ属性は考慮されません。たとえば、iOS Safariは、画像とビデオ(オーディオではない)のaccept
属性(キャプチャではない)に依存しています。accept
属性を使用しない場合でも、ブラウザで「写真を撮るかビデオを撮る」か「既存のものを選択する」のどちらかを選択できます
したがって、キャプチャ属性は影響を与えないように見えます。
また、この作業の詳細については、 SO post を参照することをお勧めします。それが役に立てば幸い。乾杯。
更新:反対票を投じた後、問題についてさらに深く掘り下げます。この問題の最適な解決策はCordovaカメラプラグインを使用することであるため、ほとんどの検索は成功しませんでした。最後にこれにつまずいた SO post これはこの質問とまったく同じです。ユーザーは問題を解決できました(ただし、横断歩道のWebビューを使用)。その投稿の答えは、@ Fabioによってすでにここで言及されています。ただし、権限を含めるためだけにプラグインを追加する代わりに、 cordova-custom-plugin を使用して必要な権限を追加できます。
また、@ jcesarmobileのコメント(Cordovaエキスパート)によるクロスウォークWebビュープラグインなしの投稿によると、入力タイプはiOSではのみ機能し、Androidでは機能しません。したがって、カメラプラグインを使用することが、横断歩道プラグインを使用せずに機能させる唯一の方法です。
更新2:更新された質問の後、私はこの問題の解決のためにもう少し深く掘り下げました。しかし、今はこの問題がAndroid Webviewで解決されないことを確認できます。Cordovaの問題ではなく、Chromium Webビューの問題のようです。
詳細については、Apache Cordova Issue Trackerで以下の問題を確認するように要求してください。
これらの問題はどちらも現在まで解決されていません。だから今のところ、Androidで動作させることができないと思います。Cordovaカメラプラグインを使用しない限り。私に同意して解決策を受け入れてください。)乾杯
プラグインのソースコードを変更したくない場合の回避策を次に示します。写真を撮るための別のコントロールを作成します。コントロールのクリックイベントを次のハンドラーに設定します。
(event) => {
event.stopPropagation();
Camera.sourceType = Camera.PictureSourceType.CAMERA;
const onCameraSuccess = (imgURL) => {
window.resolveLocalFileSystemURL(imgURL, (entry) => {
const onFileSuccess = (file) => this._onSelectMultipleFiles(event, file);
const onFileFail = (error) => console.log(error);
entry.file(onFileSuccess, onFileFail);
});
console.log("picture retrieved successfully");
};
const onCameraFail = () => {
console.log("picture retrieval failed");
};
navigator.camera.getPicture(onCameraSuccess, onCameraFail, {
quality: 100,
destinationType: Camera.DestinationType.FILE_URI,
});
}
これは、コントロールがクリックされたときにcordova-plugin-cameraを使用してカメラアプリを起動し、cordova-plugin-fileからresolveLocalFileSystemURLを呼び出して、カメラから返された画像URLを、_onSelectMultipleFilesメソッドで処理されるFileオブジェクトに変換します。 cordova docsの例を参照
注この実装は私のプロジェクトに固有であるため、onSuccessで渡されたイメージURLの使用方法によってはresolveLocalFileSystemURLを呼び出す必要がない場合がありますcamera.getPictureのコールバック。
明らかに、これの欠点は、2つのコントロールを使用する必要があることです。1つはファイルから画像を取得するため、もう1つはカメラから画像を取得するためです。
免責事項:この回答に関する最近のコメントでは、機能しなくなったと報告されています。この質問と回答は古いコードバとプラグインのバージョンに関連しているため、現在の状況には適用されない場合があります。
古い質問ですが、私はこの問題に直面しました。あなたが望むものを達成する最も簡単な方法は、あなたがそれらを使用する必要がない場合でも、あなたのアプリにこれらのコルドバプラグインを含めることです
cordova-plugin-camera
cordova-plugin-media-capture
cordova-plugin-device
cordova-plugin-file
cordova-plugin-media
これらがロードされていると、私はこの動作を見つけました
クリック
<input type="file" />
カメラ、ビデオカメラ、マイク、ドキュメントから選択するように求めます
クリック
<input type="file" accept="image/*" />
カメラまたはドキュメントから選択するように求めます
クリック
<input type="file" accept="image/*" capture="capture" />
すぐにカメラを起動します。
私のプロジェクトは、cordova-plugin-inappbrowserを使用していました。
プラグインソースのクラスInAppBrowserのメソッドonActivityResultとonShowFileChooserを使用して、マージソリューション filechooserのない入力フィールドからwebview open camera で解決します。
プラグインバージョン3.0.0からInAppBrowserクラスに加えられた変更を確認する
1-インポートを含める:
import Android.app.Activity;
import Android.os.Environment;
import Android.provider.MediaStore;
import Android.util.Log;
import Java.io.File;
import Java.io.IOException;
import Java.text.SimpleDateFormat;
import Java.util.Date;
2-バリアベルを宣言します。
private String mCM;
3-onShowFileChooserコードを置き換える
// For Android 5.0+
public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
{
LOG.d(LOG_TAG, "File Chooser 5.0+");
// If callback exists, finish it.
if(mUploadCallbackLollipop != null) {
mUploadCallbackLollipop.onReceiveValue(null);
}
mUploadCallbackLollipop = filePathCallback;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(cordova.getActivity().getPackageManager()) != null) {
File photoFile = null;
try{
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCM);
}catch(IOException ex){
Log.e(LOG_TAG, "Image file creation failed", ex);
}
if(photoFile != null){
mCM = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
}else{
takePictureIntent = null;
}
}
// Create File Chooser Intent
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("*/*");
Intent[] intentArray;
if(takePictureIntent != null){
intentArray = new Intent[]{takePictureIntent};
}else{
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Selecione a imagem");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
// Run cordova startActivityForResult
cordova.startActivityForResult(InAppBrowser.this, chooserIntent, FILECHOOSER_REQUESTCODE);
return true;
}
4-メソッドの作成
private File createImageFile() throws IOException{
@SuppressLint("SimpleDateFormat") String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "img_"+timeStamp+"_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(imageFileName,".jpg",storageDir);
}
5-onActivityResultを置き換える
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
// For Android >= 5.0
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
LOG.d(LOG_TAG, "onActivityResult (For Android >= 5.0)");
Uri[] results = null;
//Check if response is positive
if(resultCode== Activity.RESULT_OK){
if(requestCode == FILECHOOSER_REQUESTCODE){
if(null == mUploadCallbackLollipop){
return;
}
if(intent == null || intent.getData() == null){
//Capture Photo if no image available
if(mCM != null){
results = new Uri[]{Uri.parse(mCM)};
}
}else{
String dataString = intent.getDataString();
if(dataString != null){
results = new Uri[]{Uri.parse(dataString)};
}
}
}
}
mUploadCallbackLollipop .onReceiveValue(results);
mUploadCallbackLollipop = null;
}
// For Android < 5.0
else {
LOG.d(LOG_TAG, "onActivityResult (For Android < 5.0)");
// If RequestCode or Callback is Invalid
if(requestCode != FILECHOOSER_REQUESTCODE || mUploadCallback == null) {
super.onActivityResult(requestCode, resultCode, intent);
return;
}
if (null == mUploadCallback) return;
Uri result = intent == null || resultCode != cordova.getActivity().RESULT_OK ? null : intent.getData();
mUploadCallback.onReceiveValue(result);
mUploadCallback = null;
}
}
Gilberto answer からインスピレーションを得て、これが私の適応です:
新しい方法は4つあります。1つは許可を取得する方法、もう1つは許可を確認する方法、写真を撮る前に画像ファイルを作成する方法、カメラを開く方法です。
ここにそれらの方法があります
/**
* Called by the system when the user grants permissions
*
* @param requestCode
* @param permissions
* @param grantResults
*/
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults)
throws JSONException {
for (int r : grantResults) {
if (r == PackageManager.PERMISSION_DENIED) {
Toast.makeText(cordova.getActivity(), "Autorisation pour ouvrir la caméra refusé", Toast.LENGTH_LONG)
.show();
mUploadCallbackLollipop.onReceiveValue(null);
mUploadCallbackLollipop = null;
return;
}
}
if (requestCode == PERM_REQUEST_CAMERA_FOR_FILE) {
startCameraActivityForAndroidFivePlus();
}
}
private File createImageFile() throws IOException {
@SuppressLint("SimpleDateFormat")
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "img_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(imageFileName, ".jpg", storageDir);
}
private void startCameraActivityForAndroidFivePlus() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile = null;
try {
photoFile = createImageFile();
takePictureIntent.putExtra("PhotoPath", mCapturedPhoto);
} catch (IOException ex) {
LOG.e(LOG_TAG, "Image file creation failed", ex);
}
if (photoFile != null) {
mCapturedPhoto = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
// Fix FileUriExposedException exposed beyond app through ClipData.Item.getUri()
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
// Run cordova startActivityForResult
cordova.startActivityForResult(InAppBrowser.this, takePictureIntent, FILECHOOSER_REQUESTCODE_Lollipop);
}
private boolean checkPermissionForCamera() {
if (Build.VERSION.SDK_INT >= 23) {
List<String> permToAsk = new ArrayList<String>();
if (cordova.getActivity().checkSelfPermission(
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
permToAsk.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (cordova.getActivity()
.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
permToAsk.add(Manifest.permission.CAMERA);
}
if (permToAsk.size() > 0) {
cordova.requestPermissions(InAppBrowser.this, PERM_REQUEST_CAMERA_FOR_FILE,
permToAsk.toArray(new String[permToAsk.size()]));
return true;
}
}
return false;
}
InAppChromeClient実装が次のように更新されました。
inAppWebView.setWebChromeClient(new InAppChromeClient(thatWebView) {
// For Android 5.0+
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
LOG.d(LOG_TAG, "File Chooser 5.0+");
// If callback exists, finish it.
if (mUploadCallbackLollipop != null) {
mUploadCallbackLollipop.onReceiveValue(null);
}
mUploadCallbackLollipop = filePathCallback;
// #Update to always open camera app
if (checkPermissionForCamera()) {
return true;
}
startCameraActivityForAndroidFivePlus();
return true;
}
});
そしてここにそれらの定数があります:
private String mCapturedPhoto;
private final static int PERM_REQUEST_CAMERA_FOR_FILE = 3;