在一个带有input tpye=file标签的Html页面,通过WebView,上传android手机上的图片,发现不工作。(在Ios和微信上完全正常工作)所以,需要研究一下Android的WebView,来支持type=file的标签。
WebView设置WebChromeClient
重写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());
}
|
本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1726034,如需转载请自行联系原作者