I need to pick images from the device and upload it to the server. For the first time, when I pick the images, onShowFileChooser() gets called and everything works. But, when I try to click upload again, onShowFileChooser() never gets called. But it's working for non-lollypop devices. openFileChoser() gets called, whenever I click upload. Is there anything that I'm missing. Here is my code :
//Needed for file upload feature vWebView.setWebChromeClient(new WebChromeClient() { // file upload callback (Android 2.2 (API level 8) -- Android 2.3 (API level 10)) (hidden method) public void openFileChooser(ValueCallback<Uri> filePathCallback) { showAttachmentDialog(filePathCallback); } // file upload callback (Android 3.0 (API level 11) -- Android 4.0 (API level 15)) (hidden method) public void openFileChooser(ValueCallback filePathCallback, String acceptType) { showAttachmentDialog(filePathCallback); } // file upload callback (Android 4.1 (API level 16) -- Android 4.3 (API level 18)) (hidden method) public void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture) { showAttachmentDialog(filePathCallback); } // file upload callback (Android 5.0 (API level 21) -- current) (public method) // for Lollipop, all in one @Override public boolean onShowFileChooser( WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { // Double check that we don't have any existing callbacks if (mFilePathCallbackArray != null) { mFilePathCallbackArray.onReceiveValue(null); } mFilePathCallbackArray = filePathCallback; // Set up the take picture intent if (mTypeCap == IMAGE) { Intent takePictureIntent = pictureIntentSetup(); return showChooserDialog(takePictureIntent); } //set up video capture intent else { Intent takeVideoIntent = videoIntentSetUp(); return showChooserDialog(takeVideoIntent); } } }); //For lollypop private Intent pictureIntentSetup() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(getActivity().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("Failed", "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; } } return takePictureIntent; } //For lollypop private Intent videoIntentSetUp() { Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); if (takeVideoIntent.resolveActivity(getActivity().getPackageManager()) != null) { // create the file where the video should go File videoFile = null; try { videoFile = createVideoFile(); takeVideoIntent.putExtra("PhotoPath", mCameraPhotoPath); } catch (IOException ex) { // Error occurred while creating the File Log.e("Failed", "Unable to create Video File", ex); } // continue only if the file was successfully created if (videoFile != null) { mCameraPhotoPath = "file:" + videoFile.getAbsolutePath(); takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(videoFile)); } else { takeVideoIntent = null; } } return takeVideoIntent; } //For lollypop private boolean showChooserDialog(Intent intent) { Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); if (mTypeCap.equalsIgnoreCase(IMAGE)) contentSelectionIntent.setType(IMAGE); else contentSelectionIntent.setType(VIDEO); Intent[] intentArray; if (intent != null) { intentArray = new Intent[]{intent}; } else { intentArray = new Intent[0]; } Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); if (mTypeCap.equalsIgnoreCase(IMAGE)) chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); else chooserIntent.putExtra(Intent.EXTRA_TITLE, "Video Chooser"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); getActivity().startActivityForResult(chooserIntent, FILE_CHOOSER_RESULT_CODE); return true; }
OnActivityResult of the activity:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //File upload related if (requestCode == NewsDetailFragment.FILE_CHOOSER_RESULT_CODE && (resultCode == RESULT_OK || resultCode == RESULT_CANCELED)) { Fragment fragment = getSupportFragmentManager() .findFragmentById(R.id.container); if (fragment != null && fragment instanceof DetailFragment) { Fragment currentFragment = ((DetailFragment) fragment).getCurrentFragment(); if (currentFragment instanceof WebDetailFragment) currentFragment.onActivityResult(requestCode, resultCode, data); } } } }
onActivityResult of fragment:
@Override public void onActivityResult(int requestCode, int resultCode, Intent intentData) { super.onActivityResult(requestCode, resultCode, intentData); // code for all versions except of Lollipop if (!Utility.isLollypopAndAbove()) { Uri result = null; // check that the response is a good one if (resultCode == Activity.RESULT_OK) { if (requestCode == FILE_CHOOSER_RESULT_CODE) { if (null == this.mFilePathCallback) { return; } if (null == mFilePathCallback) return; if (intentData == null) { // if there is not data, then we may have taken a photo if (mCameraPhotoPath != null) { result = Uri.parse(mCameraPhotoPath); } } else { String dataString = intentData.getDataString(); if (dataString != null) { result = Uri.parse(dataString); } } // Uri result = intentData == null || resultCode != Activity.RESULT_OK ? null // : intentData.getData(); } // for Lollipop only } mFilePathCallback.onReceiveValue(result); mFilePathCallback = null; } else { Uri[] results = null; // check that the response is a good one if(resultCode==Activity.RESULT_OK) { if (requestCode == FILE_CHOOSER_RESULT_CODE) { if (null == mFilePathCallbackArray) { return; } if (intentData == 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 = intentData.getDataString(); if (dataString != null) { results = new Uri[]{Uri.parse(dataString)}; } } } } mFilePathCallbackArray.onReceiveValue(results); mFilePathCallbackArray = null; return; } }
firstly, sorry to my english. you should return empty Uri[]{} to file receive
mUploadMessageForAndroid5.onReceiveValue(new Uri[]{});
private static final int REQUEST_GET_THE_THUMBNAIL = 4000; private static final long ANIMATION_DURATION = 200; public final static int FILECHOOSER_RESULTCODE = 1; public final static int FILECHOOSER_RESULTCODE_FOR_ANDROID_5 = 2; //JS webView.getSettings().setJavaScriptEnabled(true); //set ChromeClient webView.setWebChromeClient(getChromeClient()); //ChromeClinet配置 private WebChromeClient getChromeClient() { return new WebChromeClient() { //3.0++ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { openFileChooserImpl(uploadMsg); } //3.0-- public void openFileChooser(ValueCallback<Uri> uploadMsg) { openFileChooserImpl(uploadMsg); } public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { openFileChooserImpl(uploadMsg); } // For Android > 5.0 public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> uploadMsg, WebChromeClient.FileChooserParams fileChooserParams) { openFileChooserImplForAndroid5(uploadMsg); return true; } }; } private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; new AlertDialog.Builder(mActivity) .setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (items[which].equals(items[0])) { Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE); } else if (items[which].equals(items[1])) { dispatchTakePictureIntent(); } dialog.dismiss(); } }) .setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { Log.v(TAG, TAG + " # onCancel"); mUploadMessage = null; dialog.dismiss(); }}) .show(); } private void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg) { mUploadMessageForAndroid5 = uploadMsg; new AlertDialog.Builder(mActivity) .setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (items[which].equals(items[0])) { Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT); contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE); contentSelectionIntent.setType("image/*"); Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent); chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser"); startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE_FOR_ANDROID_5); } else if (items[which].equals(items[1])) { dispatchTakePictureIntent(); } dialog.dismiss(); } }) .setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { Log.v(TAG, TAG + " # onCancel"); //important to return new Uri[]{}, when nothing to do. This can slove input file wrok for once. //InputEventReceiver: Attempted to finish an input event but the input event receiver has already been disposed. mUploadMessageForAndroid5.onReceiveValue(new Uri[]{}); mUploadMessageForAndroid5 = null; dialog.dismiss(); }}).show(); } private void dispatchTakePictureIntent() { Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePictureIntent.resolveActivity(mActivity.getPackageManager()) != null) { // File file = new File(createImageFile()); Uri imageUri = null; try { imageUri = Uri.fromFile(createImageFile()); } catch (IOException e) { e.printStackTrace(); } //temp sd card file takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(takePictureIntent, REQUEST_GET_THE_THUMBNAIL); } } 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 = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/don_test/"); if (!storageDir.exists()) { storageDir.mkdirs(); } File image = File.createTempFile( imageFileName, /* prefix */ ".jpg", /* suffix */ storageDir /* directory */ ); // Save a file: path for use with ACTION_VIEW intents mCurrentPhotoPath = image.getAbsolutePath(); return image; } @Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { Log.v(TAG, TAG + " # onActivityResult # requestCode=" + requestCode + " # resultCode=" + resultCode); if (requestCode == FILECHOOSER_RESULTCODE) { if (null == mUploadMessage) return; Uri result = intent == null || resultCode != Activity.RESULT_OK ? null : intent.getData(); mUploadMessage.onReceiveValue(result); mUploadMessage = null; } else if (requestCode == FILECHOOSER_RESULTCODE_FOR_ANDROID_5) { if (null == mUploadMessageForAndroid5) return; Uri result; if (intent == null || resultCode != Activity.RESULT_OK) { result = null; } else { result = intent.getData(); } if (result != null) { Log.v(TAG, TAG + " # result.getPath()=" + result.getPath()); mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result}); } else { mUploadMessageForAndroid5.onReceiveValue(new Uri[]{}); } mUploadMessageForAndroid5 = null; } else if (requestCode == REQUEST_GET_THE_THUMBNAIL) { if (resultCode == Activity.RESULT_OK) { File file = new File(mCurrentPhotoPath); Uri localUri = Uri.fromFile(file); Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri); mActivity.sendBroadcast(localIntent); Uri result = Uri.fromFile(file); mUploadMessageForAndroid5.onReceiveValue(new Uri[]{result}); mUploadMessageForAndroid5 = null; } else { File file = new File(mCurrentPhotoPath); Log.v(TAG, TAG + " # file=" + file.exists()); if (file.exists()) { file.delete(); } } } }
Faced similar problem i was returning boolean value in method onShowFileChooser, issue was fixed when i called super class method
@Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { //Logic to implement return super.onShowFileChooser(webView, filePathCallback, fileChooserParams); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With