關注公眾號 QXF069
為每個 Activity 繫結一個 url 可以方便的讓第三方 app 直接開啟這些 Activity。也可以方便在 app 內部進行頁面跳轉,解耦。
背景 舉一個常見的案例,假設我們有個產品 A,產品 A 包含 h5 網頁端和客戶端,當使用者在手機開啟我們的 h5 網頁端的時候,我們會期望如果使用者手機安裝了我們的客戶端,則直接開啟 app,否則停留在網頁端瀏覽。
這是一個很常見的需求,但是實現需要 h5 和 Android 的配合,本文會先說下原理,然後單獨描述 Android 端需要做的事情,最後會給一個連結說明 h5 的工作。
原理 Android 端先給 Activity 繫結一個 url ,比如說是 myapp://main.
使用者訪問 http://myapp.com 網頁時,h5 嘗試訪問 myapp://main,如果使用者安裝了客戶端,則會開啟相應的 Activity,否則會繼續留在 h5 瀏覽網頁。
那麼,如何給 Activity 繫結一個 url 是在 Android 端的關鍵。
Android 實現 建立一個空的 ViewActivity.
public class ViewActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }
在 AndroidManifest.xml 裡面註冊 ViewActivity,包含一個 action 為 android.intent.action.VIEW 的 intent-filter
這樣,ViewActivity 就具備了接收 myapp 協議的 android.intent.action.VIEW 事件的能力。比如說,如果某個 app 執行了下面的這段邏輯,我們的 ViewActivity 就可能被開啟。
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("myapp://dosomething")); startActivity(intent); 剛才之所以說 “可能被開啟”,是為了嚴謹。因為完全可能使用者手機上,還有另外一個 app 也宣告瞭一樣協議的 intent-filter. 這時候系統就會給出一個彈出框,讓使用者選擇一個期望的應用來開啟該地址。
既然入口找到了,接下來就簡單了,無非就是實現一下 ViewActivity 處理跳轉邏輯,比如這樣。
public class ViewActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Uri uri = getIntent().getData(); String url = uri.toString(); if ("myapp://main".equals(url)) { startActivity(new Intent(ViewActivity.this, MainActivity.class)); } else if ("myapp://user".equals(url)) { startActivity(new Intent(ViewActivity.this, UserActivity.class)); } finish(); } } 但是上面這種,這是一個理想的情況,因為現實情況會複雜的多。比如說會遇到傳參問題,開啟一個 UserActivity 可能都是需要指定一個 userId 的。不過再怎麼複雜,無非就是對一個 url 的解析。
下面會介紹一個我寫的開源專案,省掉了解析 url 的麻煩,下面會基於這個庫來說明。
庫 這個庫叫 ActivityRouter,通過給 Activity 新增註解來繫結 url. 首先我們要把庫新增到專案裡面來, 需要修改兩個 build.gradle 檔案。
專案根目錄的 build.gradle
buildscript { dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7' } } app 專案的 build.gradle
apply plugin: 'android-apt'
dependencies { compile 'com.github.mzule.activityrouter:activityrouter:1.1.1' apt 'com.github.mzule.activityrouter:compiler:1.1.1' } 這樣,等專案 sync 完 ActivityRouter 就已經被整合在專案裡面了。
此外還需要改一個配置,之前在 AndroidManifest.xml 上註冊的 ViewActivity 現在要換成 ActivityRouter 裡面自帶的 Activity,這樣 ActivityRouter 才有機會處理相關的 Intent 事件。修改完的 AndroidManifest.xml 如下:
接下來就是去修改需要繫結 url 的 Activity,新增註解即可,一個典型的實現如下:
@Router("main") public class MainActivity extends Activity { } 一個需要引數的 Activity 可以這樣宣告:
@Router("user/:userId") // :userId 代表引數名為 userId public class UserActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String userId = getIntent().getStringExtra("userId"); // 獲取引數 userId } } 也可以給引數指定型別,比如說常見的 id 為 long 型.
@Router(value = "user/:userId", longExtra = "userId") 這樣我們就可以通過 myapp://main 來訪問 MainActivity, myapp://user/89757 來訪問 UserActivity 並且 userId = 89757 了。
H5 實現 如上文所說網頁自動跳轉到 app 需要 h5 配合,由於 h5 已經超越了 Android 的範疇,這邊就直接貼個連結。
http://t.cn/RqMTBDZ
http://t.cn/RzOQWGU
App 內應用場景 除了第三方 app 跳轉場景外,還可以在 app 內部 Activity 跳轉時採用 Router 來實現,比如在 Android 端和後端約定好頁面對應的 url,後端在傳送 push 的時候,就可以傳送特定的 url,客戶端只需要處理開啟 url 即可,可以有效減少 push 通知的適配工作。相關 API 如下:
Routers.open(Context, String) Routers.open(Context, Uri)
關注公眾號獲取更多內容