在很多应用的web站,其实都有这样一个功能,就是直接在网页中打开应用,接下来的就来探讨一下这个功能的实现,有些地方也我还没弄明白,还请懂的大神指点。
首先,得说一点不好消息,在微信中,这样的方式是行不通的,因为微信把这种Intent(这个功能本身也就是一个Intent)给干掉了;
首先来看一段代码:
<intent-filter> <action android:name="android.intent.action.VIEW" /> <data android:scheme="test.target" /> <data android:host="my.com" /> <data android:port=":6060" /> <data android:path="/hello0" /> <data android:pathPrefix="/hello"/> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> </intent-filter>
这段代码的意思也就是说,在系统中注册了一个Intent,这个Intent能干什么呢?有什么功能呢?
- action:表示这个Intent是可以从一个View中打开;
- data:配置Intent所能够接收的Data(Uri),如上面的scheme,host,port,path等等;
- category:配置Intent是可浏览的,我理解就是可以被浏览器唤起的;
这段代码很明显就是要放在被打开的应用的某一个Activity里面的;
通过这段代码分析,我们可以得出带有这样一个Uri(scheme:test.target;host:my.com;port:6060;path:hello0和path为hello开头的链接)的Intent;
而我们的html页面就需要这样一个指向上面的Uri的链接:
<a href="test.target://my.com:6060/hello">打开应用</a> <a href="test.target://my.com:8480/hellox/22">打开应用</a>
上面那个链接,正好匹配在系统中配置的Uri,而下面的那个链接,我在测试的时候发现也能打开应用,而实际上下面的链接的port和系统配置的不一样,这是我还没搞明白的地方!求大家的指点
其实到这里,我们还应该想到的是,能在应用中获取这个链接的一些参数或者属性吗?答案是肯定的,我拿了下一条链接来做一个简单的测试分析
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Uri data = getIntent().getData(); if (data != null) { String scheme = data.getScheme(); // test.target String host = data.getHost(); // my.com int port = data.getPort(); // 8480 String path = data.getPath(); // hellox/22 List<String> params = data.getPathSegments(); // params0:hellox;params1:22 } }
最后,来分析一下原理:
在androidManifest.xml中定义intent-filter的时候定义的scheme,host,port,path这些东西拼凑起来其实就是一个有用的类HTTP路径;
当在webview或者是浏览器中,尝试打开一个链接“test.target://li.com:8480/hellox/22”,如同打开http://www.xx.com是一样的,浏览器或者webview先看能否处理当前需要处理的这个uri,但是浏览器发现test.target这个schema它是处理不了的,所以就将这个链接请求发送到系统中,然后由系统搜索是否有intent-filter能够处理这个uri,如果有一个这样的intent-filter,则直接打开;如果存在多个,则会弹出一个选择界面让用户选择(如同打开一个pdf文档,如果手机中有多个pdf的阅读器,会让用户进行选择);
灵活应用:如果手机中没有这个应用,就下载此应用
在实际项目中的scheme最好定义成http,这样如果手机中没有这个应用,还可以由浏览器打开这样一个页面,要实现这个扩展功能,其实只需要定义一个页面,浏览器请求这个页面的时候直接下载应用,然后把这个页面的http地址进行分割然后配置到对应的intent-filter的各个节点中即可;
其它参考:*