1. 程式人生 > >WebView上傳圖片解決方案(包括4.4.2以及其它)

WebView上傳圖片解決方案(包括4.4.2以及其它)

WebView上傳圖片實現(本文只實現相簿選擇)

1.webview的缺陷

相信剛接觸過webview的童鞋,一定以為webview使用很簡單,就是把uri傳給webview即可,然後天真的以為webview就可以像瀏覽器那樣,可以實現網頁內的全部功能。But    突然有一天,新增業務需求:在webview內上傳圖片至伺服器,然後你去測試,就傻眼了,點選沒反應。

2.webview不能上傳的原因

自行google

3.webview不能上傳的解決方案(這才是重點)

3.1 解決方案(不包括android 4.4.2)

一般情況下我們的webview都是這樣初始化的:

 public void initWebview() throws Exception {
    isWebViewNull();
    WebSettings webSettings = webView.getSettings();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    }
    webSettings.setBlockNetworkImage(false);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        webSettings.setLoadsImagesAutomatically(true);
    } else {
        webSettings.setLoadsImagesAutomatically(false);
    }

    webSettings.setDomStorageEnabled(true);
    webSettings.setJavaScriptEnabled(true);
    //TODO
    webSettings.setUseWideViewPort(true);
    webSettings.setAllowFileAccess(true);
    webSettings.setUserAgentString(webSettings.getUserAgentString());
    webSettings.setPluginState(WebSettings.PluginState.ON);
    webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
}

重點是對webchromeClient的重寫,適用於大部分的手機

    private ValueCallback<Uri> mUploadMessage;
    private ValueCallback<Uri[]> mUploadCallbackAboveL;
    private final int RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP = 1;
    private final int RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP = 2;

    /**
    *內部類
    */
    class MyWebChromeClient extends WebChromeClient {
    // For Android 3.0+

    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
        if (mUploadMessage != null)
            return;
        mUploadMessage = uploadMsg;
        selectImage(RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP);
    }

    // For Android < 3.0
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
        openFileChooser(uploadMsg, "");
    }

    // For Android > 4.1.1

    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
        openFileChooser(uploadMsg, acceptType);
    }

    // For Android 5.0+
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        mUploadCallbackAboveL = filePathCallback;
        selectImage(RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP);
        return true;
    }

    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        progressBar.setSecondaryProgress(newProgress);
    }

    @Override
    public void onReceivedTitle(WebView view, String title) {
        super.onReceivedTitle(view, title);
        tv_title.setText(TextUtils.isEmpty(webTitle) ? title : webTitle);
    }

}
String compressPath = "";
/**開啟相簿,同時處理圖片(專案業務需要統一命名)*/
private void selectImage(int resultCode) {
    LogUtil.e("resultCode="+resultCode);
    compressPath = Environment.getExternalStorageDirectory().getPath() + "/QWB/temp";
    File file = new File(compressPath);
    if (!file.exists()) {
        file.mkdirs();
    }
    compressPath = compressPath + File.separator + "compress.png";

    File image = new File(compressPath);
    if (image.exists()) {
        image.delete();
    }

    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    Intent wrapperIntent = Intent.createChooser(intent, "File Chooser");
    startActivityForResult(wrapperIntent, resultCode);
}
/**選擇後,回傳值*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (mUploadMessage == null && mUploadCallbackAboveL == null) {
        return;
    }
    Uri uri = null;
    switch (requestCode) {
        case RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP: {
            uri = afterChosePic(data);
            if (mUploadMessage != null) {
                mUploadMessage.onReceiveValue(uri);
                mUploadMessage = null;
            }
        }
        break;
        case RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP: {
            uri = afterChosePic(data);
            if (mUploadCallbackAboveL != null) {
                mUploadCallbackAboveL.onReceiveValue(new Uri[]{uri});
                mUploadCallbackAboveL = null;
            }
        }
        break;
    }

}
/**
 * 選擇照片後結束
 *
 * @param data
 */

private Uri afterChosePic(Intent data) {

    if (data == null) {
        return null;
    }

    String path = BitmapUtils.getPath(this, data.getData());
    String[] names = path.split("\\.");
    String endName = null;
    if (names != null) {
        endName = names[names.length - 1];
    }
    if (endName != null) {
        compressPath = compressPath.split("\\.")[0] + "." + endName;
    }
    LogUtil.e("path===" + path + ",compress=" + compressPath + ",endName=" + endName);
    File newFile = FileUtils.compressFile(path, compressPath);
    return Uri.fromFile(newFile);
}

3.2解決方案(針對android 4.4.2,我的測試手機是samsung galaxy note2 android 4.4.2)

此方案不是我原創,是我在stackoverflow上面發現的,經測試,相當給力

但是這個demo,侷限性很大,不能動態的修改url,此為一大遺憾

程式碼較多,並牽扯到我並不熟悉的framework層,以及ndk的編碼,現僅奉上demo作為分享,

Demo下載地址