scheme協(xié)議定義
scheme 是一種頁面之間跳轉(zhuǎn)的協(xié)議,不僅可以用于App之間進(jìn)行跳轉(zhuǎn),還可以用于 H5 頁面跳轉(zhuǎn)到app頁面。
通過scheme協(xié)議,服務(wù)器可以定制化告訴App跳轉(zhuǎn)那個(gè)頁面,可以通過通知欄消息定制化跳轉(zhuǎn)頁面,可以通過H5頁面跳轉(zhuǎn)頁面等。
無論Android還是IOS,都可以通過在H5頁面中打開 scheme 協(xié)議的地址,從而打開本地app。
- 蘋果手機(jī)中的APP都有一個(gè)沙盒,APP就是一個(gè)信息孤島,相互是不可以進(jìn)行通信的。但是iOS的APP可以注冊(cè)自己的URL Scheme,URL Scheme是為方便app之間互相調(diào)用而設(shè)計(jì)的。
注意:
URL Scheme必須能唯一標(biāo)識(shí)一個(gè)APP,如果你設(shè)置的URL Scheme與別的APP的URL Scheme沖突時(shí),你的APP不一定會(huì)被啟動(dòng)起來。因?yàn)楫?dāng)你的APP在安裝的時(shí)候,系統(tǒng)里面已經(jīng)注冊(cè)了你的URL Scheme。
URL Scheme應(yīng)用場景:
客戶端應(yīng)用可以向操作系統(tǒng)注冊(cè)一個(gè) URL scheme,該 scheme 用于從瀏覽器或其他應(yīng)用中啟動(dòng)本應(yīng)用。通過指定的 URL 字段,可以讓應(yīng)用在被調(diào)起后直接打開某些特定頁面,比如商品詳情頁、活動(dòng)詳情頁等等。也可以執(zhí)行某些指定動(dòng)作,如完成支付等。也可以在應(yīng)用內(nèi)通過 html 頁來直接調(diào)用顯示 app 內(nèi)的某個(gè)頁面。綜上URL Scheme使用場景大致分以下幾種:
- 服務(wù)器下發(fā)跳轉(zhuǎn)路徑,客戶端根據(jù)服務(wù)器下發(fā)跳轉(zhuǎn)路徑跳轉(zhuǎn)相應(yīng)的頁面
- H5頁面點(diǎn)擊錨點(diǎn),根據(jù)錨點(diǎn)具體跳轉(zhuǎn)路徑APP端跳轉(zhuǎn)具體的頁面
- APP端收到服務(wù)器端下發(fā)的PUSH通知欄消息,根據(jù)消息的點(diǎn)擊跳轉(zhuǎn)路徑跳轉(zhuǎn)相關(guān)頁面
- APP根據(jù)URL跳轉(zhuǎn)到另外一個(gè)APP指定頁面
scheme協(xié)議格式
scheme 協(xié)議定義和 http 協(xié)議類似,都是標(biāo)準(zhǔn)的 URI 結(jié)構(gòu)。
[scheme:][//host:port][path][?query][#fragment]
scheme : 協(xié)議名稱 - 必須
host : 協(xié)議地址 - 必須
port : 協(xié)議的端口,可以不填
path : 協(xié)議路徑,可用 / 連接多個(gè)
query : 攜帶的參數(shù)可用 & 連接多個(gè)
fragment : 錨點(diǎn)
例子
下面看一個(gè)例子:
wexin://tencent.com:8080/dl/news/open?data=902323¶ms=test
- weixin : 協(xié)議名稱
- tencent.com : 域名
- 8080 : 端口
- /dl/news/open : 頁面的路徑
- data,params : 傳遞的參數(shù)
URL Scheme如何使用
Android配置
- 在AndroidManifest.xml中對(duì)
<activity />
標(biāo)簽增加<intent-filter />
設(shè)置Scheme(只有第一步是必須配置的)
在MainAcrtivity
<activity
android:name="com.app.MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:windowsoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<!--協(xié)議部分,隨便設(shè)置-->
<!-- 下面的scheme地址為 xl://goods -->
<data android:scheme="xl"
android:host="goods"/>
<!--下面這幾行也必須得設(shè)置-->
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
在其他Activity
Java
<activity
android:name=".GoodsDetailActivity"
android:theme="@style/AppTheme">
<!--要想在別的App上能成功調(diào)起App,必須添加intent過濾器-->
<intent-filter>
<!--協(xié)議部分,隨便設(shè)置-->
<!-- 下面的scheme地址為 xl://goods:8888/goodsDetail -->
<data android:scheme="xl"
android:host="goods"
android:path="/goodsDetail"
android:port="8888"/>
<!--下面這幾行也必須得設(shè)置-->
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
</intent-filter>
</activity>
注釋:
需要配置能被js調(diào)起,一定要配置下面這句
<category android:name="android.intent.category.BROWSABLE"/>
Java
<!--必有項(xiàng)-->
<action android:name="android.intent.action.VIEW" />
<!--表示該頁面可以被隱式調(diào)用,必須加上該項(xiàng)-->
<category android:name="android.intent.category.DEFAULT" />
<!--如果希望該應(yīng)用可以通過瀏覽器的連接啟動(dòng),則添加該項(xiàng)-->
<category android:name="android.intent.category.BROWSABLE" />
擴(kuò)展:
上面的 data 節(jié)點(diǎn)中可以包含下面的信息來對(duì)相應(yīng)的scheme進(jìn)行過濾,一般需要配置 scheme 和 host。
<data
android:scheme=""
android:host=""
android:port=""
android:path=""
android:mimeType=""
android:pathPattern=""
android:pathPrefix=""
android:ssp=""
android:sspPattern=""
android:sspPrefix=""
/>
然后在相應(yīng)的 activity 可以獲取 uri 中參數(shù)。
Java
public class DeepLinkActivity extends AppCompatActivity {
private static final String TAG = "DeepLinkActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = getIntent();
Log.e(TAG, "scheme:" + intent.getScheme());
Uri uri = intent.getData();
Log.e(TAG, "scheme: " + uri.getScheme()); // 獲取 scheme 名稱
Log.e(TAG, "host: " + uri.getHost()); // 獲取 scheme 的host
Log.e(TAG, "path: " + uri.getPath()); // 獲取 scheme 的路徑
Log.e(TAG, "queryString: "+ uri.getQuery()); // 獲取 scheme 的參數(shù),?后面的部分
Log.e(TAG, "queryParameter: " + uri.getQueryParameter("param")); // 獲取 scheme 中的 param 參數(shù)
}
}
其中的 intent 實(shí)例有下面的方法可以獲取相應(yīng)的 scheme 信息:
- getScheme() :獲取Uri中的scheme名稱:[scheme:]
- getSchemeSpecificPart() :獲取Uri中的scheme-specific-part:部分:[//host:port][path]
- getFragment() :獲取Uri中的Fragment部分:[#fragment]
- getAuthority() :獲取Uri中Authority部分:[//host:port]
- getPath() :獲取Uri中path部分:[path]
- getQuery() :獲取Uri中的query部分:[?query]
- getHost() :獲取Authority中的Host字符串
- getPost() :獲取Authority中的Port字符串
- List< String> getPathSegments() :依次提取出Path的各個(gè)部分的字符串,以字符串?dāng)?shù)組的形式輸出
- getQueryParameter(String key) :獲取query部分中 key 對(duì)應(yīng)的參數(shù)值
- 注意事項(xiàng)
正常情況下,以上配置后,就可以正常進(jìn)行跳轉(zhuǎn)了,但是在安卓上,還需要進(jìn)行一步配置,如果你的應(yīng)用被其注冊(cè)過的外部 url 調(diào)起,如果要在現(xiàn)有的 MainActivity 中監(jiān)聽傳入的 intent,那么需要在AndroidManifest.xml中將 MainActivity 的launchMode設(shè)置為singleTask
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
- 問題:當(dāng)app在后臺(tái)運(yùn)行,用scheme鏈接打開,url獲取為null,不會(huì)跳轉(zhuǎn)到對(duì)應(yīng)頁面
原因:
因?yàn)閞eact native只配置了一個(gè)activity,整個(gè)應(yīng)用都是在這個(gè)activity里運(yùn)行的。當(dāng)app尚未啟動(dòng),由scheme喚起時(shí),activity會(huì)執(zhí)行onCreate生命周期鉤子,初始化intent,此時(shí)你將會(huì)得到全新的url:null。當(dāng)app已經(jīng)運(yùn)行在后臺(tái),由scheme喚起時(shí),activity不會(huì)執(zhí)行onCreate方法,你得到的url還是舊值:null。
在android/app/src/main/java/com/lka/MainActivity.java的最下面添加:
@Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
setIntent(intent);
}
注:
singTask 啟動(dòng)模式在從后臺(tái)喚醒時(shí)它的生命周期:
如果IntentActivity處于任務(wù)棧的頂端,也就是說之前打開過的Activity,現(xiàn)在處于
onPause
onStop 狀態(tài)的話,
其他應(yīng)用再發(fā)送Intent的話,執(zhí)行順序?yàn)椋?/p>
onNewIntent
onRestart
onStart
onResume
IOS配置
只需要配置info.plist 文件,只需要配置URL Schemes就可以了,identifier是可選配置
H5打開app測(cè)試
自己編寫一個(gè)html頁面,發(fā)到微信,用qq瀏覽器打開,點(diǎn)擊"打開app"按鈕,會(huì)提示是否“允許”,點(diǎn)擊允許,自動(dòng)打開app。
如果打開的 scheme 在本地沒有對(duì)應(yīng)的 app,則點(diǎn)擊連接不會(huì)反應(yīng)。
例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div >
<a href="app://www.aaa.com/list">打開app</a>
</div>
</body>
</html>
注:
1.這種的缺點(diǎn)是只能用qq瀏覽器打開
2.瀏覽器打開如下html代碼,即可啟動(dòng)App
<a href="myscheme://">打開app</a>
用原生代碼獲取參數(shù)
瀏覽器打開App時(shí),如何獲取網(wǎng)頁帶過來的數(shù)據(jù)(用原生代碼獲取)
Html
<a href="myscheme://?arg0=0&arg1=1">打開app</a>
Java
(1).假如你是通過瀏覽器打開這個(gè)網(wǎng)頁的,那么獲取數(shù)據(jù)的方式為:
Uri uri = getIntent().getData();
String test1= uri.getQueryParameter("arg0");
String test2= uri.getQueryParameter("arg1");
(2)如果使用webview訪問該網(wǎng)頁,獲取數(shù)據(jù)的操作為:
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Uri uri=Uri.parse(url);
if(uri.getScheme().equals("myscheme")){
String arg0=uri.getQueryParameter("arg0");
String arg1=uri.getQueryParameter("arg1");
}else{
view.loadUrl(url);
}
return true;
}
});
、
從APP上用原生代碼調(diào)用實(shí)現(xiàn)跳轉(zhuǎn)(沒有測(cè)試)
android調(diào)用
Java
Intent action = new Intent(Intent.ACTION_VIEW);
StringBuilder builder = new StringBuilder();
builder.append("caishilive://caishi:8080/loadtooldetail?tool_id=100");
action.setData(Uri.parse(builder.toString()));
startActivity(action);
或
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("xl://goods:8888/goodsDetail?goodsId=10011002"));
startActivity(intent);
ios調(diào)用
Java
NSString *url = @"opengs://";
// NSString *url = @"opengs://com.opengs.www";
if ([[UIApplication sharedApplication]
canOpenURL:[NSURL URLWithString:url]])
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}
else
{
NSLog(@"can not open URL scheme opengs");
}
URL Scheme是否有效
跳轉(zhuǎn)前要判斷一下該URL Scheme是否有效
Html
private boolean schemeValid() {
PackageManager manager = mContext.getPackageManager();
Intent action = new Intent(Intent.ACTION_VIEW);
action.setData(Uri.parse("caishilive://caishi:8080/loadtooldetail?tool_id=100"));
List list = manager.queryIntentActivities(action, PackageManager.GET_RESOLVED_FILTER);
return list != null && list.size() > 0;
}
react-native獲取url 見下節(jié) http://t.csdn.cn/h40sw
附錄:常見應(yīng)用的URL Scheme
1、記錄使用過的URL Scheme
名稱 | URL Scheme | 對(duì)應(yīng)的普通鏈接 |
---|---|---|
witter發(fā)消息 | Twitter://messages/compose?text=[yourText] | https://twitter.com/messages/compose?text=[yourText] |
Twitter發(fā)動(dòng)態(tài) | twitter://intent/tweet?text=[yourText] | https://twitter.com/intent/tweet?text=[yourText] |
打開Email | mailto:?body=[yourText] | |
給某人發(fā)Email | mailto:[emailAddress]?body=[yourText] | |
發(fā)短信SMS | sms:body=hello(AOS)sms:&body=hello(IOS) | |
whatsapp發(fā)消息 | whatsapp://send?text=[yourText] | |
fbmessenger發(fā)消息(分享鏈接) | fb-messenger://share/?link=[yourShareURL] | https://www.facebook.com/dialog/send?display=popup&app_id=[yourAppID]&link=[yourShareURL]&redirect_uri=[yourShareURL] |
fbmessenger發(fā)消息(指定對(duì)象) | fb-messenger://m.me/[yourPageID](通用) fb-messenger-public://user-thread/[yourPageID](IOS) | https://www.messenger.com/t/[yourPageID] / https://m.me/[yourPageID] |
fb打開相關(guān)主頁 | fb://page/[yourPageID] | https://www.facebook.com/[yourPageID] |
Amazon打開產(chǎn)品詳情頁 | com.amazon.mobile.shopping://www.amazon.com/dp/[yourAsin] | https://www.amazon.com/dp/[yourAsin] |
打開App Store中應(yīng)用詳情頁 | itms-apps://itunes.apple.com/cn/app/[yourAppID] | https://itunes.apple.com/cn/app/[yourAppID] |
打電話 | tel:[telephoneNumber] |
2、系統(tǒng)默認(rèn)應(yīng)用
名稱 | URL Scheme | Bundle Identifier |
---|---|---|
Safari | http:// | |
maps | http://maps.google.com | |
Phone | tel:// | |
SMS | sms:// | |
mailto:// | ||
iBooks | ibooks:// | |
App Store | itms-apps://itunes.apple.com | |
Music | music:// | |
Videos | videos:// | |
3、常用第三方軟件 |
名稱 | URL Scheme | Bundle Identifier |
---|---|---|
mqq:// | ||
微信 | weixin:// | |
騰訊微博 | TencentWeibo:// | |
淘寶 | taobao:// | |
支付寶 | alipay:// | |
微博 | sinaweibo:// | |
weico微博 | weico:// | |
QQ瀏覽器 | mqqbrowser:// | com.tencent.mttlite |
uc瀏覽器 | dolphin:// | com.dolphin.browser.iphone.chinese |
歐朋瀏覽器 | ohttp:// | com.oupeng.mini |
搜狗瀏覽器 | SogouMSE:// | com.sogou.SogouExplorerMobile |
百度地圖 | baidumap:// | com.baidu.map |
Chrome | googlechrome:// | |
優(yōu)酷 | youku:// | |
京東 | openapp.jdmoble:// | |
人人 | renren:// | |
美團(tuán) | imeituan:// | |
1號(hào)店 | wccbyihaodian:// | |
我查查 | wcc:// | |
有道詞典 | yddictproapp:// | |
知乎 | zhihu:// | |
點(diǎn)評(píng) | dianping:// | |
微盤 | sinavdisk:// | |
豆瓣fm | doubanradio:// | |
網(wǎng)易公開課 | ntesopen:// | |
名片全能王 | camcard:// | |
QQ音樂 | qqmusic:// | |
騰訊視頻 | tenvideo:// | |
豆瓣電影 | doubanmovie:// | |
網(wǎng)易云音樂 | orpheus:// | |
網(wǎng)易新聞 | newsapp:// | |
網(wǎng)易應(yīng)用 | apper:// | |
網(wǎng)易彩票 | ntescaipiao:// | |
有道云筆記 | youdaonote:// | |
多看 | duokan-reader:// | |
全國空氣質(zhì)量指數(shù) | dirtybeijing:// | |
百度音樂 | baidumusic:// | |
下廚房 | xcfapp:// |
原文鏈接:https://blog.csdn.NET/weixin_42895400/article/details/87799262
https://blog.csdn.net/wangkeke1860/article/details/49850997