Android 跨應(yīng)用間調(diào)用: URL Scheme

在Android開發(fā)中,不同Activity之間的跳轉(zhuǎn)和切換是很常見的,這使得APP的內(nèi)容更加豐富,功能更為多樣,但是一個應(yīng)用所能包括的功能畢竟有限,在很多的場景下需要跨應(yīng)用調(diào)用,比如在應(yīng)用中跳轉(zhuǎn)到微信支付的頁面,或者使用第三方賬號登陸時跳轉(zhuǎn)到QQ登陸等等。這樣的情況下,要跳轉(zhuǎn)的Activity或者Application是第三方開發(fā)的,很可能不知道要具體跳轉(zhuǎn)到哪一個Activity中,或者直接跳轉(zhuǎn)并不安全,諸如這些問題都需要在跨應(yīng)用間調(diào)用時被周全地考慮到。為了更好地解決這一問題,下面就來介紹Android中的URL Scheme協(xié)議

URL Scheme簡介

Android中的自定義的URL Scheme是一種頁面內(nèi)跳轉(zhuǎn)協(xié)議,也可以被稱為URLRouter,就是通過類似打開網(wǎng)頁的方式去通過路由打開一個Activity,而非直接通過顯式Intent方式去進行跳轉(zhuǎn)。這樣隱式intent的方法跳轉(zhuǎn)好處如下:

  1. 降低耦合性:不需要知道具體要跳轉(zhuǎn)哪個界面,只需要根據(jù)需求,按照約定好的URL路由協(xié)議發(fā)送Intent即可;
  2. 更為安全:不顯示Intent跳轉(zhuǎn),只要是符合協(xié)議的Intent都會有對應(yīng)的Activity來匹配,避免了跳轉(zhuǎn)到不該出現(xiàn)的頁面;
  3. 更為靈活: 有著更為廣泛的應(yīng)用場景,一下場景中都可以使用URL Scheme
  • 服務(wù)器下發(fā)跳轉(zhuǎn)路徑,客戶端根據(jù)服務(wù)器下發(fā)跳轉(zhuǎn)路徑跳轉(zhuǎn)相應(yīng)的頁面
  • H5頁面點擊錨點,根據(jù)錨點具體跳轉(zhuǎn)路徑APP端跳轉(zhuǎn)具體的頁面
  • APP端收到服務(wù)器端下發(fā)的PUSH通知欄消息,根據(jù)消息的點擊跳轉(zhuǎn)路徑跳轉(zhuǎn)相關(guān)頁面
  • APP根據(jù)URL跳轉(zhuǎn)到另外一個APP指定頁面

URL Scheme協(xié)議格式

上文已經(jīng)說過,URL Scheme是就通過類似打開網(wǎng)頁的方式去通過路由打開一個Activity,其協(xié)議格式和我們打開網(wǎng)頁輸入的網(wǎng)址類似。

一個完整的完整的URL Scheme協(xié)議格式由scheme、host、port、path和query組成,其結(jié)構(gòu)如下所示:

<scheme>://<host>:<port>/<path>?<query>

其中scheme既可以是Android中常見的協(xié)議,也可以是我們自定義的協(xié)議。Android中常見的協(xié)議包括content協(xié)議、http協(xié)議、file協(xié)議等,自定義協(xié)議可以使用自定義的字符串,當(dāng)我們啟動第三方的應(yīng)用時候,多是使用自定義協(xié)議。

如下是一個自定義協(xié)議的URI:

xl://goods:8888/goodsDetail?goodsId=10011002

通過上面的路徑 Scheme、Host、port、path、query全部包含:

  • xl,即為Scheme,代表該Scheme 協(xié)議名稱
  • goods,即為Host,代表Scheme作用于哪個地址域
  • 8888,即為port,代表該路徑的端口號
  • goodsDetail,即為path, 代表Scheme指定的頁面
  • goodsId,即為query,代表傳遞的參數(shù)

URL Scheme的使用方法

URL Scheme的使用方法簡要言之就是先在manifest中配置能接受Scheme方式啟動的activity;當(dāng)需要調(diào)用時,將Scheme協(xié)議的URi以Data的形式加入到Intent中,隱式調(diào)用該activity。

1). 在AndroidManifest.xml中對<activity >標(biāo)簽增加<intent-filter>設(shè)置Scheme

<activity android:name=".MainActivity">
    <intent-filter> <!--正常啟動-->
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    <intent-filter> <!--URL Scheme啟動-->
        <!--必有項-->
        <action android:name="android.intent.action.VIEW"/>
        <!--如果希望該應(yīng)用可以通過瀏覽器的連接啟動,則添加該項-->
        <category android:name="android.intent.category.BROWSABLE"/>
        <!--表示該頁面可以被隱式調(diào)用,必須加上該項-->
        <category android:name="android.intent.category.DEFAULT"/>
        <!--協(xié)議部分-->
        <data android:scheme="urlscheme"
            android:host="auth_activity">
    </intent-filter>
    <intent-filter>
        <action   android:name="emms.intent.action.check_authorization"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="emms.intent.category.authorization"/>
    </intent-filter>
</activity>

上面的設(shè)置中可以看到,MainActivity包含多個<intent-filter>設(shè)置,第一個是正常的啟動,也就是在應(yīng)用列表中啟動;第二個是通過URL Scheme方式啟動,其本身也是隱式Intent調(diào)用的一種,不同在于添加了<data>屬性,定義了其接受URL Scheme協(xié)議格式為urlschemel://auth_activity

這里需要說明下,URL Scheme協(xié)議格式中,組成URI的這些屬性在<data >標(biāo)簽中都是可選的 ,但存在如下的依賴關(guān)系:

  • 如果沒有指定scheme,那么host參數(shù)會被忽略
  • 如果沒有指定host,那么port參數(shù)會被忽略
  • 如果scheme和host都沒有指定,path參數(shù)會被忽略

當(dāng)我們將intent對象中的Uri參數(shù)與intent-filter中的<data>標(biāo)簽指定的URI格式進行對比時,我們只對比intent-filter的<data>標(biāo)簽指定的部分,例如:

  • 如果intent-filter中只指定了scheme,那么所有帶有該sheme的URI都能匹配到該intent-filter。
  • 如果intent-filter中只指定了scheme和authority(authority包括host和port兩部分)而沒有指定path,那么所有具有相同scheme和authority的URI都能匹配到該intent-filter,而不用考慮path為何值。
  • 如果intent-filter中同時指定了scheme、authority和path,那么只有具有相同scheme、authority和path的URI才能匹配到該intent-filter。

需要注意的是,intent-filter的<data>標(biāo)簽在指定path的值時,可以在里面使用通配符*,起到部分匹配的效果。

2). 使用URL啟動Activity

  Uri data = Uri.parse("urlschemel://auth_activity");
  Intent intent = new Intent(Intent.ACTION_VIEW,data);
  //保證新啟動的APP有單獨的堆棧,如果希望新啟動的APP和原有APP使用同一個堆棧則去掉該項
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  try {
    startActivityForResult(intent, RESULT_OK);
  } catch (Exception e) {
    e.printStackTrace();
    Toast.makeText(MainActivity.this, "沒有匹配的APP,請下載安裝",Toast.LENGTH_SHORT).show();
  }

當(dāng)然可以在網(wǎng)頁中調(diào)用

<a href="urlschemel://auth_activity">打開新的應(yīng)用</a>

或者是在JS中調(diào)用

window.location = "urlschemel://auth_activity";

3.)如何判斷URL Scheme是否有效

boolean checkUrlScheme(Intent intent){
    PackageManager packageManager = getPackageManager();
    List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
    return !activities.isEmpty();
}

將子APP在Home Launcher中隱藏

有時候需要把一些輔助性的、較為獨立的APP在Home Launcher中隱藏起來,只允許一些特定的APP調(diào)用。這個時候,我們可以利用URL Scheme協(xié)議來做到這一點,設(shè)置AndroidManifest.xml中對<activity >標(biāo)簽如下

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <!--表示該頁面可以被隱式調(diào)用,必須加上該項-->
        <category android:name="android.intent.category.DEFAULT"/>
        <!--協(xié)議部分-->
        <data android:scheme="urlscheme"
            android:host="auth_activity">
    </intent-filter>
</activity>

因為Home Launcher列出的應(yīng)用圖標(biāo)要求必須有Activity同時滿足

  • <action android:name="android.intent.action.MAIN"/>
  • <category android:name="android.intent.category.LAUNCHER"/>

上面的配置中有多余的category和data限制存在,所以并不匹配,不會在Home Launcher出現(xiàn),但是可以使用URL Scheme來啟動。

  Uri data = Uri.parse("urlschemel://auth_activity");
  Intent intent = new Intent(Intent.ACTION_MAIN,data);
  intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

這樣就可以將一組APP設(shè)置一個統(tǒng)一的入口,然后根據(jù)實際需要在調(diào)用不同子APP,即所謂的APP業(yè)務(wù)組件化URL Scheme在其中有著重要的作用,更進一步討論會在以后的文章中呈現(xiàn),敬請期待。

參考文獻:
http://blog.csdn.net/iispring/article/details/48481793
http://blog.csdn.net/hb707934728/article/details/53196419
http://www.cnblogs.com/whoislcj/p/5825333.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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