前言:Android 有些项目需要在WebView
上调用手机系统相册来上传图片,开发过程中发现在很多机器上无法正常唤起系统相册来选择图片,要知道WebView 嵌套网页中有js调取拍照和选择图片上传的功能,这个需要在我们的代码中去实现方法。
首先,准备变量和WebView的基础设置
private WebView mWebView = null;
//5.0以下使用
private ValueCallback mUploadMessage;
// 5.0及以上使用
private ValueCallback<Uri[]> mUploadMessageAboveL;
//图片
private final static int FILE_CHOOSER_RESULT_CODE = 135;
//拍照图片路径
private String mCameraFielPath;
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setAllowFileAccess(true);
其次,WebView的WebChromeClient()重写
mWebView.setWebChromeClient(new WebChromeClient() {
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
}
@Override
public void onProgressChanged(WebView view, int progress) {
super.onProgressChanged(view, progress);
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> valueCallback) {
mUploadMessage = valueCallback;
openImageChooser();
}
// For Android >= 3.0
public void openFileChooser(ValueCallback valueCallback, String acceptType) {
mUploadMessage = valueCallback;
openImageChooser();
}
//For Android >= 4.1
public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
mUploadMessage = valueCallback;
openImageChooser();
}
// For Android >= 5.0
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
mUploadMessageAboveL = filePathCallback;
openImageChooser();
return true;
}
});
再者,实现openImageChooser()代码
private void openImageChooser() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if(takePictureIntent.resolveActivity(this.getPackageManager()) != null){
File photoFile = null;
try{
photoFile = FileUtil.createTempImageFile();
}catch(Exception ex){
MLog.e(TAG, "Image file creation failed", ex);
}
if(photoFile != null){
mCameraFielPath = photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
}else{
takePictureIntent = null;
}
}
Intent imageIntent = new Intent(Intent.ACTION_GET_CONTENT);
imageIntent.addCategory(Intent.CATEGORY_OPENABLE);
imageIntent.setType("image/*");
Intent[] intentArray;
if(takePictureIntent != null){
intentArray = new Intent[]{takePictureIntent};
}else{
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, imageIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooserIntent, FILE_CHOOSER_RESULT_CODE);
}
对了,上面有个创建临时图片文件的代码实现如下:
public static File createImageFile() throws IOException{
@SuppressLint("SimpleDateFormat")
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "img_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(imageFileName, ".jpg", storageDir);
}
接着,需要重写Activity的onActivityResult()这个方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (null == mUploadMessage && null == mUploadMessageAboveL) return;
if (resultCode != RESULT_OK) {
if (mUploadMessageAboveL != null) {
mUploadMessageAboveL.onReceiveValue(null);
mUploadMessageAboveL = null;
}
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
mUploadMessage = null;
}
return;
}
Uri result = null;
if (requestCode == FILE_CHOOSER_RESULT_CODE) {
if (null != data && null != data.getData()) {
result = data.getData();
}
if (result == null && FileUtil.isExist(mCameraFielPath)) {
result = Uri.fromFile(new File(mCameraFielPath));
}
if (mUploadMessageAboveL != null) {
onActivityResultAboveL(data, result);
} else if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void onActivityResultAboveL(Intent intent, Uri uri) {
Uri[] results = null;
if (intent != null) {
String dataString = intent.getDataString();
ClipData clipData = intent.getClipData();
if (clipData != null) {
results = new Uri[clipData.getItemCount()];
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
results[i] = item.getUri();
}
}
if (dataString != null)
results = new Uri[]{Uri.parse(dataString)};
}else {
if (uri != null){
results = new Uri[]{uri};
}
}
mUploadMessageAboveL.onReceiveValue(results);
mUploadMessageAboveL = null;
}
OK,到这你就可以试试了,你用写好的WebBrowserActivity装载:https://www.baidu.com/,或者https://www.google.com.hk/,使用搜索框中的图片搜索功能。或者你你自己创建一个html,如下:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="user-scalable=no">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<input id="input" type="file"/>
</body>
</html>
OK!OK!可以了吧,这回可以运行了吧,可以了,run吧。
mWebView.loadUrl("https://www.baidu.com/");
但是,有的人又该发问了,Release下怎么不可以使用呀?莫慌,这个时候你就要想到DR定律:只要Debug下正常Release下不正常,那就首先考虑混淆的事。解决版本如下:
-keepclassmembers class * extends android.webkit.WebChromeClient {
public void openFileChooser(...);
public void onShowFileChooser(...);
}
对了,上面代码里面用到了FileUtil,我也放出来:
public class FileUtil {
public static String addSlash(String pPath) {
if (!TextUtils.isEmpty(pPath)) {
if (!pPath.endsWith(File.separator)) {
pPath = pPath + File.separator;
}
}else {
pPath = File.separator;
}
return pPath;
}
public static boolean isExist(String pFilePath) {
try {
File file = new File(pFilePath);
return file.exists();
} catch (Exception e) {
return false;
}
}
@NonNull
public static File createTempImageFile() throws IOException {
String imageFileName = "img_" + formatDate(System.currentTimeMillis())+ "_";
File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(imageFileName, ".jpg", storageDir);
}
/**
* 格式成 yyyy-MM-dd HH:mm:ss
*
* @param pLongDate milliseconds
* @return
*/
public static String formatDate(long pLongDate) {
String dateFormat = "yyyy-MM-dd HH:mm:ss";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateFormat, Locale.getDefault());
String resultString = "";
try {
resultString = simpleDateFormat.format(new Date(pLongDate));
} catch (Exception e) {
e.printStackTrace();
}
return resultString;
}
}
到这里就完满结束了,你还有问题的话。
请QQ我136049925或者加入QQ群:179730949。
文章评论