ionic應(yīng)用兼容Android9與10的經(jīng)歷

水平有限,如果存在問(wèn)題歡迎大家訪問(wèn)我的博客批評(píng)指正.

ionic應(yīng)用兼容android9的經(jīng)歷

文中Android P就是Android 9,這一塊原因大家自己google.

突然,給用戶(hù)開(kāi)發(fā)的App無(wú)法在Android9與Android10上正常使用,甚至10上面無(wú)法進(jìn)行安裝,不得不拉取很早之前的代碼進(jìn)行問(wèn)題排查.

此前是ionic4與Angular的混合開(kāi)發(fā)項(xiàng)目,所以我首先想到的事Android9以上api進(jìn)行了變動(dòng),如果是權(quán)限好處理,如果是api并且涉及到第三方cordova插件那么就有點(diǎn)麻煩,不能等到插件作者自己更新的情況下我們只能自己基于源碼去修改.就像我之前想找一個(gè)支持中文TTS的cordova插件,網(wǎng)上能找到的幾乎全部是英文的.最后只能自己封裝(中文TTS插件),所以如果了解cordova插件原理及懂一些java知識(shí),第二點(diǎn)也不麻煩.

好在我們這次的問(wèn)題出在自己本身身上,就是那種好解決的,我們現(xiàn)在我們添加的android平臺(tái)源碼里面改動(dòng).

問(wèn)題解決

Apache HTTP client 類(lèi)丟失

將 compileSdkVersion 升級(jí)到 28(Android9) 之后,如果在項(xiàng)目中用到了 Apache HTTP client 的相關(guān)類(lèi),就會(huì)拋出找不到這些類(lèi)的錯(cuò)誤。這是因?yàn)楣俜揭呀?jīng)啟動(dòng)類(lèi)加載器中將其移除,如果仍然需要使用 Apache HTTP client,可以在AndroidManifest.xml文件中加入:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

具體再application節(jié)點(diǎn)下.

網(wǎng)絡(luò)無(wú)法連接

CLEARTEXT communication to life.115.com not permitted by network security policy

原因: Android P以后 限制了明文流量的網(wǎng)絡(luò)請(qǐng)求,非加密的流量請(qǐng)求都會(huì)被系統(tǒng)禁止掉

方案一

既然不讓用明文,那我們將http換成https就可以解決問(wèn)題了,這也是以后的趨勢(shì),大勢(shì)所趨.

方案二

考慮到有些請(qǐng)求是和客戶(hù)打交道,太麻煩,那么還有其他解決辦法.

在資源文件新建xml目錄(res下建立xml目錄,一般自己存在),新建一個(gè)文件network_security_config.xml(一般也存在),添加或修改原有內(nèi)容:

全部放開(kāi)

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true" />
</network-security-config>

或者允許部分:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <!--<base-config cleartextTrafficPermitted="true" />-->
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">sample.domain.com</domain>
    </domain-config>
</network-security-config>

然后在AndroidManifest.xml的application節(jié)點(diǎn)屬性上添加:

<application
    ...
    android:networkSecurityConfig="@xml/network_security_config">

其它方案:

  1. 不要使用太高的targetversion,26以及以前的版本還是可以正常訪問(wèn)http.

  2. 在AndroidMainifest的加入android:usesCleartextTraffic

<application
    android:usesCleartextTraffic="true"/>

Android 9使用前臺(tái)服務(wù)報(bào)異常

原因:在安卓P版本之后,必須要授予FOREGROUND_SERVICE權(quán)限,才能夠使用前臺(tái)服務(wù),否則會(huì)拋出異常。

那就在AndroidManifest.xml中manifest添加權(quán)限唄:

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

到這一步,我在Android P的問(wèn)題其實(shí)已經(jīng)解決了,Android 10的一會(huì)再說(shuō),但是我還是把我解決過(guò)程中網(wǎng)上大家提的其他問(wèn)題列舉一下.

劉海屏適配(原生代碼)

比如我們需要全屏顯示的時(shí)候,Google在api28中已經(jīng)做了處理。如下面代碼:

requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    //android p 劉海屏適配
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {//加版本判斷,28以下會(huì)報(bào)錯(cuò)
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.layoutInDisplayCutoutMode
                = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
        getWindow().setAttributes(lp);
    }

layoutInDisplayCutoutMode值說(shuō)明:

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT:默認(rèn)情況下,全屏窗口不會(huì)使用到挖孔區(qū)域,非全屏窗口可正常使用挖孔區(qū)域。
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS:窗口聲明使用挖孔區(qū)域
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES:窗口聲明使用挖孔區(qū)域
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER:窗口聲明不使用挖孔區(qū)域

限制靜態(tài)廣播的接收

升級(jí)安卓P之后,隱式廣播將會(huì)被全面禁止,在AndroidManifest中注冊(cè)的Receiver將不能夠生效,如果你的清單文件中有如下的監(jiān)聽(tīng)器:

<receiver android:name="com.yanghaoyi.receiver.UpdateReceiver">
        <intent-filter>
            <action android:name="com.yanghaoyi.action.ACTION_UPDATE" />
        </intent-filter>
</receiver>

你需要移除上面的代碼,并在應(yīng)用中進(jìn)行動(dòng)態(tài)注冊(cè),例如:

private void registerReceiver(){
    myReceiver = new MyReceiver();
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(TOAST_ACTION);
    registerReceiver(myReceiver, intentFilter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(myReceiver);
}

非全屏透明Activity禁用設(shè)置orientation

java.lang.IllegalStateException: Only fullscreen activities can request orientation

非全屏透明頁(yè)面不允許設(shè)置方向,否則會(huì)拋異常.

如果一個(gè)Activity的Style符合下面三個(gè)條件之一,認(rèn)為不是“fullscreen”:

“windowIsTranslucent”為true;

“windowIsTranslucent”為false,但“windowSwipeToDismiss”為true;

“windowIsFloating“為true;

解決方案:android:windowIsTranslucent設(shè)置為false。

ionic兼容優(yōu)化

上面我采用了添加xml打開(kāi)明文訪問(wèn),前臺(tái)權(quán)限以及Apache HTTP client 類(lèi)丟失解決方案,每次添加完平臺(tái)都得改一次代碼,是不是相當(dāng)不方便,那么ionic本身的config.xml就派上用場(chǎng)了.

將上文提到的network_security_config.xml文件放在resources/android/xml目錄下.

并且在config.xml的widget標(biāo)簽上添加屬性:

<widget ... xmlns:android="http://schemas.android.com/apk/res/android">
...
</widget>

在config.xml的android平臺(tái)配置里面添加:

<platform name="android">
        <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
            <application android:networkSecurityConfig="@xml/network_security_config" />
        </edit-config>
        <config-file parent="/manifest" target="app/src/main/AndroidManifest.xml">
            <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
        </config-file>
        <config-file parent="/manifest/application" target="app/src/main/AndroidManifest.xml">
            <uses-library android:name="org.apache.http.legacy" android:required="false" />
        </config-file>
 </platform>

然后就不用擔(dān)心每次刪除平臺(tái)后再次添加重新修改代碼了.

Android 10的一些問(wèn)題

在Android 10的一些手機(jī)上,比如華為,不知道是因?yàn)槭謾C(jī)自己設(shè)置的原因還是android升級(jí)了,不允許安裝非正式版app,所以我們?cè)诎l(fā)送測(cè)試版(debug)版本的apk安裝會(huì)失敗,因?yàn)橛袝r(shí)候并不是我們都是整個(gè)開(kāi)發(fā)完上應(yīng)用市場(chǎng)的,客戶(hù)可能需要提前體驗(yàn)或者看效果.而每個(gè)手機(jī)關(guān)閉設(shè)置又不一樣,反正華為的沒(méi)找見(jiàn),那么我們發(fā)布時(shí)應(yīng)該將我們的app進(jìn)行正式簽名,防止客戶(hù)安裝失敗.

而且簽名也是我們app正式發(fā)布的必須流程.

具體簽名流程請(qǐng)參考我的Android簽名一文.

INSTALL_FAILED_NO_MATCHING_ABIS(虛擬機(jī)的問(wèn)題)

有時(shí)候我們使用虛擬機(jī)測(cè)試應(yīng)用是可能因?yàn)榧軜?gòu)的問(wèn)題,報(bào)錯(cuò):
Installation failed with message Failed to finalize session : INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113. It is possible that this issue is resolved by uninstalling an existing version of the apk if it is present, and then re-installing.

解決方案:
在Android studio 的build.gradle文件里(model:app):在android中添加以下內(nèi)容:

android{
    ...
    splits {
        abi {
            enable true
            reset()
            include 'x86', 'armeabi-v7a','x86_64'
            universalApk true
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容