为每一个 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)
哈哈,感谢你看到这里。