這周遇到一個比較棘手的問題,需要在android上邊集成h5頁面,並且在h5頁面上,需要用戶能夠上傳android本地的照片,一開始我以為webview會自動處理掉的,因此沒太留意,當真正集成時,才發現,h5界面上傳圖片無法打開本地android的圖庫,h5調用的方式是:
<input type = "file"/>
通過最為簡單的input菜單來選擇,於是我就百度了一波,找到了兩種比較好的解決方法,一種是h5編寫js代碼,調用android app實現的函數,來實現打開圖庫進行圖片選擇的功能,還有一種方法是,通過重寫webview中WebChromeClient類,然后來進行實現打開本地圖庫的功能。
在這主要講述第二種方法的實現。
我這先放上重寫的代碼:
public class OpenFileWebChromeClient extends WebChromeClient {
public String TAG = "OpenFileWebChromeClient";
public static final int REQUEST_FILE_PICKER = 1;
public ValueCallback<Uri> mFilePathCallback;
public ValueCallback<Uri[]> mFilePathCallbacks;
private Activity mContext;
private TextView textView;
public OpenFileWebChromeClient(Activity mContext) {
super();
this.mContext = mContext;
}
/**
* Android < 3.0 調用這個方法
*/
public void openFileChooser(ValueCallback<Uri> filePathCallback) {
mFilePathCallback = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
mContext.startActivityForResult(Intent.createChooser(intent, "File Chooser"),
REQUEST_FILE_PICKER);
}
/**
* 3.0 + 調用這個方法
*/
public void openFileChooser(ValueCallback filePathCallback,
String acceptType) {
mFilePathCallback = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
mContext.startActivityForResult(Intent.createChooser(intent, "File Chooser"),
REQUEST_FILE_PICKER);
}
/**
* js上傳文件的<input type="file" name="fileField" id="fileField" />事件捕獲
*/
/**
* Android > 4.1.1 調用這個方法
*/
@Deprecated
public void openFileChooser(ValueCallback<Uri> filePathCallback,
String acceptType, String capture) {
mFilePathCallback = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
mContext.startActivityForResult(Intent.createChooser(intent, "File Chooser"),
REQUEST_FILE_PICKER);
}
@Override
public boolean onShowFileChooser(WebView webView,
ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams) {
mFilePathCallbacks = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
mContext.startActivityForResult(Intent.createChooser(intent, "File Chooser"),
REQUEST_FILE_PICKER);
return true;
}
}
這樣既可打開本地的圖庫,當然,這只是能夠打開了,選擇后的圖片又怎樣返回給h5頁面呢?
需要在activity中實現如下的代碼:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == OpenFileWebChromeClient.REQUEST_FILE_PICKER) {
if (mOpenFileWebChromeClient.mFilePathCallback != null) {
Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
: intent.getData();
if (result != null) {
String path = MediaUtility.getPath(getApplicationContext(),
result);
Uri uri = Uri.fromFile(new File(path));
mOpenFileWebChromeClient.mFilePathCallback
.onReceiveValue(uri);
} else {
mOpenFileWebChromeClient.mFilePathCallback
.onReceiveValue(null);
}
}
if (mOpenFileWebChromeClient.mFilePathCallbacks != null) {
Uri result = intent == null || resultCode != Activity.RESULT_OK ? null
: intent.getData();
if (result != null) {
String path = MediaUtility.getPath(getApplicationContext(),
result);
Uri uri = Uri.fromFile(new File(path));
mOpenFileWebChromeClient.mFilePathCallbacks
.onReceiveValue(new Uri[] { uri });
} else {
mOpenFileWebChromeClient.mFilePathCallbacks
.onReceiveValue(null);
}
}
mOpenFileWebChromeClient.mFilePathCallback = null;
mOpenFileWebChromeClient.mFilePathCallbacks = null;
}
}
這樣,返回的數據則是h5頁面需要的數據,這樣一來,h5就可以像在電腦上一樣的,對返回的數據進行操作,可以進行實時的預覽,上傳等功能。
但是對於以上的方法,我們在測試的時候發現,在android4.4上是不支持的,原因則是android4.4的webview沒有對onShowFileChooser和openFileChooser做任何的處理,因此不支持,這算是android上的一個坑吧。
最后,記得添加權限,因為要讀取本地的圖片,所以要獲取讀本地sdcard的權限!
