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的樣例來說明如何使用。

<activity
    android:name="com.example.android.GizmosActivity"
    android:label="@string/title_gizmos" >
    <intent-filter android:label="@string/filter_view_http_gizmos">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Accepts URIs that begin with "http://www.example.com/gizmos” -->
        <data android:scheme="http"
              android:host="www.example.com"
              android:pathPrefix="/gizmos" />
        <!-- note that the leading "/" is required for pathPrefix-->
    </intent-filter>
    <intent-filter android:label="@string/filter_view_example_gizmos">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <!-- Accepts URIs that begin with "example://gizmos” -->
        <data android:scheme="example"
              android:host="gizmos" />
    </intent-filter>
</activity>

在上面有兩個

<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文件,主要的文件有以下幾個:
class.png
在DeepLinkDispatch框架中主要是通過DeepLinkDelegate代理來處理傳來的Uri,在DeepLinkDelegate中主要是dispatchFrom這個方法來處理Uri。代碼如下:
DeepLinkResult.png
1. 收下根據getIntent.getData()即可獲取到對應的uri。
2. 然後通過DeepLinkLoader.load()來加載註冊的uri。代碼如下
load.png

  1. 調用loader.parseUri去解析Uri,解析完成後返回的是DeepLinkEntry來供我們使用。

  2. 解析Uri中的key-value對,代碼仍然在dispatchFrom中。
    parseUri.png

其中DeepLinkUri.getParameters代碼如下:
getParameters.png

然後調用了該類的parseParameters獲取patterns集合。
parseParameters.png

從DeepLink的intent中獲取的就是key,具體跳轉的內容就是value。
5. DeepLinkUri.queryParameterNames
通過queryParameterNames就把真實的Uri解析成對應的註解了,之後就會進行分發邏輯了。
6. 具體分發邏輯
dispatch.png
dispatch1.png
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. 總結

  1. DeepLink實現了網頁直接和App直接跳轉。之前手機上的每個App都相當於一個個孤島,沒有辦法和廣泛的網站實現直接的跳轉。現在比如你在瀏覽微博的時候看到某個App上面有精彩的內容,你就可以直接點擊鏈接跳轉到App裏面(甚至可以判斷如果按照了App就進入App裏面,如果不安裝那麼就進入應用市場的該App下載界面),這樣的交互很方便,很好的將App連接到了整個網絡世界,以後有個瀏覽器就能隨意的跳轉。
  2. DeepLink完全可以在搜索中使用,目前的搜索都是搜到了內容還是調網頁。以後如果開發者把自己的DeepLink鏈接提交給搜索公司,那麼在搜索到對應的結果的時候就可以直接點擊搜到的結果跳轉到自己的App了。這個還能應用到廣告上去。推廣自己的App就更容易了。
  3. DeepLink使得大企業的衆多App之間相互拉活,相互跳轉。假如某公司有個超級App,那麼想推廣自己的其他App就可以使用DeepLink在開啓自己某個子頁面的時候,把這個子頁面交給其他App進行處理。這樣就拉活了自己的其他App了。
  4. 在DeepLink的基礎上,Google又新出了一個AppLinks,AppLinks就是你自己的網站和你自己的App相互關聯了。比如用戶在短信中點擊了你的網站,那麼就可以直接跳轉到你的App,而不會出現選擇對話框。Google官方是這樣說的:
Android App Links are a special type of deep link that allow your website URLs to immediately open the 
corresponding content in your Android app (without requiring the user to select the app).

To add Android App Links to your app, define intent filters that open your app content using HTTP URLs (as
 described in [Create Deep Links to App Content]), and verify that you own both your app and the website URLs (as described in this guide). If the 
system successfully verifies that you own the URLs, the system automatically routes those URL intents to your app.

創建你自己的AppLinks,可以參考如下Create Deep Links to App Content。後續我會專門寫篇文章介紹下AppLinks及其用法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章