WebView選擇文件

之前開發(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就是谷歌的解決方法港华,而且谷歌本身就希望用戶用最新的幾個版本道川。所以這個問題沒法指望谷歌,自己想辦法繞彎解決吧苹丸。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愤惰,一起剝皮案震驚了整個濱河市苇经,隨后出現(xiàn)的幾起案子赘理,更是在濱河造成了極大的恐慌,老刑警劉巖扇单,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件商模,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜘澜,警方通過查閱死者的電腦和手機施流,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鄙信,“玉大人瞪醋,你說我怎么就攤上這事∽肮睿” “怎么了银受?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸦采。 經(jīng)常有香客問我宾巍,道長,這世上最難降的妖魔是什么渔伯? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任顶霞,我火速辦了婚禮,結果婚禮上锣吼,老公的妹妹穿的比我還像新娘选浑。我一直安慰自己蓝厌,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布古徒。 她就那樣靜靜地躺著褂始,像睡著了一般。 火紅的嫁衣襯著肌膚如雪描函。 梳的紋絲不亂的頭發(fā)上崎苗,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機與錄音舀寓,去河邊找鬼胆数。 笑死,一個胖子當著我的面吹牛互墓,可吹牛的內(nèi)容都是我干的必尼。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼篡撵,長吁一口氣:“原來是場噩夢啊……” “哼判莉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起育谬,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤券盅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后膛檀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锰镀,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年咖刃,在試婚紗的時候發(fā)現(xiàn)自己被綠了泳炉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡嚎杨,死狀恐怖花鹅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情枫浙,我是刑警寧澤刨肃,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站自脯,受9級特大地震影響之景,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜膏潮,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一锻狗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦轻纪、人聲如沸油额。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽潦嘶。三九已至,卻和暖如春崇众,著一層夾襖步出監(jiān)牢的瞬間掂僵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工顷歌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锰蓬,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓眯漩,卻偏偏與公主長得像芹扭,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子赦抖,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 作者簡介 原創(chuàng)微信公眾號郭霖 WeChat ID: guolin_blog 又到了周五啦舱卡,提前祝大家周末愉快! 本...
    木木00閱讀 4,404評論 1 8
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫队萤、插件轮锥、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,029評論 4 62
  • 前言: 現(xiàn)在很多app里面,都會有這么一個需求浮禾,就是上傳圖片的按鈕交胚,當然按了這個按鈕之后份汗,就會出現(xiàn)二種選擇: 1....
    青蛙要fly閱讀 2,013評論 1 8
  • ¥開啟¥ 【iAPP實現(xiàn)進入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程盈电,因...
    小菜c閱讀 6,358評論 0 17
  • 之前就刷了劍指offer,這里復習的時候在博客上總結一下杯活,為了清晰思路和方便歸納匆帚。劍指offer是用c和c++實現(xiàn)...
    stoneyang94閱讀 260評論 0 0