转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/123238777 本文出自【赵彦军的博客】
浏览器为什么能唤起App的页面
浏览器为什么能唤起App的页面
URI、URL
- URI=Uniform Resource Identifier:统一资源标志符,在某一个规则下能把一个资源独一无二的标识出来。比如你的身份证号。
- URL=Uniform Resource Locator :统一资源定位符,可以提供找到该资源的路径,是URI的子集,是用定位方式实现的URI。
在www上,每一个信息资源都有统一的且在网上唯一的地址,该地址就叫URL,就是指网络地址。
二、URL的组成
URL的一般语法格式为(带方括号[]的为可选项)
protocol://hostname[:port]/path/[;parameters][?query]#fragment
协议://域名:端口号/目录/文件名.文件后缀?参数=值#标志
https://www.testurl.com:8080/path/subpath;parms=test_parms?uid=123&gid=45#fragment=009&fragment
- protocol 协议,常用的协议是http
- hostname 主机地址,可以是域名,也可以是IP地址
- port 端口 http协议默认端口是:80端口,如果不写默认就是:80端口
- path 路径 网络资源在服务器中的指定路径
- parameter 参数 如果要向服务器传入参数,在这部分输入
- query 查询字符串 如果需要从服务器那里查询内容,在这里编辑
- fragment 片段 网页中可能会分为不同的片段,如果想访问网页后直接到达指定位置,可以在这部分设置
Scheme
英文含义:方案、格式、策略
就是自定义的protocol,非标准,在许多情况下,scheme就是protocol的名称,定义了如何获取资源。
注意点
- 编码,query要编码,否则使用系统方法直接解析会失败
举例
val url = "taobao://app/path?version=1.0&name=zhaoyanjun&open=true"
val uri = Uri.parse(url)
val scheme = uri.scheme
val host = uri.host
val path = uri.path
val version = uri.getQueryParameter("version")
val name = uri.getQueryParameter("name")
val open = uri.getBooleanQueryParameter("open", false)
Log.d("yu--", "scheme:$scheme")
Log.d("yu--", "host:$host")
Log.d("yu--", "path:$path")
Log.d("yu--", "version:$version name:$name")
Log.d("yu--", "open:$open")
日志:
D/yu--: scheme:taobao
D/yu--: host:app
D/yu--: path:/path
D/yu--: version:1.0 name:zhaoyanjun
D/yu--: open:true
encode
在线 encode: http://www.jsons.cn/urlencode/
query要编码,否则使用系统方法直接解析会失败。
为什么要编码,举个例子,我有两个参数:
- 参数1:h5=https://baidu.com/step?_bid=11&version=1
- 参数2:version=1234
完整的 scheme 如下:
taobao://app/path?h5=https://baidu.com/step?_bid=11&version=1&&version=1234
下面获取分别获取参数 h5、version
val h5 = uri.getQueryParameter("h5")
val version = uri.getQueryParameter("version")
结果:
h5:https://baidu.com/step?_bid=11
version:1
显然获取的值,不是我们想要的正确的值,下面我们将 整个 query 参数编码,在看看效果。编码后的 scheme 如下:
参数一编码前:https://baidu.com/step?_bid=11&version=1
参数一编码后:https%3A%2F%2Fbaidu.com%2Fstep%3F_bid%3D11%26version%3D1
参数二编码前:1234
参数二编码后:1234
把两个参数组合起来,完整的 scheme 如下:
taobao://app/path?h5=https%3A%2F%2Fbaidu.com%2Fstep%3F_bid%3D11%26version%3D1&version=1234
后去相关参数如下:
D/yu--: scheme:taobao
D/yu--: host:app
D/yu--: path:/path
D/yu--: h5:https://baidu.com/step?_bid=11&version=1
D/yu--: version:1234
h5如何通过scheme唤起app
在 Activity 里添加 scheme 值
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<!-- scheme 开始 -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.APP_BROWSER" />
<data
android:host="app"
android:path="/path"
android:scheme="taobao" />
</intent-filter>
<!-- scheme 结束 -->
</activity>
WEB 端通过调用 taobao://app/path?query1=1&query2=true 便能打开这个Activity。其中 scheme 和 host 是必须的,另外的看需求。
通过WEB端打开
<!DOCTYPE html>
<html>
<head>
<title>test</title>
</head>
<body>
<a href="taobao://app/path?query1=1&query2=true">打开APP</a>
</body>
<html>
核心就是一段 Schema 协议的 URL,scheme、host 是打开APP页面所必须的。传递的参数都可以在APP页面中获取到。
通过另一个APP打开
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse("taobao://app/path?query1=1&query2=true")
)
startActivity(intent)
获取 scheme 值
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val uri = intent.data
if (uri != null) {
val scheme = uri.scheme
val host = uri.host
val path = uri.path
val query1 = uri.getQueryParameter("query1")
val query2 = uri.getQueryParameter("query2")
Log.d("yu--", "scheme:$scheme")
Log.d("yu--", "host:$host")
Log.d("yu--", "path:$path")
Log.d("yu--", "query1:$query1")
Log.d("yu--", "query2:$query2")
}
}
}
编码、解码
private fun encode(url: String): String {
return URLEncoder.encode(url, "UTF-8")
}
private fun decode(url: String): String {
return URLDecoder.decode(url, "UTF-8")
}
private fun getDecodeParams(uri: Uri, key: String): String? {
runCatching {
return URLDecoder.decode(getParams(uri, key), "UTF-8")
}
return null
}
private fun getParams(uri: Uri, key: String): String? {
runCatching {
return uri.getQueryParameter(key)
}
return null
}
|