由于工作要求, 非要搞什么深度链接, 在百度的帮助下花了半小时搞明白了DeepLink是什么, 怎么用, 能做什么.
那么, DeepLink是什么呢? 其实说白了, 就是可以通过一个网页链接来打开APP中某一界面的技术, 没错, 就是通过链接来打开APP. 那么要怎么做呢? 首先要在想要被打开的activity的清单文件中注册一个意图过滤器:
如上图所示,其中action 和两个 category 是固定不变必须要加的, 特别是 BROWSABLE这个 category, 不加入这个就不能再浏览器中打开APP.
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
然后就是data节点了, 上图的data节点对应demo://www.open.com:8080
这个链接, 这个data就是用来匹配具体应用的, data节点中还可以加入path属性, 如果加了该属性(例如:android:path="\aaa"
)要匹配到APP就需要在链接的端口号后边加\aaa
, 需要注意的是, 清单文件 data节点path属性必须要以\
开头. 当然host port path属性都可以不加, 仅仅有scheme也是可以匹配到应用的, 当然, 你需要保证自己的scheme是手机APP中唯一的.
还有一个地方需要注意, 就是如果把链接 demo://www.open.com:8080
直接复制到浏览器中, 你会发现其实并不能打开APP, 这是因为浏览器检测到你的链接不是以http
开头所以自动识别进行搜索, 所以需要写一个简单的html页面来进行测试:
比如这个:
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<link href="/style.css" rel="stylesheet" type="text/css" media="all">
</head>
<body>
<a href="demo://www.open.com:8080/open?activity=com.eshel.chat.deeplink.LoginActivity">open</a>
</body>
</html>
复制上述html代码, 新建文本文件, 粘贴并修改链接后改后缀为**.html**, 之后选择打开方式为浏览器, 点击open按钮就可以测试了.
如果上述步骤都执行完, 那么应该可以通过DeepLink打开 APP了, 但是又有一个问题来了, 怎么才能打开app中任意界面呢? 难道每个activity都要加意图过滤器, 然后先不管这个问题, 我在想假如链接后边有参数, 那么会传到被打开的activity中呢?
这个是我测试用的链接:demo://www.open.com:8080/open?activity=com.eshel.chat.deeplink.LoginActivity
, 下边截图是测试结果:
点击链接后我在 MainActivity中 `getIntent().tostring` 设置到textview上, 可以看出其中dat部分就是我的链接, 那么dat是什么呢? 既然结果是通过toString方法得到的, 那么先看下intent的toString方法: ![这里写图片描述](https://img-blog.csdnimg.cn/img_convert/fc80078b031096a58d64b2adbbbbd872.png)
可以看出, toString的实现其实都是在toShortString里. 那么再来看下toShortString: ![这里写图片描述](https://img-blog.csdnimg.cn/img_convert/a0d2aeb2e87a0b531e0f0c15266e01e4.png)
终于看到dat中的url是mData toString得到的, mData是什么呢? 再来看一个方法: ![这里写图片描述](https://img-blog.csdnimg.cn/img_convert/083edb8b5008db6f6e2a0bf80beafeed.png)
通过getData方法可以看出mData是个Uri, 那么这个mData应该就是对应的是清单文件中的data节点了, 通过代码提示和文档注释可以找到Uri中有方法来获取'?'后边的参数, 代码如下:
setContentView(R.layout.activity_main);
mTest = findViewById(R.id.test);
Intent intent = getIntent();
if(intent != null){
mTest.setText(intent.toString());
try {//com.eshel.chat.deeplink.LoginActivity
String parameter = intent.getData().getQueryParameter("activity");
Class<?> aClass = Class.forName(parameter);
if(aClass != null){
Intent intent1 = new Intent(this,aClass);
startActivity(intent1);
finish();
}
// mTest.setText(path);
}catch (Exception e){
e.printStackTrace();
}catch (Error e){
e.printStackTrace();
}
}
获取到URL中的参数, activity
的值, 并通过反射尝试找到那个类, 如果存在则跳转, 当然千万不要忘记try catch. 通过这种方法就可以在URL中指定任意存在的activity并进行跳转了.
现在又有一个问题了, 虽然已经可以打开任意activity了, 但有的 activity 是依赖一些参数的, 它们在创建的时候 通常会通过 getIntent().getStringExtra("aaa")
等方法从上个activity获取一些数据, 那么从链接跳转到该activity并没有携带extra的数据, 怎么办呢? 很简单, 在参数后拼接一个参数extra
, 最好是一个json数组, 然后在代码中获取到该数据, 转换json格式并遍历, 通过循环进行putExtra到intent中, 这样就可以在把参数传递到actvity中了, 当然如果需要传递一个对象的话我就帮不了你了, 这种方式只能传递基本数据类型, 如果要传递javabean对象可以自己定义格式写代码解析json, 并通过反射或者gson框架将json转成javabean对象, 具体怎么搞这里就不再说了, 感兴趣的可以自己操作试试.