1. 程式人生 > 實用技巧 >flutter專案實現webview Activity(小程式)

flutter專案實現webview Activity(小程式)

眾所周知,flutter官方的webview存在這樣那樣的bug,一個個去維護又很累,還有一些是國內特有機型會產生的bug,特有輸入法產生的bug。像這種不會產生crash的bug,在isssues裡提了,多半就沒有訊息了。而且flutter官方也說webview不建議投入使用,鍵盤的坑也格外的多,無法複製貼上之類的。對這一類做了一些適配,到最後百度輸入法的一個bug切切實實的打敗了我。也沒有別的方案可以解決。

而且flutter webview的bug其實是來自於androidView,甚至可能是flutter engine的問題,國內的大公司類似鹹魚都是自己定製了flutter engine。所以,這塊選擇是用原生的webview來實現吧。

廢話有點多,簡單的介紹一下,我這裡的業務場景,我現在的軟體是提供webview給第三方,有點類似小程式的樣子,然後也定製了一些功能。

實現類似小程式的樣子

像微信,支付寶之類的小程式開啟後,後臺會多出一個任務來,可以同時開啟主任務和小程式的任務進行互動。不是很清楚的話,可以自己開啟下手機看一下。

想要實現兩個任務其實很簡單,更改AndroidManifest裡taskAffinity屬性,如下圖,

然後在啟動的時候設定intent屬性

intent.setFlags(intent.FLAG_ACTIVITY_NEW_TASK);

這兩段結合起來,在startActivity的時候,他會新開一個棧,而不是和主任務在一個棧裡。這樣就初步實現了後臺中兩個任務的需求了。但是,現在問題來了,那如果他開了第二個小程式了怎麼辦呢?對吧,看一下微信發現他會再建立一個。

好,那麼問題來了,微信的小程式是不是開幾個建立幾個呢?開多少個後臺就有多少個呢。我覺得不是,微信應該設定了數量,有個上限 ,但是這個上限是多少可以自己去設定一下。我在觀察微信小程式的activity的時候發現,不同的小程式特定情況下會佔用同一個的activity。

竟然如此,那麼就是說,微信小程式和activity的按需分配的,也就是說小程式是無限的,但是activity是有限的。當要開啟一個小程式前,他去看看有哪些activity是空著的,空著就把他塞進去。

所以這邊,我的解決方法是建立多個webviewActivity,他們分屬不同的棧,定了一下上限為5。也就是建立了五個一樣的activity,當然存在一些小區別。實現的邏輯大概如下:

我在application申明瞭一個數組,List[0]即表示activity0,當list[0]中有資料的時候 ,即表示這個activity在使用中。list在application啟動的時候會自動清零,然後依次存進去,一邊存一邊啟動這個activity。5個存滿之後,加個標識,從頭開始覆蓋。因為主專案是flutter寫的,所以很多功能無法剝離開,必須要啟動主專案,所以在application裡再去申明一個int型別的activity,當webview裡的頁面需要呼叫主專案的方法時,把當前activity記錄下來,比如activity0,就記錄0,然後等主專案這邊結束了,就啟動0這個activity。

webview實現input type=file

flutter的webview是沒有這個功能的,因為原生的webview也沒有這個功能,需要重寫onShowFileChooser這個方法,這一塊我之前寫過一篇比較詳細的,可以看下這篇https://www.cnblogs.com/afei123/p/13053712.html

簡單說一下,那邊的邏輯是在onShowFileChooser跳轉一個透明activity,然後從這個activity去選擇,如下圖。然後開啟相機和選擇檔案這塊可以去那篇文章的github連結裡去看,具體不贅述了。

當初為了下面這個dialog,新建了一個ativity,其實現在自定義webview的時候完全可以放到自己的webviewactivity裡去。這裡講點高階的東西,需求來了,希望開啟檔案管理器可以根據前端程式碼進行選擇。變成下圖這樣。

input type=file的時候還可以設定accept屬性,用來選擇開啟照片還是別的什麼東西,開啟照片的情況下,檔案什麼都是不可看的狀態。然後accept這個屬性可以通過下面的方法獲取,所以怎麼搞明白了吧。

final String[] acceptTypes = getSafeAcceptedTypes(fileChooserParams);

實現文件預覽

文件預覽這塊實現需要接入TBS服務,也就是騰訊的x5核心。這個有一個缺陷就是需要把檔案下載到本地,而且如果不是用騰訊瀏覽器開啟只支援9種格式,具體的可以在TBS的官網去看一下。

我這邊將原生的webview也全部替換成了x5,也為了方便點。

所以實現文件預覽需要走兩步,一步下載,一步開啟。下載文件自己就根據url去設定就好了,開一個執行緒,下載完了執行開啟文件的方法。

我這裡使用的是TbsReaderView這個方法,這個方法官網上沒講。使用方法如下

tbsReaderView = new TbsReaderView(this,readerCallback);
        RelativeLayout mRelativeLayout = findViewById(R.id.tbsView);
        mRelativeLayout.addView(tbsReaderView,new RelativeLayout.LayoutParams(-1,-1));

我這邊是建立了一個activity來顯示他,然後自己定義了下toolbar。

圖片預覽

然後還要實現的就是圖片預覽,我這邊是預設拿到了圖片地址list。然後用photoView+viewPager實現他。不過很奇怪,當photoView放入viewPager之後,就無法縮放了。這塊mark一下。

和flutter的互動

如下圖,當反饋需要開啟flutter頁面怎麼辦。

包括js事件需要傳遞給flutter怎麼辦,在flutter端註冊一個MethodChannel,然後在flutter這邊設定一個接收端。具體實現操作就是這樣了。

如果對具體細節程式碼實現有問題的話可以私信我。q980160988