http://blog.csdn.net/earbao/article/details/50716747
http://david-wei.github.io/2015/07/07/Webview-%E6%94%AF%E6%8C%81-input-type-file/
在一個(gè)帶有input tpye=file標(biāo)簽的Html頁面岩喷,通過WebView,上傳android手機(jī)上的圖片监憎,發(fā)現(xiàn)不工作纱意。(在Ios和微信上完全正常工作)所以,需要研究一下Android的WebView鲸阔,來支持type=file的標(biāo)簽偷霉。
WebView設(shè)置WebChromeClient
重寫WebChromeClient中關(guān)于文件選擇的方法迄委,onShowFileChooser和openFileChooser。(項(xiàng)目中只需要選擇圖片类少,所以加上了圖片過濾叙身。)
public static final int INPUT_FILE_REQUEST_CODE = 1;
private ValueCallback mUploadMessage;
private final static int FILECHOOSER_RESULTCODE = 2;
private ValueCallback mFilePathCallback;
private String mCameraPhotoPath;
private WebChromeClient mWebChromeClient = new WebChromeClient() {
? ? // android 5.0
? ? public boolean onShowFileChooser(
? ? ? ? ? ? WebView webView, ValueCallback filePathCallback,
? ? ? ? ? ? WebChromeClient.FileChooserParams fileChooserParams) {
? ? ? ? if (mFilePathCallback != null) {
? ? ? ? ? ? mFilePathCallback.onReceiveValue(null);
? ? ? ? }
? ? ? ? mFilePathCallback = filePathCallback;
? ? ? ? Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
? ? ? ? if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
? ? ? ? ? ? // Create the File where the photo should go
? ? ? ? ? ? File photoFile = null;
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? photoFile = createImageFile();
? ? ? ? ? ? ? ? takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
? ? ? ? ? ? } catch (IOException ex) {
? ? ? ? ? ? ? ? // Error occurred while creating the File
? ? ? ? ? ? ? ? Log.e("WebViewSetting", "Unable to create Image File", ex);
? ? ? ? ? ? }
? ? ? ? ? ? // Continue only if the File was successfully created
? ? ? ? ? ? if (photoFile != null) {
? ? ? ? ? ? ? ? mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
? ? ? ? ? ? ? ? takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
? ? ? ? ? ? ? ? ? ? ? ? Uri.fromFile(photoFile));
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? takePictureIntent = null;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
? ? ? ? contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
? ? ? ? contentSelectionIntent.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, contentSelectionIntent);
? ? ? ? chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
? ? ? ? chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
? ? ? ? startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
? ? ? ? return true;
? ? }
? ? //The undocumented magic method override
? ? //Eclipse will swear at you if you try to put @Override here
? ? // For Android 3.0+
? ? public void openFileChooser(ValueCallback uploadMsg) {
? ? ? ? mUploadMessage = uploadMsg;
? ? ? ? Intent i = new Intent(Intent.ACTION_GET_CONTENT);
? ? ? ? i.addCategory(Intent.CATEGORY_OPENABLE);
? ? ? ? i.setType("image/*");
? ? ? ? WebViewActivity.this.startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILECHOOSER_RESULTCODE);
? ? }
? ? // For Android 3.0+
? ? public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
? ? ? ? mUploadMessage = uploadMsg;
? ? ? ? Intent i = new Intent(Intent.ACTION_GET_CONTENT);
? ? ? ? i.addCategory(Intent.CATEGORY_OPENABLE);
? ? ? ? i.setType("image/*");
? ? ? ? WebViewActivity.this.startActivityForResult(
? ? ? ? ? ? ? ? Intent.createChooser(i, "Image Chooser"),
? ? ? ? ? ? ? ? FILECHOOSER_RESULTCODE);
? ? }
? ? //For Android 4.1
? ? public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
? ? ? ? mUploadMessage = uploadMsg;
? ? ? ? Intent i = new Intent(Intent.ACTION_GET_CONTENT);
? ? ? ? i.addCategory(Intent.CATEGORY_OPENABLE);
? ? ? ? i.setType("image/*");
? ? ? ? WebViewActivity.this.startActivityForResult(Intent.createChooser(i, "Image Chooser"), WebViewActivity.FILECHOOSER_RESULTCODE);
? ? }
};
在onActivityResult中獲取對(duì)應(yīng)的選取文件的返回結(jié)果
public void onActivityResult(int requestCode, int resultCode, Intent data) {
? ? if (requestCode == FILECHOOSER_RESULTCODE) {
? ? ? ? if (null == mUploadMessage) return;
? ? ? ? Uri result = data == null || resultCode != RESULT_OK ? null
? ? ? ? ? ? ? ? : data.getData();
? ? ? ? if (result != null) {
? ? ? ? ? ? String imagePath = ImageFilePath.getPath(this, result);
? ? ? ? ? ? if (!StrUtils.isEmpty(imagePath)) {
? ? ? ? ? ? ? ? result = Uri.parse("file:///" + imagePath);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? mUploadMessage.onReceiveValue(result);
? ? ? ? mUploadMessage = null;
? ? } else if (requestCode == INPUT_FILE_REQUEST_CODE && mFilePathCallback != null) {
? ? ? ? // 5.0的回調(diào)
? ? ? ? Uri[] results = null;
? ? ? ? // Check that the response is a good one
? ? ? ? if (resultCode == Activity.RESULT_OK) {
? ? ? ? ? ? if (data == null) {
? ? ? ? ? ? ? ? // If there is not data, then we may have taken a photo
? ? ? ? ? ? ? ? if (mCameraPhotoPath != null) {
? ? ? ? ? ? ? ? ? ? Logger.d("camera_photo_path", mCameraPhotoPath);
? ? ? ? ? ? ? ? ? ? results = new Uri[]{Uri.parse(mCameraPhotoPath)};
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? String dataString = data.getDataString();
? ? ? ? ? ? ? ? Logger.d("camera_dataString", dataString);
? ? ? ? ? ? ? ? if (dataString != null) {
? ? ? ? ? ? ? ? ? ? results = new Uri[]{Uri.parse(dataString)};
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? mFilePathCallback.onReceiveValue(results);
? ? ? ? mFilePathCallback = null;
? ? } else {
? ? ? ? super.onActivityResult(requestCode, resultCode, data);
? ? ? ? return;
? ? }
}
返回文件的解析,因?yàn)閔tml頁面需要的是文件硫狞,所以客戶端需要返回的是對(duì)應(yīng)文件的路徑信轿。這樣,就會(huì)存在一個(gè)問題残吩,在Android 4.4上财忽,通過文件選擇返回的結(jié)果都是對(duì)應(yīng)以content開頭格式的對(duì)應(yīng)的路徑。這就得需要咱們來進(jìn)行判斷世剖,最終都需要轉(zhuǎn)回成以file開頭對(duì)應(yīng)的格式文件定罢。下面,我封裝成了一個(gè)ImageFilePath的類旁瘫,通過調(diào)用getPath方法來獲取最終的結(jié)果。這個(gè)類的方法如下:
/**
* Method for return file path of Gallery image
*
* @param context
* @param uri
* @return path of the selected image file from gallery
*/
public static String getPath(final Context context, final Uri uri) {
? ? // check here to KITKAT or new version
? ? final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
? ? // DocumentProvider
? ? if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
? ? ? ? // ExternalStorageProvider
? ? ? ? if (isExternalStorageDocument(uri)) {
? ? ? ? ? ? final String docId = DocumentsContract.getDocumentId(uri);
? ? ? ? ? ? final String[] split = docId.split(":");
? ? ? ? ? ? final String type = split[0];
? ? ? ? ? ? if ("primary".equalsIgnoreCase(type)) {
? ? ? ? ? ? ? ? return Environment.getExternalStorageDirectory() + "/"
? ? ? ? ? ? ? ? ? ? ? ? + split[1];
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // DownloadsProvider
? ? ? ? else if (isDownloadsDocument(uri)) {
? ? ? ? ? ? final String id = DocumentsContract.getDocumentId(uri);
? ? ? ? ? ? final Uri contentUri = ContentUris.withAppendedId(
? ? ? ? ? ? ? ? ? ? Uri.parse("content://downloads/public_downloads"),
? ? ? ? ? ? ? ? ? ? Long.valueOf(id));
? ? ? ? ? ? return getDataColumn(context, contentUri, null, null);
? ? ? ? }
? ? ? ? // MediaProvider
? ? ? ? else if (isMediaDocument(uri)) {
? ? ? ? ? ? final String docId = DocumentsContract.getDocumentId(uri);
? ? ? ? ? ? final String[] split = docId.split(":");
? ? ? ? ? ? final String type = split[0];
? ? ? ? ? ? Uri contentUri = null;
? ? ? ? ? ? if ("image".equals(type)) {
? ? ? ? ? ? ? ? contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
? ? ? ? ? ? } else if ("video".equals(type)) {
? ? ? ? ? ? ? ? contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
? ? ? ? ? ? } else if ("audio".equals(type)) {
? ? ? ? ? ? ? ? contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
? ? ? ? ? ? }
? ? ? ? ? ? final String selection = "_id=?";
? ? ? ? ? ? final String[] selectionArgs = new String[] { split[1] };
? ? ? ? ? ? return getDataColumn(context, contentUri, selection,
? ? ? ? ? ? ? ? ? ? selectionArgs);
? ? ? ? }
? ? }
? ? // MediaStore (and general)
? ? else if ("content".equalsIgnoreCase(uri.getScheme())) {
? ? ? ? // Return the remote address
? ? ? ? if (isGooglePhotosUri(uri))
? ? ? ? ? ? return uri.getLastPathSegment();
? ? ? ? return getDataColumn(context, uri, null, null);
? ? }
? ? // File
? ? else if ("file".equalsIgnoreCase(uri.getScheme())) {
? ? ? ? return uri.getPath();
? ? }
? ? return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context
*? ? ? ? ? ? The context.
* @param uri
*? ? ? ? ? ? The Uri to query.
* @param selection
*? ? ? ? ? ? (Optional) Filter used in the query.
* @param selectionArgs
*? ? ? ? ? ? (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String selection, String[] selectionArgs) {
? ? Cursor cursor = null;
? ? final String column = "_data";
? ? final String[] projection = { column };
? ? try {
? ? ? ? cursor = context.getContentResolver().query(uri, projection,
? ? ? ? ? ? ? ? selection, selectionArgs, null);
? ? ? ? if (cursor != null && cursor.moveToFirst()) {
? ? ? ? ? ? final int index = cursor.getColumnIndexOrThrow(column);
? ? ? ? ? ? return cursor.getString(index);
? ? ? ? }
? ? } finally {
? ? ? ? if (cursor != null)
? ? ? ? ? ? cursor.close();
? ? }
? ? return null;
}
/**
* @param uri
*? ? ? ? ? ? The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
? ? return "com.android.externalstorage.documents".equals(uri
? ? ? ? ? ? .getAuthority());
}
/**
* @param uri
*? ? ? ? ? ? The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
? ? return "com.android.providers.downloads.documents".equals(uri
? ? ? ? ? ? .getAuthority());
}
/**
* @param uri
*? ? ? ? ? ? The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
? ? return "com.android.providers.media.documents".equals(uri
? ? ? ? ? ? .getAuthority());
}
/**
* @param uri
*? ? ? ? ? ? The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
? ? return "com.google.android.apps.photos.content".equals(uri
? ? ? ? ? ? .getAuthority());
}