DeepLink用法及源码解析
終于建了一個自己個人小站:https://huangtianyu.gitee.io,以后優先更新小站博客,歡迎進站,O(∩_∩)O~~
1. 簡介
DeepLink官網上有這樣的解釋:
When a clicked link or programmatic request invokes a web URI intent, the Android system tries each of the following actions, in sequential order, until the request succeeds: 1. Open the user's preferred app that can handle the URI, if one is designated. 2. Open the only available app that can handle the URI. 3. Allow the user to select an app from a dialog.Follow the steps below to create and test links to your content. You can also use the [App Links Assistant](https://developer.android.com/studio/write/app-link-indexing.html) in Android Studio to add Android App Links翻譯后的意思就是:
當單擊鏈接或編程請求調用Web URI意圖時,Android系統按順序依次嘗試以下每一個操作,直到請求成功為止:
1. 打開用戶首選的應用程序,它可以處理URI,如果指定的話。
2. 打開可以處理URI的惟一可用應用程序。
3. 允許用戶從對話框中選擇應用程序。
意思也就是用戶可以自己寫一串字符串,系統會對該字符串進行解析,然后調起注冊過相應scheme的應用,如果有多個注冊了,那么就會彈出對話框讓用戶選擇。
2. 用法
Google官方給了一個樣例:search-samples
以下根據Android官方的deep-linking的樣例來說明如何使用。
在上面有兩個
<intent-filter>...<data android:scheme="https" android:host="www.example.com" /><data android:scheme="app" android:host="open.my.app" /> </intent-filter>上面在同一個
@Override public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent intent = getIntent();String action = intent.getAction();Uri data = intent.getData(); }getIntent可以在Activity的生命周期的任何時段進行獲取,不過一般別人應用要調你應用,肯定都是希望進入你的應用某個界面,或實現某個功能。其他應用會把該傳的信息都傳給你,最好的解析地方肯定是onCreate(或onStart但onStart還是會晚一些)。對于這個官方給了以下建議:
* The deep link should take users directly to the content, without any prompts, interstitial pages, or logins. Make sure that users can see the app content even if they never previously opened the application. It is okay to prompt users on subsequent interactions or when they open the app from the Launcher. This is the same principle as the [first click free](https://support.google.com/webmasters/answer/74536?hl=en) experience for web sites. * Follow the design guidance described in [Navigation with Back and Up](https://developer.android.com/design/patterns/navigation.html) so that your app matches users' expectations for backward navigation after they enter your app through a deep link意思就是:
1. 打開應用后應該直接到內容,不要有任何提示,間接的頁面,或登錄。確保用戶可以看到應用程序的內容,即使他們以前從未打開過應用程序。可以在隨后的交互中提示用戶,或者在啟動程序中打開應用程序。這與網站第一次點擊免費體驗的原理是相同的。
2. 遵循導航與后退和向上描述的設計指南,使您的應用程序與用戶通過向后鏈接進入您的應用程序的深度導航的期望相符。
實現上面代碼后就可以進行測試了。在測試時可以使用adb的shell命令進行測試,語法格式如下:
$ adb shell am start-W -a android.intent.action.VIEW -d <URI> <PACKAGE>例如我們上面的例子就可以采用如下方式進行打開:
$ adb shell am start-W -a android.intent.action.VIEW-d "example://gizmos" com.example.android上面的intent也可以通過瀏覽器里面的網頁進行設置,現在瀏覽器都會解析這個intent然后調起對應的應用,即可以直接在網頁中調起應用。
DeepLink使得開發網站和自己的App能很好的相互交互。而且一個intent字符串也好發送,比如你想推廣你的App,你就可以把這個intent發給廣告商,然后點擊的時候就把這個intent給手機瀏覽器,通過瀏覽器調起你自己的應用。這個最好的應用還在搜索上,在搜索的時候,當用戶搜到對應內容的時候,現在一般都是跳網站。但是如果有DeepLink,那么就可以直接通過DeepLink的intent直接跳轉到你自己的App,這既方便了用戶,也方便了開發者。
3. DeepLink原理分析
3.1 DeepLinkDispatch框架
DeepLink采用的是Airbnb推出的DeepLinkDispatch框架,該DeepLinkDispatch是一個以注解形式來實現dispatch跳轉的框架。這個是它的簡單介紹README.md。
3.2 Dispatch框架使用例子
@DeepLink("foo://example.com/deepLink/{id}") public class MainActivity extends Activity {@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Intent intent = getIntent();if (intent.getBooleanExtra(DeepLink.IS_DEEP_LINK, false)) {Bundle parameters = intent.getExtras();String idString = parameters.getString("id");// Do something with idString}} }多個
//多filter的注解 @DeepLink({"foo://example.com/deepLink/{id}", "foo://example.com/anotherDeepLink"}) public class MainActivity extends Activity {@Override protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Intent intent = getIntent();if (intent.getBooleanExtra(DeepLink.IS_DEEP_LINK, false)) {Bundle parameters = intent.getExtras();String idString = parameters.getString("id");// Do something with idString}} }某個方法的注解:
@DeepLink("foo://example.com/methodDeepLink/{param1}") public static Intent intentForDeepLinkMethod(Context context, Bundle extras) {Uri.Builder uri = Uri.parse(extras.getString(DeepLink.URI)).buildUpon();return new Intent(context, MainActivity.class).setData(uri.appendQueryParameter("bar", "baz").build()).setAction(ACTION_DEEP_LINK_METHOD); }上面的注解相當于DeepLink中在manifest中的Activity標簽下注冊的
public class DeepLinkReceiver extends BroadcastReceiver {private static final String TAG = "DeepLinkReceiver";@Override public void onReceive(Context context, Intent intent) {String deepLinkUri = intent.getStringExtra(DeepLinkHandler.EXTRA_URI);if (intent.getBooleanExtra(DeepLinkHandler.EXTRA_SUCCESSFUL, false)) {Log.i(TAG, "Success deep linking: " + deepLinkUri);} else {String errorMessage = intent.getStringExtra(DeepLinkHandler.EXTRA_ERROR_MESSAGE);Log.e(TAG, "Error deep linking: " + deepLinkUri + " with error message +" + errorMessage);}} }public class YourApplication extends Application {@Override public void onCreate() {super.onCreate();IntentFilter intentFilter = new IntentFilter(DeepLinkHandler.ACTION);//使用應用內廣播注冊的,不用擔心其他應用收到 LocalBroadcastManager.getInstance(this).registerReceiver(new DeepLinkReceiver(), intentFilter);} }下面就來分析下它的原理。
3.3 源碼剖析
3.3.1 根據注解生成對應class文件
在AS點擊build后即可生成對應的class文件,主要的文件有以下幾個:
在DeepLinkDispatch框架中主要是通過DeepLinkDelegate代理來處理傳來的Uri,在DeepLinkDelegate中主要是dispatchFrom這個方法來處理Uri。代碼如下:
1. 收下根據getIntent.getData()即可獲取到對應的uri。
2. 然后通過DeepLinkLoader.load()來加載注冊的uri。代碼如下
調用loader.parseUri去解析Uri,解析完成后返回的是DeepLinkEntry來供我們使用。
解析Uri中的key-value對,代碼仍然在dispatchFrom中。
其中DeepLinkUri.getParameters代碼如下:
然后調用了該類的parseParameters獲取patterns集合。
從DeepLink的intent中獲取的就是key,具體跳轉的內容就是value。
5. DeepLinkUri.queryParameterNames
通過queryParameterNames就把真實的Uri解析成對應的注解了,之后就會進行分發邏輯了。
6. 具體分發邏輯
6.1 首先生成Intent對象
6.2 setAction和data,通過以上將action和data放入Intent中。
6.3 處理Bundle。
6.4 調用callingActivity。
6.5 startActivity
6.6 createResultAndNotify
頁面路由的框架大多類似,主要邏輯是:先注冊下需要路由的地址頁及對應的uri,然后通過uri調起時有控制中樞攔截后進行匹配,當匹配成功后就執行跳轉,在匹配的時候uri后面可以跟上所需要傳輸的數據,然后在接收端進行解析即可完成數據的交互。通過以上步驟就完成了DeepLink調起應用頁面的操作了,具體代碼稍后再貼。
4. 總結
創建你自己的AppLinks,可以參考如下Create Deep Links to App Content。后續我會專門寫篇文章介紹下AppLinks及其用法。
總結
以上是生活随笔為你收集整理的DeepLink用法及源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图形系统中的仿射变换
- 下一篇: 产品经理如何基于需求迭代产品(下篇3):