最近更新了「知乎」手机客户端,发现了知乎的一个新 feature
,在浏览器打开知乎的网页的时候会弹出程序选择窗口,选择在「知乎」程序里或者继续在网页端浏览。
不得不说这是一个很棒的主意,因为「知乎」自己程序里的搜索功能实在是太差了(据说是搜狗提供的),很多时候搜索不到自己想要的答案,而在网页端直接浏览的体验没有手机客户端好,这样倒是完美的结合了两种方式的优点。
刚好自己做的「手机睿思」其实也有类似的毛病,当你在手机上收到一个别人发过来的论坛帖子链接,有时候不在校内就无法打开,有时在校外,而网页端「手机睿思」体验又比较差,如果能实现「知乎」类似的结果就方便很多了。
理论
网页直接启动 Android
程序主要是通过 intent-filter
来实现的,intent-filter
包含很多属性,这里需要用到 <action>
、<category>
和<data>
这三个,详细的配置是通过 <data>
标签来完成的。
要添加的这要是这三个标签:
action_VIEW
:浏览网页使用的就是这个action
,不然无法接收浏览网页请求category.BROWSABLE
:目标Activity
中必须有这个,否则点击超链接后无法成功跳转category.DEFAULT
:没有这个的Activity
不接受隐式启动
以上三个标签负责接收网页跳转,剩下的URL
匹配就需要用 <data>
标签了。
URL
主要有四个部分组成,scheme
、authority
、path
、queryString
,其中authority
有分为host
和path
两部分,格式如下
1 | scheme://host:port/path?queryString |
根据URL
的格式,<data>
标签对应有以下属性:
1 | <data |
以 https://www.zhihu.com/question/28629301/answer/432294682
为例子,其中
scheme
: 协议类型,如http
、https
、ftp
等,也可以是自定义的数据host
: 主机地址,如www.zhihu.com
port
: 端口,比如常见的80
、8080
端口,默认的80
端口一般不写path
: 路径,比如/question/28629301/answer/432294682
pathPrefix
: 路径前缀,只有路径前缀是这个的才可以匹配,用于精确匹配条件pathPattern
: 和pathPrefix
类似,使用正则表达式来精确匹配路径
其他的属性这里用不上,因此不再详细解释,有兴趣可以自行了解。我需要匹配的URL
是这样的。
1 | http://rs.xidian.edu.cn/forum.php?mod=viewthread&tid=952631 |
在我的需求下用到了以下属性:
scheme
,设置为http
host
,设置为rs.xidian.edu.cn
path
,设置为/forum.php
实践
下面说一下具体现实步骤
创建两个
Activity
,MainActivity
和HttpActivity
,MainActivity
有一个按钮,用来发送浏览网页请求,HttpActivity
用于接收请求。HttpActivity
的配置如下1
2
3
4
5
6
7
8
9
10
11<activity android:name=".HttpActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:scheme="http"
android:host="rs.xidian.edu.cn"
android:pathPrefix="/forum.php"/>
</intent-filter>
</activity>在
MainActivity
里做好发送请求的代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private Button btn;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
btn.setOnClickListener(this);
}
public void onClick(View view) {
Uri uri = Uri.parse("http://rs.xidian.edu.cn/forum.php?mod=viewthread&tid=952475");
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(uri);
MainActivity.this.startActivity(i);
}
}在
HttpActivity
里进行数据接收,可以通过uri.getQueryParameter()
方法获取URL
携带的参数信息。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class HttpActivity extends AppCompatActivity {
public static final String TAG = "HttpActivity";
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_http);
Intent i = getIntent();
Uri uri = i.getData();
Log.i(TAG, "link:" + i.getDataString());
Log.i(TAG, "scheme: " + uri.getScheme());
Log.i(TAG, "host:" + uri.getHost());
Log.i(TAG, "path: " + uri.getPath());
Log.i(TAG, "mod: " + uri.getQueryParameter("mod"));
Log.i(TAG, "tid: " + uri.getQueryParameter("tid"));
}
}查看结果
1
2
3
4
5
6I/HttpActivity: link:http://rs.xidian.edu.cn/forum.php?mod=viewthread&tid=952475
I/HttpActivity: scheme: http
I/HttpActivity: host:rs.xidian.edu.cn
I/HttpActivity: path: /forum.php
I/HttpActivity: mod: viewthread
I/HttpActivity: tid: 952475
成功获取得到了参数,「知乎」用的是类似的方法,不过把host
换成了它自己的,另外根据path
和其他参数进行不同Activity
的跳转。
据我测试发现,以Chrome
为例,每新开一个标签页的时候会发送一次action_VIEW
的Intent
,这样就可以触发打开app,
不过「睿思」基本没有被搜索网站所收录,网页直接跳转这个基本用不上,现在能解决的痛点大概是聊天的时候直接发链接访问的问题了。