爲每一個 Activity 綁定一個 url 能夠方便的讓第三方 app 直接打開這些 Activity。也能夠方便在 app 內部進行頁面跳轉,解耦。java
舉一個常見的案例,假設咱們有個產品 A,產品 A 包含 h5 網頁端和客戶端,當用戶在手機打開咱們的 h5 網頁端的時候,咱們會指望若是用戶手機安裝了咱們的客戶端,則直接打開 app,不然停留在網頁端瀏覽。android
這是一個很常見的需求,可是實現須要 h5 和 Android 的配合,本文會先說下原理,而後單獨描述 Android 端須要作的事情,最後會給一個連接說明 h5 的工做。git
Android 端先給 Activity 綁定一個 url ,好比說是 myapp://main
.github
用戶訪問 http://myapp.com
網頁時,h5 嘗試訪問 myapp://main
,若是用戶安裝了客戶端,則會打開相應的 Activity,不然會繼續留在 h5 瀏覽網頁。後端
那麼,如何給 Activity 綁定一個 url 是在 Android 端的關鍵。app
建立一個空的 ViewActivity.ide
public class ViewActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }
在 AndroidManifest.xml
裏面註冊 ViewActivity,包含一個 action 爲 android.intent.action.VIEW
的 intent-filter
gradle
<activity android:name=".ViewActivity" android:theme="@android:style/Theme.NoDisplay"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" /> </intent-filter> </activity>
這樣,ViewActivity
就具有了接收 myapp
協議的 android.intent.action.VIEW
事件的能力。好比說,若是某個 app 執行了下面的這段邏輯,咱們的 ViewActivity 就可能被打開。ui
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("myapp://dosomething")); startActivity(intent);
剛纔之因此說 "可能被打開",是爲了嚴謹。由於徹底可能用戶手機上,還有另一個 app 也聲明瞭同樣協議的 intent-filter. 這時候系統就會給出一個彈出框,讓用戶選擇一個指望的應用來打開該地址。this
既然入口找到了,接下來就簡單了,無非就是實現一下 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
以下:
<activity android:name="com.github.mzule.activityrouter.router.RouterActivity" android:theme="@android:style/Theme.NoDisplay"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="myapp" /> </intent-filter> </activity>
接下來就是去修改須要綁定 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 了。
如上文所說網頁自動跳轉到 app 須要 h5 配合,因爲 h5 已經超越了 Android 的範疇,這邊就直接貼個連接。
除了第三方 app 跳轉場景外,還能夠在 app 內部 Activity 跳轉時採用 Router 來實現,好比在 Android 端和後端約定好頁面對應的 url,後端在發送 push 的時候,就能夠發送特定的 url,客戶端只須要處理打開 url 便可,能夠有效減小 push 通知的適配工做。相關 API 以下:
Routers.open(Context, String) Routers.open(Context, Uri)
哈哈,感謝你看到這裏。