之前開發(fā)的時候都沒有注意到尚氛,在webview的頁面里面,如果有個地方要選擇圖片,不管怎么點擊都不會自動幫你跳轉(zhuǎn)到選擇圖片或者選擇文件的頁面,不管怎么點擊都是沒反應砌左。
在ios里面是點擊能自動跳轉(zhuǎn)的,而android不行铺敌,所以需要自己去寫跳轉(zhuǎn)的邏輯汇歹。
1.監(jiān)聽H5頁面點擊選擇文件
在WebChromeClient中,有一個方法可以監(jiān)聽H5選擇文件偿凭。低版本是openFileChooser产弹,高版本是onShowFileChooser,我們需要在WebChromeClient重寫這些方法弯囊。
public class MyWebChromeClient extends WebChromeClient {
private WebFileChoseListener webFileChoseListener;
// 3.0 + 調(diào)用這個方法
public void openFileChooser(ValueCallback filePathCallback, String acceptType) {
if (webFileChoseListener!= null){
webFileChoseListener.getFile(filePathCallback);
}
}
// Android > 4.1.1 調(diào)用這個方法
public void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture) {
if (webFileChoseListener!= null){
webFileChoseListener.getFile(filePathCallback);
}
}
// Android > 5.0 調(diào)用這個方法
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (webFileChoseListener!= null){
webFileChoseListener.getFile(filePathCallback);
}
return true;
}
public void setBnWebFileChoseListener(WebFileChoseListener webFileChoseListener) {
this.webFileChoseListener= webFileChoseListener;
}
}
不要在WebChromeClient 里面寫邏輯痰哨,單一職權嘛,所以我們寫個監(jiān)聽回調(diào)給外層匾嘱。這里寫了3個函數(shù)是因為我的最小版本是3.1斤斧,所以都寫上,如果最小版本是3.0以下霎烙,還要多寫個方法撬讽,這個可以在網(wǎng)上找到。最后看看我們監(jiān)聽回調(diào)的接口悬垃。
public interface WebFileChoseListener {
void getFile(ValueCallback valueCallback);
}
接收返回的filePathCallback是ValueCallback類型游昼,之后我們會用這個對象把本地圖片的uri傳回去。
2.跳轉(zhuǎn)相冊
在外部重寫getFile方法
@Override
public void getFile(ValueCallback valueCallback) {
this.valueCallback = valueCallback;
Intent intent = new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");
startActivityForResult(intent, Constant.INTENT_PHONE);
}
就直接跳轉(zhuǎn)相冊就好了尝蠕,這里只是我的寫法酱床,跳轉(zhuǎn)相冊、跳轉(zhuǎn)文件夾這些愛怎么寫怎么寫趟佃,這里的邏輯就已經(jīng)變成普通跳轉(zhuǎn)邏輯了扇谣,我的目的就是拿到uri就行昧捷,我不管你跳不跳轉(zhuǎn)或者跳轉(zhuǎn)到哪個頁面,只要最終拿到uri返回給h5就行罐寨。
3.返回結果給h5
我上面是跳轉(zhuǎn)系統(tǒng)相冊靡挥,獲取圖片成功肯定會回調(diào)給onActivityResult
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == BnConstant.INTENT_PHONE){
if (resultCode == Activity.RESULT_OK) {
WebUtils.seleteH5Phone(data, valueCallback);
}
}
}
valueCallback在上面this.valueCallback = valueCallback有保存到全局變量。WebUtils寫個工具類鸯绿,免得每次都要重復寫這堆邏輯跋破。
public class WebUtils {
public static void seleteH5File(Intent data, ValueCallback valueCallback){
if (valueCallback == null){
// todo valueCallback 為空的邏輯
return;
}
try {
Uri[] results = null;
String dataString = data.getDataString();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
ClipData clipData = data.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)};
valueCallback.onReceiveValue(results);
}
}catch (Exception e){
e.printStackTrace();
}
valueCallback = null;
}
}
這個valueCallback.onReceiveValue()在5.0 以上要傳Uri[]才行,單傳uri是沒用的瓶蝴《痉担回調(diào)中的參數(shù)也有泛型ValueCallback<Uri[]>,傳對應的就行舷手,所以我這里是沒對舊版本的進行兼容拧簸。
4. H5頁面的按鈕無法再次點擊
有的朋友可能會發(fā)生這種情況,H5頁面的按鈕第二次沒法點擊男窟。加入第一次點擊之后盆赤,我跳到了相冊,我沒有選圖片歉眷,直接返回牺六。之后再點H5頁面的按鈕就會沒反應。
這是因為前一次沒把結果回傳給H5汗捡。
所以要在某些地方加上valueCallback.onReceiveValue(null)淑际,就算選擇失敗,也要返回扇住。
將上面代碼改為
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Constant.INTENT_PHONE){
if (resultCode == Activity.RESULT_OK) {
BnWebUtils.seleteH5File(data, valueCallback);
}else {
valueCallback.onReceiveValue(null);
valueCallback = null;
}
}
}
public class WebUtils {
public static void seleteH5File(Intent data, ValueCallback valueCallback){
......
try {
......
}catch (Exception e){
e.printStackTrace();
valueCallback.onReceiveValue(null);
}
valueCallback = null;
}
}
這部分邏輯也并非很復雜春缕,只是很容易被忽視,就算你在某個項目寫了台囱,隔時間長了淡溯,下個項目也不一定會記得,所以要記錄下來簿训。
這還沒過一天就踩坑了咱娶。
問題:在android 4.4的手機上既不會調(diào)用openFileChooser方法也不會調(diào)用onShowFileChooser方法
在網(wǎng)上找,有人說是混淆强品,也許在其它地方還真跟混淆有點關系膘侮,但這里真不是混淆的問題。據(jù)說是因為谷歌在4.4的時候刪除了openFileChooser方法的榛,網(wǎng)上有些地方也給出了解決方法琼了。大部分都是兩種:
(1)方法1:使用其它的第三方webview框架,抱歉,我沒時間去一個一個試雕薪。
(2)方法2:不用這種套路昧诱,自己和H5做交互。那如果不是自己的H5頁面咋整所袁。
于是我想看看QQ瀏覽器是怎么解決的盏档,結果發(fā)現(xiàn)在4.4的手機上QQ瀏覽器也選不了圖片(不知道會不會是模擬器的影響)。于是我用4.3的版本試燥爷,結果發(fā)現(xiàn)4.3還真調(diào)用了openFileChooser方法蜈亩。
所以這應該就是谷歌留下的坑了。我當時就很氣前翎,認為谷歌為什么這么久都不解決這個問題稚配。其實谷歌真解決了,在5.0之后用新的onShowFileChooser就是谷歌的解決方法港华,而且谷歌本身就希望用戶用最新的幾個版本道川。所以這個問題沒法指望谷歌,自己想辦法繞彎解決吧苹丸。