Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload an Image from camera or gallery in WebView

WebView in this app opens a page with upload button.

Page in webview with upload button

Below is the code block that allows to open a dialog box to upload image from gallery or camera.

Within my Activity I have:

 private WebView wv;    //make HTML upload button work in Webview     private ValueCallback<Uri> mUploadMessage;    private final static int FILECHOOSER_RESULTCODE=1;   @Override    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {     if(requestCode==FILECHOOSER_RESULTCODE)     {      if (null == mUploadMessage) return;               Uri result = intent == null || resultCode != RESULT_OK ? null                       : intent.getData();               mUploadMessage.onReceiveValue(result);               mUploadMessage = null;           }    }   

Within onCreate I have the following:

    wv.setWebChromeClient(new WebChromeClient()  {         private Uri imageUri;             public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType )  {                    File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp");             // Create the storage directory if it does not exist             if (! imageStorageDir.exists()){                 imageStorageDir.mkdirs();                               }             File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");               imageUri = Uri.fromFile(file);               final List<Intent> cameraIntents = new ArrayList<Intent>();             final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);             final PackageManager packageManager = getPackageManager();             final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);             for(ResolveInfo res : listCam) {                 final String packageName = res.activityInfo.packageName;                 final Intent i = new Intent(captureIntent);                 i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));                 i.setPackage(packageName);                 i.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);                 cameraIntents.add(i);              }               mUploadMessage = uploadMsg;              Intent i = new Intent(Intent.ACTION_GET_CONTENT);               i.addCategory(Intent.CATEGORY_OPENABLE);               i.setType("image/*");              Intent chooserIntent = Intent.createChooser(i,"Image Chooser");             chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));             MainActivity.this.startActivityForResult(chooserIntent,  FILECHOOSER_RESULTCODE);          } 

I am able to see option for camera, image gallery and file explorer on clicking Upload button. Camera, gallery and file explorer upload option

File explorer and Gallery is working as expected. The problem is that, when I take a picture using camera, it is not uploaded in the "choose file" option which shows status "No file chosen".

ON SELECTING CAMERA:

camera

ON TAKING SNAPSHOT USING CAMERA: back and check options appear.

snapshot using camera

ON CHOOSING CHECK MARK:

FILE IS NOT UPLOADED :( IN "CHOOSE FILE" OPTION

enter image description here

WHAT IS EXPECTED:

image uploaded

I checked that I have the proper writing permission and hence a directory named "MyApp" is generated and the picture is stored within it (if taken by invoking camera after clicking upload button on webpage).

How to programatically tell the application to choose picture taken from camera (that was stored in MyApp directory) after hitting check mark?

like image 646
Chirag Avatar asked Mar 31 '13 02:03

Chirag


People also ask

How do I send a post request in WebView?

webView. setWebViewClient(new WebViewClient(){ public void onPageStarted(WebView view, String url, Bitmap favicon) { super. onPageStarted(view, url, favicon); } public boolean shouldOverrideUrlLoading(WebView view, String url) { webView. postUrl(Base_Url, postData.

Which method is used to load HTML content in WebView?

The loadUrl() and loadData() methods of Android WebView class are used to load and display web page.


1 Answers

After struggling a lot I found a code that works for taking files from galley and camera from 5.0+ devices

    private ValueCallback<Uri> mUploadMessage; private Uri mCapturedImageURI = null; private ValueCallback<Uri[]> mFilePathCallback; private String mCameraPhotoPath; private static final int INPUT_FILE_REQUEST_CODE = 1; private static final int FILECHOOSER_RESULTCODE = 1;    private File createImageFile() throws IOException {     // Create an image file name     String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());     String imageFileName = "JPEG_" + timeStamp + "_";     File storageDir = Environment.getExternalStoragePublicDirectory(             Environment.DIRECTORY_PICTURES);     File imageFile = File.createTempFile(             imageFileName,  /* prefix */             ".jpg",         /* suffix */             storageDir      /* directory */     );     return imageFile; } 

this is initialization and setting webview

     mWebView= (WebView) findViewById(R.id.webview);         mWebView.getSettings().setJavaScriptEnabled(true);         mWebView.getSettings().setPluginState(WebSettings.PluginState.OFF);         mWebView.getSettings().setLoadWithOverviewMode(true);         mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);         mWebView.getSettings().setUseWideViewPort(true);         mWebView.getSettings().setUserAgentString("Android Mozilla/5.0 AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");         mWebView.getSettings().setAllowFileAccess(true);         mWebView.getSettings().setAllowFileAccess(true);         mWebView.getSettings().setAllowContentAccess(true);         mWebView.getSettings().supportZoom();         mWebView.loadUrl(Common.adPostUrl);          mWebView.setWebViewClient(new WebViewClient() {             public boolean shouldOverrideUrlLoading(WebView view, String url) {                 // do your handling codes here, which url is the requested url                 // probably you need to open that url rather than redirect:                 if ( url.contains(".pdf")){                     Intent intent = new Intent(Intent.ACTION_VIEW);                     intent.setDataAndType(Uri.parse(url), "application/pdf");                     try{                         view.getContext().startActivity(intent);                     } catch (ActivityNotFoundException e) {                         //user does not have a pdf viewer installed                     }                 } else {                     mWebView.loadUrl(url);                 }                 return false; // then it is not handled by default action             }               @Override             public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {  Log.e("error",description);             }               @Override             public void onPageStarted(WebView view, String url, Bitmap favicon) {        //show progressbar here                  super.onPageStarted(view, url, favicon);             }              @Override             public void onPageFinished(WebView view, String url) {           //hide progressbar here              }          });         mWebView.setWebChromeClient(new ChromeClient()); 

and here is my ChomeClient() method

public class ChromeClient extends WebChromeClient {      // For Android 5.0     public boolean onShowFileChooser(WebView view, ValueCallback<Uri[]> filePath, WebChromeClient.FileChooserParams fileChooserParams) {         // Double check that we don't have any existing callbacks         if (mFilePathCallback != null) {             mFilePathCallback.onReceiveValue(null);         }         mFilePathCallback = filePath;          Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);         if (takePictureIntent.resolveActivity(getPackageManager()) != null) {             // Create the File where the photo should go             File photoFile = null;             try {                 photoFile = createImageFile();                 takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);             } catch (IOException ex) {                 // Error occurred while creating the File                 Log.e(Common.TAG, "Unable to create Image File", ex);             }              // Continue only if the File was successfully created             if (photoFile != null) {                 mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();                 takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,                         Uri.fromFile(photoFile));             } else {                 takePictureIntent = null;             }         }          Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);         contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);         contentSelectionIntent.setType("image/*");          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, "Image Chooser");         chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);          startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);          return true;      }      // openFileChooser for Android 3.0+     public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {          mUploadMessage = uploadMsg;         // Create AndroidExampleFolder at sdcard         // Create AndroidExampleFolder at sdcard          File imageStorageDir = new File(                 Environment.getExternalStoragePublicDirectory(                         Environment.DIRECTORY_PICTURES)                 , "AndroidExampleFolder");          if (!imageStorageDir.exists()) {             // Create AndroidExampleFolder at sdcard             imageStorageDir.mkdirs();         }          // Create camera captured image file path and name         File file = new File(                 imageStorageDir + File.separator + "IMG_"                         + String.valueOf(System.currentTimeMillis())                         + ".jpg");          mCapturedImageURI = Uri.fromFile(file);          // Camera capture image intent         final Intent captureIntent = new Intent(                 android.provider.MediaStore.ACTION_IMAGE_CAPTURE);          captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);          Intent i = new Intent(Intent.ACTION_GET_CONTENT);         i.addCategory(Intent.CATEGORY_OPENABLE);         i.setType("image/*");          // Create file chooser intent         Intent chooserIntent = Intent.createChooser(i, "Image Chooser");          // Set camera intent to file chooser         chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS                 , new Parcelable[] { captureIntent });          // On select image call onActivityResult method of activity         startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);       }      // openFileChooser for Android < 3.0     public void openFileChooser(ValueCallback<Uri> uploadMsg) {         openFileChooser(uploadMsg, "");     }      //openFileChooser for other Android versions     public void openFileChooser(ValueCallback<Uri> uploadMsg,                                 String acceptType,                                 String capture) {          openFileChooser(uploadMsg, acceptType);     }  } 

//here is my onActivityResult method to handle data from gallery or camera intent

@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {          if (requestCode != INPUT_FILE_REQUEST_CODE || mFilePathCallback == null) {             super.onActivityResult(requestCode, resultCode, data);             return;         }          Uri[] results = null;          // Check that the response is a good one         if (resultCode == Activity.RESULT_OK) {             if (data == null) {                 // If there is not data, then we may have taken a photo                 if (mCameraPhotoPath != null) {                     results = new Uri[]{Uri.parse(mCameraPhotoPath)};                 }             } else {                 String dataString = data.getDataString();                 if (dataString != null) {                     results = new Uri[]{Uri.parse(dataString)};                 }             }         }          mFilePathCallback.onReceiveValue(results);         mFilePathCallback = null;      } else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {         if (requestCode != FILECHOOSER_RESULTCODE || mUploadMessage == null) {             super.onActivityResult(requestCode, resultCode, data);             return;         }          if (requestCode == FILECHOOSER_RESULTCODE) {              if (null == this.mUploadMessage) {                 return;              }              Uri result = null;              try {                 if (resultCode != RESULT_OK) {                      result = null;                  } else {                      // retrieve from the private variable if the intent is null                     result = data == null ? mCapturedImageURI : data.getData();                 }             } catch (Exception e) {                 Toast.makeText(getApplicationContext(), "activity :" + e,                         Toast.LENGTH_LONG).show();             }              mUploadMessage.onReceiveValue(result);             mUploadMessage = null;          }     }      return; } 

and here is the permissions required to open camera

<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.CAMERA2" /> // for new versions api 21+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> 

Note: My code also contains the code for devices running 3.0+ also but I never tested them , the above code worked on Lolipop, Marshmallow and Nougat emulators. One more thing , if you see and icon of Android System in place of Camera it means you have many apps available in your device to handle camera.

like image 151
Umar Ata Avatar answered Oct 15 '22 04:10

Umar Ata