Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Choose camera in file upload in cordova application on android without using cordova camera

So i made a cordova app, i added android platform and made a simple html with an imput field

<input type="file" capture="camera" accept="image/*" id="takePictureField"> 

I have added

<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" /> 

to the manifest file.

but when i press the button I cannot choose to take a new picture with the camera. are there any permission i miss, or anything else ??

I cannot use the cordova take picture functions, it has to be done in pure html.

like image 728
pjensen68321 Avatar asked Oct 15 '14 11:10

pjensen68321


People also ask

Which command is used to install camera plugin?

Installation. To add a camera plugin in your Cordova app, type the below command: cordova plugin add cordova-plugin-camera.

What is camera plugin in Cordova?

This plugin defines a global navigator. camera object, which provides an API for taking pictures and for choosing images from the system's image library. Although the object is attached to the global scoped navigator , it is not available until after the deviceready event.

What are Cordova plugins?

What is a Cordova plugin? A plugin is a bit of add-on code that provides JavaScript interface to native components. They allow your app to use native device capabilities beyond what is available to pure web apps.


2 Answers

After a bit of Googling, this is what I could conclude:

Media capture in mobile browsers still seems to have some issues. Check out this link. The excerpt says:

Actually, it seems that current implementations don’t rely on the capture attribute at all, but only on the type and accept attributes: the browser displays a dialog box in which the user can choose where the file has to be taken, and the capture attribute is not taken into consideration. For example, iOS Safari relies on the accept attribute (not capture) for images and videos (not audio). Even if you don’t use the accept attribute, the browser will let you choose between “Take Photo or Video” and “Choose Existing”

So looks like capture attribute does not make any impact.

Also, suggest you look at this SO post for more info on making this work. Hope it helps. Cheers.

UPDATE: After downvoting, I dig further deep regarding the issue. Most of the searches resulted in no success as the optimum solution for this issue is to use Cordova camera plugin. Finally stumbled on this SO post which is exactly duplicate of this question. The user was able to resolve the issue (using crosswalk web view, though). The answer in that post is mentioned here already by @Fabio. But instead of adding the plugin just for including the permissions, you can make use of cordova-custom-plugin to add the required permissions.

Also as per @jcesarmobile's comment (who is a Cordova expert) in the post without crosswalk web view plugin, input type works fine only on iOS and not on Android. So using camera plugin is the only way to make it work without using crosswalk plugin.Hopefully, it helps.

UPDATE 2: After the updated question, I dug bit more deep for the resolution of this issue. But now I can assure that this issue is still not resolved for Android Webview. Looks like it is not a Cordova issue but issue with Chromium web view.

For detailed info, request you to please look at these issues in Apache Cordova Issue Tracker:

  • File input element not opening
  • File input element should support accept/source attributes

Both these issues are unresolved till date. So I m sure that for now, you cannot make it work on Android unless you use Cordova camera plugin. Hope you agree with me and accept the resolution. Cheers

like image 102
Gandhi Avatar answered Sep 17 '22 19:09

Gandhi


My project was using cordova-plugin-inappbrowser.

I solve it merging solution in webview open camera from input field without filechooser with methods onActivityResult and onShowFileChooser from class InAppBrowser in plugin source.

See the changes made in InAppBrowser class from plugin version 3.0.0

1 - include imports:

import android.app.Activity; import android.Manifest; 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 - declare variable:

    private String mCM;  

3 - Replace onShowFileChooser code:

                     // For Android 5.0+                     public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)                     {                         if(Build.VERSION.SDK_INT >=23 && (cordova.getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || cordova.getActivity().checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {                             cordova.getActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, 1);                         }                          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 - create method

     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 - Replace 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;         }     }  
like image 20
Gilberto Alexandre Avatar answered Sep 20 '22 19:09

Gilberto Alexandre