本文共 9590 字,大约阅读时间需要 31 分钟。
在一个带有input tpye=file标签的Html页面,通过WebView,上传android手机上的图片,发现不工作。(在Ios和微信上完全正常工作)所以,需要研究一下Android的WebView,来支持type=file的标签。
重写WebChromeClient中关于文件选择的方法,onShowFileChooser和openFileChooser。(项目中只需要选择图片,所以加上了图片过滤。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | public static final int INPUT_FILE_REQUEST_CODE = 1 ; private ValueCallback<Uri> mUploadMessage; private final static int FILECHOOSER_RESULTCODE = 2 ; private ValueCallback<Uri[]> mFilePathCallback; private String mCameraPhotoPath; private WebChromeClient mWebChromeClient = new WebChromeClient() { // android 5.0 public boolean onShowFileChooser( WebView webView, ValueCallback<Uri[]> 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<Uri> 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<Uri> 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中获取对应的选取文件的返回结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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的回调 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 ; } } |
返回文件的解析,因为html页面需要的是文件,所以客户端需要返回的是对应文件的路径。这样,就会存在一个问题,在Android 4.4上,通过文件选择返回的结果都是对应以content开头格式的对应的路径。这就得需要咱们来进行判断,最终都需要转回成以file开头对应的格式文件。下面,我封装成了一个ImageFilePath的类,通过调用getPath方法来获取最终的结果。这个类的方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | /** * 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()); } |