通过 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的时候就 ...
随机推荐
- 关于requests库中文编码问题
转自:代码分析Python requests库中文编码问题 Python reqeusts在作为代理爬虫节点抓取不同字符集网站时遇到的一些问题总结. 简单说就是中文乱码的问题. 如果单纯的抓取微博 ...
- HBase Configuration过程
(2012-10-22 15:56:10) 转载▼ HBase客户端API中,我们看到对HBase的任何操作都需要首先创建HBaseConfiguration类的实 例.为HBaseConf ...
- Java中equals方法简略描述
所有类都从Object中继承了equals方法,源码:public boolean equals(Object o){return this == o;} 直接判断this与o本身是否为同一对象(是否 ...
- Shell脚本学习-echo命令
跟着RUNOOB网站的教程学习的笔记 shell的echo指令与PHP的echo指令类似,都是用于字符串的输出.命令格式: echo string 1 显示普通字符串 echo "It is ...
- Ubuntu 中 iptables 增删查改
iptables是linux系统自带的防火墙,功能强大.如果iptables不熟悉的话可以用apf,是一款基于iptables的防墙. 一.安装并启动防火墙 $ /etc/init.d/iptable ...
- Kaldi如何准备自己的数据
Introduction 跑完kaldi的一些脚本例子,你可能想要自己用Kaldi跑自己的数据集.这里将会阐述如何准备好数据. run.sh较上的部分是有关数据准备的,通常local与数据集相关. 例 ...
- SVM理解
https://blog.csdn.net/feilong_csdn/article/details/62427148
- 关于JavaScript的操作
一:js基础. 1. var是定义js变量的关键字. 如: var leng=5;定义一个变量为5 var length = 16; // Number 通过数字字面量赋值 var points = ...
- C#6.0语言规范(三) 基本概念
应用程序启动 具有入口点的程序集称为应用程序.运行应用程序时,会创建一个新的应用程序域.应用程序的几个不同实例可以同时存在于同一台机器上,并且每个实例都有自己的应用程序域. 应用程序域通过充当应用程序 ...
- 数组的三种声明方式总结、多维数组的遍历、Arrays类的常用方法总结
1. 数组的三种声明方式 public class WhatEver { public static void main(String[] args) { //第一种 例: String[] test ...