onShowFileChooser() from android webview works only once onShowFileChooser() from android webview works only once android android

onShowFileChooser() from android webview works only once


firstly, sorry to my english. you should return empty Uri[]{} to file receive

mUploadMessageForAndroid5.onReceiveValue(new Uri[]{});

my code can choose take photo or local image:

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;//JSwebView.getSettings().setJavaScriptEnabled(true);//set ChromeClientwebView.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;}@Overridepublic 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);        }


In the onShowFileChooser() method you should return true, only if you are using the filePathCallback, which is the best way:

private ValueCallback<Uri[]> filePathCallback;@Overridepublic boolean onShowFileChooser(        WebView webView, ValueCallback<Uri[]> filePathCallback,        WebChromeClient.FileChooserParams fileChooserParams) {    // do whatever you need to do, to show a file chooser/camera intent    this.filePathCallback = filePathCallback;    return true;}@Overrideprotected void onActivityResult(int requestCode, int resultCode,                                Intent intent) {    // Check for your correct requestCode from your intent here    if (resultCode == RESULT_CANCELED) {        // this is important, call the callback with null parameter        this.filePathCallback.onReceiveValue(null);    } else if (resultCode == RESULT_OK) {        // extract the uri(s) you need here        this.filePathCallback.onReceiveValue(new Uri[]{result});    }}