android 支持WebView上传文件

来源:互联网 发布:红色警戒mac版种子 编辑:程序博客网 时间:2024/05/16 15:28

android webview本身不支持文件上传,因此我们需要重写webview的WebChromeClient,对其中的onShowFileChooser(高版本会调用这个)和openFileChooser(低版本会调用这个)做相应处理,先上代码:

public class MyChromeClient extends WebChromeClient {    private static final String TAG = "MyChromeClient";    // 加载WebView的Activity     private UrlActivity activity;    public static final int FILECHOOSER_RESULTCODE = 5173;    public static final String CAMERA_DIR = "xiao6Camera";    @SuppressWarnings("deprecation")    public MyChromeClient(UrlActivity cordova) {        this.activity = cordova;    }    @Override    public void onProgressChanged(WebView view, int newProgress) {        super.onProgressChanged(view, newProgress);    }    // <input type="file" name="fileField" id="fileField" />    // Android > 4.1.1    @Override    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,            FileChooserParams fileChooserParams) {        // 传递ValueCallback<Uri[]>到activity        this.activity.setmUploadMsgList(filePathCallback);        this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);        return true;    }    @SuppressWarnings("static-access")    public void openFileChooser(ValueCallback<Uri> uploadMsg,            String acceptType, String capture) {        // 传递ValueCallback<Uri>到activity        this.activity.setmUploadMsg(uploadMsg);        this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);    }    // 3.0 +    @SuppressWarnings("static-access")    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {        // 传递ValueCallback<Uri>到activity        this.activity.setmUploadMsg(uploadMsg);        this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);    }    // Android < 3.0    @SuppressWarnings("static-access")    public void openFileChooser(ValueCallback<Uri> uploadMsg) {        // 传递ValueCallback<Uri>到activity        this.activity.setmUploadMsg(uploadMsg);        this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);    }    private Intent createDefaultOpenableIntent() {        Intent i = new Intent(Intent.ACTION_GET_CONTENT);        i.addCategory(Intent.CATEGORY_OPENABLE);        i.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,                "image/*");        Intent chooser = createChooserIntent(createCameraIntent());        chooser.putExtra(Intent.EXTRA_INTENT, i);        return chooser;    }    private Intent createChooserIntent(Intent... intents) {        Intent chooser = new Intent(Intent.ACTION_CHOOSER);        chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);        chooser.putExtra(Intent.EXTRA_TITLE, "选择图片");        return chooser;    }    @SuppressWarnings("static-access")    private Intent createCameraIntent() {        Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);        File externalDataDir = Environment                .getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);        File cameraDataDir = new File(externalDataDir.getAbsolutePath()                + File.separator + CAMERA_DIR);        cameraDataDir.mkdirs();        String mCameraFilePath = cameraDataDir.getAbsolutePath()                + File.separator + System.currentTimeMillis() + ".jpg";        // 把图片路径传给activity        this.activity.setmCameraFilePath(mCameraFilePath);        cameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);        cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,                Uri.fromFile(new File(mCameraFilePath)));        Log.i(TAG, "callback camera");        return cameraIntent;    }    /*     *      * private Intent createCamcorderIntent() { return new     *      * Intent(MediaStore.ACTION_VIDEO_CAPTURE); }     *      *      *      * private Intent createSoundRecorderIntent() { return new     *      * Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION); }     */    public static Uri getImageContentUri(Context context, java.io.File imageFile) {        String filePath = imageFile.getAbsolutePath();        Cursor cursor = context.getContentResolver().query(                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,                new String[] { MediaStore.Images.Media._ID },                MediaStore.Images.Media.DATA + "=? ",                new String[] { filePath }, null);        if (cursor != null && cursor.moveToFirst()) {            int id = cursor.getInt(cursor                    .getColumnIndex(MediaStore.MediaColumns._ID));            Uri baseUri = Uri.parse("content://media/external/images/media");            return Uri.withAppendedPath(baseUri, "" + id);        } else {            if (imageFile.exists()) {                ContentValues values = new ContentValues();                values.put(MediaStore.Images.Media.DATA, filePath);                return context.getContentResolver().insert(                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);            } else {                return null;            }        }    }}

使用时只需要Webview.setWebChromeClient(new MyChromeClient(this));
此时还需要重写加载webview的这个Activity的onActivityResult方法,在这里才是把文件传给web的

    /**     * webview上传文件的载体     */    public ValueCallback<Uri> mUploadMsg;    public ValueCallback<Uri[]> mUploadMsgList;    /**     * 如果调用拍照,图片保存路径     */    public static String mCameraFilePath = "";    public static String getmCameraFilePath() {        return mCameraFilePath;    }    public static void setmCameraFilePath(String mCameraFilePath) {        UrlActivity.mCameraFilePath = mCameraFilePath;    }    public ValueCallback<Uri> getmUploadMsg() {        return mUploadMsg;    }    public void setmUploadMsg(ValueCallback<Uri> mUploadMsg) {        this.mUploadMsg = mUploadMsg;    }    public ValueCallback<Uri[]> getmUploadMsgList() {        return mUploadMsgList;    }    public void setmUploadMsgList(ValueCallback<Uri[]> mUploadMsgList) {        this.mUploadMsgList = mUploadMsgList;    }// .......    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        switch (requestCode) {        case MyChromeClient.FILECHOOSER_RESULTCODE:            if (null == mUploadMsg && null == mUploadMsgList) {                Log.i("webview activity", "UploadMsg =null");                return;            }            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();            if (result != null || (!TextUtils.isEmpty(mCameraFilePath))) {                if (null == result) {                    result = Uri.fromFile(new File(mCameraFilePath));                }                if (null != mUploadMsg) {                    mUploadMsg.onReceiveValue(result);                }                if (null != mUploadMsgList) {                    mUploadMsgList.onReceiveValue(new Uri[] { result });                }            } else {                Log.i("webview activity", "result =null");                setResultNull();            }            break;        default:            break;        }    }    private void setResultNull() {        if (null != mUploadMsg) {            mUploadMsg.onReceiveValue(null);        }        if (null != mUploadMsgList) {            mUploadMsgList.onReceiveValue(null);        }    }

mCameraFilePath是拍照后回传的图片路径
mUploadMsg.onReceiveValue(null); 和mUploadMsgList.onReceiveValue(null);是必须要有的,比如正在选择图片上传时按返回键,如果不回传null,
web端会一直等待结果,导致你再次点击无响应。

mUploadMsgList是ValueCallback