通过 URL 打开 Activity
为每个 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
<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 就可能被打开。
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 如下:
<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 了。
H5 实现
如上文所说网页自动跳转到 app 需要 h5 配合,由于 h5 已经超越了 Android 的范畴,这边就直接贴个链接。
App 内应用场景
除了第三方 app 跳转场景外,还可以在 app 内部 Activity 跳转时采用 Router 来实现,比如在 Android 端和后端约定好页面对应的 url,后端在发送 push 的时候,就可以发送特定的 url,客户端只需要处理打开 url 即可,可以有效减少 push 通知的适配工作。相关 API 如下:
Routers.open(Context, String)
Routers.open(Context, Uri)
结语
哈哈,感谢你看到这里。
通过 URL 打开 Activity的更多相关文章
- Unity3D研究院之打开Activity与调用JAVA代码传递参数
原地址:http://www.xuanyusong.com/archives/667 Unity for Android 比较特殊,Unity for IOS 打包是将XCODE工程直接交给开发 ...
- 打开Activity时,不自动显示(弹出)虚拟键盘
打开Activity时,不自动显示(弹出)虚拟键盘 在AndroidManifest.xml文件中<activity>标签中添加属性 android:windowSoftInputMode ...
- Activity 事件以及如何得到新打开Activity关闭后返回的数据
1: package com.example.activity_basic; 2: 3: import android.os.Bundle; 4: import android.app.Activ ...
- 点击短信中的url打开某个应用
实现功能: 短信内容中含有url(例如,http://youngo.com/app/),点击后打开apk 遗留问题: 点击url后,会出现选择框,让用户选择是用浏览器打开还是用该apk打开----没有 ...
- Android Intent (可通过URL启动 Activity)
Intent分为两大类: (1)显性的(Explicit) (2)隐性的(Implicit) 对于隐性意图,在某些时候, 应用程序只是想启动具有某种特征的组件, 并不想和某个特定的组件耦合. 使用In ...
- crm使用url打开窗口视图
//URL可寻址元素使您能够包含指向Microsoft Dynamics CRM窗口. 视图. 对话框和其它应用程序中的报告. //这样.您就能够轻松扩展其它应用程序.报表或站点,以便用户无需切换应用 ...
- Android学习(八) 打开Activity
在Android中打开窗口有两种方式,第一种是不需要返回值的,第二种是带返回值的. Main.xml文件,程序从这个窗口开始执行. <LinearLayout xmlns:android=&qu ...
- 04_显示意图打开activity
实际上用显式意图打开一个activity就很简单了.只需要指定你要打开的这个activity的class就可以了. 需要注意一点的是创建了一个ThirdActivity必须要在清单文件里面声明.如果没 ...
- 03_隐式意图打开activity
想让第一个activity把第二个activity打开的话,在清单文件里面声明一下并且 右键Debug As Android Application居然没有报错 mimeType 讲HTML的时候就 ...
随机推荐
- python 之 函数
什么是函数 引言 现在有这么个情况:假设我们python中的len方法不可以使用了,而恰好你又要计算一个字符串的长度你该怎么办呢?有人说:‘简单,可以使用for循环嘛 s1 = "hello ...
- spring boot + spring batch 读数据库文件写入文本文件&读文本文件写入数据库
好久没有写博客,换了一家新公司,原来的公司用的是spring,现在这家公司用的是spring boot.然后,项目组布置了一个任务,关于两个数据库之间的表同步,我首先想到的就是spring batch ...
- python基础之Day9
一.文件操作 1.r+t:可读可写 2.w+t:可写可读 3.a+t:可追加写.可读 4.f.seek(offset,whence) offset代表文件的指针的偏移量,单位是字节byteswhenc ...
- sqlserver 通过日志恢复误删的数据
转载地址:https://www.cnblogs.com/mrzl/p/4043313.html
- ActiveMQ_2安装
Linux安装 环境JDK7以上 gz文件拷贝到 /usr/local/目录下 解压 后缀为 .tar.gz的压缩包 进入解压后的文件夹 cd apache-activemq-x.xx.x/ cd b ...
- docker-compose安装redis-sentinel集群(1主+2副+2哨兵)
前提:本试验环境已经提前安装了docker和docker-compose 说明:本次部署是单机伪集群,想要部署真正的集群,需要将秒个主件拆分到各个机器上去部署,只修改ip地址 1.下载redis的相关 ...
- jsp页面有一个注册form表单,传值的时候后台接收到的全部是null
[页面上的传值元素一定要有name属性才可在后台接受到参数的值.切记!] 此处一定要注意,form表单里面的元素,比如input元素是否和后台的requset.getparameter();中的参数名 ...
- FreeRTOS移植到STM32上的移植过程
所有的单片机都是顺序执行的,而对于多任务而言就显得力不从心了,虽然在一些小项目中可以通过定时器来实现,但这种实现方式没有实时性,一旦任务需要在规定时间内做出响应,那只能通过实时操作系统来完成了.在很多 ...
- Eclipse中一些真正常用的快捷键
F2 文件重命名(要使用某个过长的文件名或者不好打的文件名时,直接F2再Ctrl+C非常好用,比如:Validform_v5.3.2_min.js) Ctrl+S 保存当前文件 Ctrl+Shift+ ...
- struts2框架学习笔记2:配置详解
核心配置文件: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC ...