帶你了解Android的Scheme協(xié)議

最近在一個技術(shù)公眾號里看見Scheme,由于之前沒有接觸過。觸及到了我的知識盲點,于是花了些功夫去了解這個協(xié)議。

URL Scheme 有什么用?使用場景

Scheme 用于從瀏覽器或其他應(yīng)用中啟動本應(yīng)用。也就是說要從其他應(yīng)用中跳轉(zhuǎn)本應(yīng)用的界面或者網(wǎng)頁跳轉(zhuǎn)本應(yīng)用打開特定的界面。

如何定義Scheme協(xié)議

首先我們來看看URL Scheme 的格式
客戶端自定義的 URL 作為從一個應(yīng)用調(diào)用另一個的基礎(chǔ),遵循 RFC 1808 (Relative Uniform Resource Locators) 標(biāo)準(zhǔn)。這跟我們常見的網(wǎng)頁內(nèi)容 URL 格式一樣。
一個普通的 URL 分為幾個部分,scheme、host、port、relativePath、query、fragment(定義一個url包含了你定義的scheme,主機(jī)名或者域名,端口(可選)路徑,查詢條件等)
URL的一般語法格式為:
(帶方括號[]的為可選項):
protocol :// hostname[:port] / path / [;parameters][?query]#fragment

protocol: 協(xié)議也就是你定義的scheme
hostname: 地址域
port:端口
path:路徑
params:參數(shù)

在Android中的用法

在AndroidManifest.xml中定義intent-filter,這里我給出部分代碼

<activity
            android:name=".SchemeTargetActivity"
            android:launchMode="singleTask">
            <!-- 要想在別的App上能成功調(diào)起App,必須添加intent過濾器 -->
            <intent-filter>
                <!-- 協(xié)議部分 可以隨便設(shè)置 還可以加一些host port path 等,協(xié)議規(guī)則越詳細(xì)定位界面更精確,-->
                <!--<data android:scheme="bruce"></data>-->

                <data android:scheme="bruce"
                    android:host="baidu"
                    android:port="8080"
                    android:path="/tieba"
                    ></data>
                <!-- 必須設(shè)置 -->
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <!-- 如果需要外部網(wǎng)頁打開本頁面,還需要設(shè)置這個 -->
                <category android:name="android.intent.category.BROWSABLE" />

            </intent-filter>

 </activity>

為什么設(shè)置singleTask就是為了防止生成多個實例多次啟動這個頁面。如果有傳參,我們可以重寫onNewIntent獲取參數(shù)
下面我給出兩個activity的代碼,注意這里兩個activity來自不同的應(yīng)用。我姑且定為C應(yīng)用,D應(yīng)用。 C調(diào)用D

C應(yīng)用的activity代碼

/**
 * DATE:2018/3/21
 * USER: liuzj
 * DESC:
 * email:liuzj@hi-board.com
 */

public class BActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);


    }

    public void scheme(View view) {
        if (hasApplication()) {
            Toast.makeText(this, "有目標(biāo)界面", Toast.LENGTH_SHORT).show();
            Uri uri = Uri.parse("bruce://baidu:8080/tieba");
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        }else {
            Toast.makeText(this, "沒有目標(biāo)界面", Toast.LENGTH_SHORT).show();
        }

    }

    /**
     * 判斷是否安裝了應(yīng)用
     * @return true 為已經(jīng)安裝
     */
    private boolean hasApplication() {
        PackageManager manager = getPackageManager();
        Intent action = new Intent(Intent.ACTION_VIEW);
        action.setData(Uri.parse("bruce://baidu:8080/tieba"));
        List list = manager.queryIntentActivities(action, PackageManager.GET_RESOLVED_FILTER);
        return list != null && list.size() > 0;
    }
}

D應(yīng)用的activit代碼如下:

/**
 * DATE:2018/3/22
 * USER: liuzj
 * DESC:
 * email:liuzj@hi-board.com
 */

public class SchemeTargetActivity extends AppCompatActivity {

    private static final String TAG = "SchemeTargetActivity";
    private TextView text;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scheme);
        text = (TextView) findViewById(R.id.tv);
        Uri uri = getIntent().getData();
        if (uri != null) {
            dispatchUri(uri);
        } else {
            Log.e(TAG, "Uri is null");
        }
    }

    /**
     * 這里可以做一些獲取你從uri中設(shè)置的信息
     *
     * @param uri
     */
    private void dispatchUri(Uri uri) {

        String uriStr = uri.toString();
        Log.e(TAG, "dispatchUri: 39---" + uriStr);
        Log.e(TAG, "dispatchUri: 40---" + uri.getScheme());
        text.setText(uri.getScheme());
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Uri uri = intent.getData();
        Log.e(TAG, "onNewIntent: 48--------" + uri.toString());
        text.setText(uri.toString());
    }
}

你以為到了這里就要結(jié)束了嗎?怎么可能。我們來玩一玩通過短信鏈接來打開應(yīng)用
把協(xié)議改一改

<activity
            android:name=".SchemeTargetActivity"
            android:launchMode="singleTask">
            <!-- 要想在別的App上能成功調(diào)起App,必須添加intent過濾器 -->
            <intent-filter>
                <!-- 協(xié)議部分 可以隨便設(shè)置 還可以加一些host port path 等,協(xié)議規(guī)則越詳細(xì)定位界面更精確,-->
                <!--<data android:scheme="bruce"></data>-->

                <data
                    android:scheme="bruce"
                    android:host="mytest.com"
                    android:path="/get"
                    >

                </data>
                <!-- 必須設(shè)置 -->
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <!-- 如果需要外部網(wǎng)頁打開本頁面,還需要設(shè)置這個 -->
                <category android:name="android.intent.category.BROWSABLE" />

            </intent-filter>

        </activity>

其實scheme設(shè)置成http也是可以的但是怕用戶會通過瀏覽器去打開,所以為了避免這種問題這里的scheme我們自己寫一個

寫個html

<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="Refresh" content="0;url=bruce://mytest.com/get" />
    <title>Android測試</title>
</head>
<body>
</body>
</html>

即只要點擊網(wǎng)址我們就會重定向去打開app,前端代碼寫的不好,多見諒。實際開發(fā)中前端代碼還可通過超時判斷用戶是否安裝了app,沒有安裝就去下載頁面,安裝了app就可以打開app跳轉(zhuǎn)到該頁面。

最后編輯于
?著作權(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)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評論 25 708
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,692評論 19 139
  • 在Android開發(fā)中,不同Activity之間的跳轉(zhuǎn)和切換是很常見的,這使得APP的內(nèi)容更加豐富,功能更為多樣,...
    登高且賦閱讀 58,161評論 12 61
  • 羅本:從南非到巴西,我等了四年,我是要告訴別人,我失去的東西我一定要拿回來。 這段話當(dāng)然是杜撰的,但是可能確實羅本...
    流殤夕水閱讀 968評論 6 4
  • 6.18日,父親節(jié),我的救贖之路第一步。每天更新!
    酷斗閱讀 202評論 0 0

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