概述
默認(rèn)情況
WebView 不支持<input type=file>,WebView 點(diǎn)擊沒有反應(yīng)。
兼容
重寫 webview 的 webchromeClient 中的 openFileChooser 方法。Android 版本的多樣性,就理所當(dāng)然的各種兼容。
// For Android < 3.0
public void openFileChooser(ValueCallback uploadMsg) {
openFileChooser(uploadMsg, "");
}
//For Android 3.0 - 4.0
public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
}
// For Android 4.0 - 5.0
public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg, acceptType);
}
// For Android > 5.0
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
return true;
}
具體代碼實(shí)現(xiàn)
網(wǎng)上也有很多實(shí)現(xiàn)方式,這邊記錄一下自己用到的一種
webview 調(diào)用時,彈出本地彈框,選擇(相冊/相機(jī)/取消),選擇相冊跳轉(zhuǎn)到文件選擇頁面、選擇相機(jī)注意權(quán)限配置,返回照片要做壓縮、選擇取消注意給webview一個空回應(yīng),要不點(diǎn)擊沒有反應(yīng)。
- ZpWebChromeClient
-
public class ZpWebChromeClient extends WebChromeClient { private OpenFileChooserCallBack mOpenFileChooserCallBack; // For Android < 3.0 public void openFileChooser(ValueCallback uploadMsg) { openFileChooser(uploadMsg, ""); } //For Android 3.0 - 4.0 public void openFileChooser(ValueCallback uploadMsg, String acceptType) { if (mOpenFileChooserCallBack != null) { mOpenFileChooserCallBack.openFileChooserCallBack(uploadMsg, acceptType); } } // For Android 4.0 - 5.0 public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Android > 5.0 @TargetApi(Build.VERSION_CODES.LOLLIPOP) public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) { if (mOpenFileChooserCallBack != null) { mOpenFileChooserCallBack.showFileChooserCallBack(filePathCallback, fileChooserParams); } return true; } public void setOpenFileChooserCallBack(OpenFileChooserCallBack callBack) { mOpenFileChooserCallBack = callBack; } public interface OpenFileChooserCallBack { void openFileChooserCallBack(ValueCallback uploadMsg, String acceptType); void showFileChooserCallBack(ValueCallback filePathCallback, FileChooserParams fileChooserParams); } }
- ZpWebView
-
public class ZpWebView extends WebView { private ZpWebChromeClient webChromeClient; public ZpWebView(Context context) { super(context); initWebView(); } public ZpWebView(Context context, AttributeSet attrs) { super(context, attrs); initWebView(); } public ZpWebView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initWebView(); } private void initWebView() { webChromeClient = new ZpWebChromeClient(); setWebChromeClient(webChromeClient); WebSettings webviewSettings = getSettings(); // 不支持縮放 webviewSettings.setSupportZoom(false); // 自適應(yīng)屏幕大小 webviewSettings.setUseWideViewPort(true); webviewSettings.setLoadWithOverviewMode(true); String cacheDirPath = getContext().getFilesDir().getAbsolutePath() + "cache/"; webviewSettings.setAppCachePath(cacheDirPath); webviewSettings.setAppCacheEnabled(true); webviewSettings.setDomStorageEnabled(true); webviewSettings.setAllowFileAccess(true); webviewSettings.setAppCacheMaxSize(1024 * 1024 * 8); webviewSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); } public void setOpenFileChooserCallBack(ZpWebChromeClient.OpenFileChooserCallBack callBack) { webChromeClient.setOpenFileChooserCallBack(callBack); } }
- MainActivity
-
public class MainActivity extends AppCompatActivity { public static final int REQUEST_SELECT_FILE_CODE = 100; private static final int REQUEST_FILE_CHOOSER_CODE = 101; private static final int REQUEST_FILE_CAMERA_CODE = 102; // 默認(rèn)圖片壓縮大?。▎挝唬篕) public static final int IMAGE_COMPRESS_SIZE_DEFAULT = 400; // 壓縮圖片最小高度 public static final int COMPRESS_MIN_HEIGHT = 900; // 壓縮圖片最小寬度 public static final int COMPRESS_MIN_WIDTH = 675; private ValueCallback mUploadMsg; private ValueCallback mUploadMsgs; // 相機(jī)拍照返回的圖片文件 private File mFileFromCamera; private File mTakePhotoFile; private BottomSheetDialog selectPicDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { ZpWebView webView = findViewById(R.id.webview); webView.setOpenFileChooserCallBack(new ZpWebChromeClient.OpenFileChooserCallBack() { @Override public void openFileChooserCallBack(ValueCallback uploadMsg, String acceptType) { mUploadMsg = uploadMsg; showSelectPictrueDialog(0, null); } @Override public void showFileChooserCallBack(ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { if (mUploadMsgs != null) { mUploadMsgs.onReceiveValue(null); } mUploadMsgs = filePathCallback; showSelectPictrueDialog(1, fileChooserParams); } }); } /** * 選擇圖片彈框 */ private void showSelectPictrueDialog(final int tag, final WebChromeClient.FileChooserParams fileChooserParams) { selectPicDialog = new BottomSheetDialog(this, R.style.Dialog_NoTitle); selectPicDialog.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface dialogInterface) { if (mUploadMsgs != null) { mUploadMsgs.onReceiveValue(null); mUploadMsgs = null; } } }); View view = LayoutInflater.from(this).inflate(R.layout.dialog_bottom_select_pictrue, null); // 相冊 TextView album = view.findViewById(R.id.tv_select_pictrue_album); // 相機(jī) TextView camera = view.findViewById(R.id.tv_select_pictrue_camera); // 取消 TextView cancel = view.findViewById(R.id.tv_select_pictrue_cancel); album.setOnClickListener(new View.OnClickListener() { @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onClick(View view) { if (tag == 0) { Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("*/*"); startActivityForResult(Intent.createChooser(i, "File Browser"), REQUEST_FILE_CHOOSER_CODE); } else { try { Intent intent = fileChooserParams.createIntent(); startActivityForResult(intent, REQUEST_SELECT_FILE_CODE); } catch (ActivityNotFoundException e) { mUploadMsgs = null; } } } }); camera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { takeCameraPhoto(); } }); cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { selectPicDialog.dismiss(); } }); selectPicDialog.setContentView(view); selectPicDialog.show(); } public void takeCameraPhoto() { if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) { Toast.makeText(this, "設(shè)備無攝像頭", Toast.LENGTH_SHORT).show(); return; } String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath(); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); mFileFromCamera = new File(filePath, System.nanoTime() + ".jpg"); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTakePhotoFile)); startActivityForResult(intent, REQUEST_FILE_CAMERA_CODE); } else { try { mTakePhotoFile = File.createTempFile("Zp" + System.nanoTime(), ".jpg", filePath); Uri contentUri = FileProvider.getUriForFile(InnerBrowserActivity.this, "com.zp.demo.ZpFileProvider", mTakePhotoFile); intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(intent, REQUEST_FILE_CAMERA_CODE); } catch (IOException e) { } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_SELECT_FILE_CODE: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (mUploadMsgs == null) { return; } mUploadMsgs.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data)); mUploadMsgs = null; } break; case REQUEST_FILE_CHOOSER_CODE: if (mUploadMsg == null) { return; } Uri result = data == null || resultCode != RESULT_OK ? null : data.getData(); mUploadMsg.onReceiveValue(result); mUploadMsg = null; break; case REQUEST_FILE_CAMERA_CODE: takePictureFromCamera(); break; } } /** * 處理相機(jī)返回的圖片 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void takePictureFromCamera() { if (mFileFromCamera != null && mFileFromCamera.exists()) { String filePath = mFileFromCamera.getAbsolutePath(); // 壓縮圖片到指定大小 File imgFile = ZpImageUtils.compressImage(this, filePath, COMPRESS_MIN_WIDTH, COMPRESS_MIN_HEIGHT, IMAGE_COMPRESS_SIZE_DEFAULT); Uri localUri = Uri.fromFile(imgFile); Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri); this.sendBroadcast(localIntent); Uri result = Uri.fromFile(imgFile); if (mUploadMsg != null) { mUploadMsg.onReceiveValue(Uri.parse(filePath)); mUploadMsg = null; } if (mUploadMsgs != null) { mUploadMsgs.onReceiveValue(new Uri[]{result}); mUploadMsgs = null; } } else { if (mUploadMsg != null) { mUploadMsg.onReceiveValue(null); mUploadMsg = null; } if (mUploadMsgs != null) { mUploadMsgs.onReceiveValue(null); mUploadMsgs = null; } } } }
備注:代碼不規(guī)范的地方,自己抽取一下,這里就不做抽取了。
-
Github 地址文章來源:http://www.zghlxwxcb.cn/news/detail-420597.html
-
WebViewUploadFileDemo文章來源地址http://www.zghlxwxcb.cn/news/detail-420597.html
到了這里,關(guān)于Android webview上傳圖片(調(diào)起相冊/相機(jī)上傳)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!