##酷炫的外部开启Activity新姿势
在H5页面疯狂的今天,H5和Native的交互就至关重要,而且交互的方式有很多,google提供了一个公共的方式:js与native互调,即js可以调用Native方法,Native同样也可以调用js方法。不过今天要讲的并不是Url拦截的方式和JavaScript注入方式,因为这种交互方式存在着不少问题:

1、Java 调用 js 里面的函数、效率并不是很高、估计要200ms左右吧、做交互性很强的事情、这种速度很难让人接受、而js去调Java的方法、速度很快、50ms左右、所以尽量用js调用Java方法
2、Java 调用 js 的函数、没有返回值、调用了就控制不到了
3、Js 调用 Java 的方法、返回值如果是字符串、你会发现这个字符串是 native 的、转成 locale 的才能正常使用、使用 toLocaleString() 函数就可以了、不过这个函数的速度并不快、转化的字符串如果很多、将会很耗费时间
4、Android4.2以下的系统存在着webview的js对象注入漏洞

所以处于这些原因,我们并未采用这种方式用于Native与webview交互,而是要介绍核武器—scheme,采用scheme + cookie的方式。
那你可能会思考什么是scheme? 到底哪些场景适合?具体怎么使用?
表要捉急,慢慢来介绍。
###什么是scheme?
客户端应用可以向操作系统注册一个 URL scheme,该 scheme 用于从浏览器或其他应用中启动本应用。通过指定的 URL 字段,可以让应用在被调起后直接打开某些特定页面,比如车辆详情页、订单详情页、消息通知页、促销广告页等等。也可以执行某些指定动作,如订单支付等。也可以在应用内通过 html 页来直接调用显示 app 内的某个页面。
###scheme格式?
客户端自定义的 URL 作为从一个应用调用另一个的基础,遵循 RFC 1808 (Relative Uniform Resource Locators) 标准。这跟我们常见的网页内容 URL 格式一样。
先来个完整的URL Scheme协议格式:

xl://goods:8888/goodsDetail?goodsId=10011002
通过上面的路径 Scheme、Host、port、path、query全部包含,基本上平时使用路径就是这样子的。

  • xl代表该Scheme 协议名称
  • goods代表Scheme作用于哪个地址域
  • goodsDetail代表Scheme指定的页面
  • goodsId代表传递的参数
  • 8888代表该路径的端口号

举个栗子:
(该 URL 会调起车辆详情页):uumobile://mobile/carDetail?car_id=123456,其中 scheme 为 uumobile,host 为 mobile,relativePath 为 /carDetail,query 为 car_id=123456。

###在什么场景使用?
下面介绍一下本人曾经常用的场景:

  • 其他应用想要调用你APP的某个页面
  • 自己的H5页面想要调用native的某个页面
  • 服务器下发路径,客户端根据服务器下发跳转路径跳转相应的页面
  • APP端收到服务器端下发的PUSH通知栏消息,根据消息的点击跳转路径跳转相关页面

这样说大家没有在具体业务中使用可能不是很清楚,那么举个例子:
我们进入到h5的活动页面,这时候点击某个链接,要求跳回我们的native,那么就用到了scheme。
###scheme的使用
使用起来还是非常简单的:
####1.在Androidmanifest.xml中定义scheme

<activity android:name=".ProcessActivity"><!-- 要想在别的App上能成功调起App,必须添加intent过滤器 --><intent-filter><!-- 协议部分,名字随便设置 --><dataandroid:host="open.app.example"android:scheme="external" /><!-- 下面这几行也必须得设置 --><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><action android:name="android.intent.action.VIEW" /></intent-filter>
</activity>

⚠️:切记 android 小写 。

####2.获取Scheme跳转的参数

private static final String TAG = ProcessActivity.class.getSimpleName().toString();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_process);distribute();}private void distribute() {Uri uri = getIntent().getData();if (uri != null) {//url部分Log.e(TAG, "uri -----> " + uri);// scheme部分String scheme = uri.getScheme();Log.e(TAG, "scheme -----> " + scheme);// host部分String host = uri.getHost();Log.e(TAG, "host -----> " + host);// 访问路劲String path = uri.getPath();Log.e(TAG, "path -----> " + path);// Query部分String query = uri.getQuery();Log.e(TAG, "query -----> " + query);//获取指定参数值String isShowSplash = uri.getQueryParameter("isShowSplash");Log.e(TAG, "isShowSplash -----> " + isShowSplash);String infomation = uri.getQueryParameter("infomation");Log.e(TAG, "infomation -----> " + infomation);} else {finish();}}

####3.使用
只需要调用如下代码就可以:

startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("external://open.app.example/first?isShowSplash=true&infomation='我是携带的信息'")));

####4.效果展示
让我们看一下打印出来的log日志:

这是我们接收到的uri传递的相关信息,只打印了一部分不是全部,有兴趣大家可以自行打印更多信息。

##实战演示
接下来我们完成一个小DEMO,主要功能通过外部APP打开对应的Activity并传递相关数据。
我们先看一下ExternalOpen这个工程里面最主要的就是配置了scheme能够通过uri的方式被启动。

看下目录结构:

功能清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="externalopen.libin.com.externalopen"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:launchMode="singleTop"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme.NoActionBar"><activityandroid:name="MainActivity"android:label="@string/app_name"android:theme="@style/AppTheme.NoActionBar"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".FirstActivity" /><activity android:name=".SecondActivity" /><activity android:name=".ThirdActivity" /><activity android:name=".ProcessActivity"><!-- 要想在别的App上能成功调起App,必须添加intent过滤器 --><intent-filter><!-- 协议部分,名字随便设置 --><dataandroid:host="open.app.example"android:scheme="external" /><!-- 下面这几行也必须得设置 --><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><action android:name="android.intent.action.VIEW" /></intent-filter></activity></application></manifest>

这里包含一个负责跳转的ProcessActivity和四个等候演示用到的展示的Activity界面。

我们先预览一下效果:

可能只看效果图,可能会看的很迷茫,接下来看下讲解。

首先我们安装两个app,一个专门负责启动相应的activity的OmnipotentFrame工程,另外一个是我们的主角ExternalOpen工程。

首先我们看到有的会显示欢迎界面,有的不显示,都是根据isShowSplash控制。
我们在isShowSplash=true 显示欢迎界面,,在isShowSplash=false时不现实欢迎界面。然后具体跳转哪一个Activity根据path决定,然后传递的信息内容放在information里面。
我们看到我们通过OmnipotentFrame可以开启ExternalOpen里面的任意activity。
主要是通过scheme和自定义processActivity控制的。
除了在外部app可以打开,在内部也可以使用这个方法,同样H5页面也可,这样APP之间的交互就方便多了,不过具体的还是要和业务相关联
更多参数可以自己根据业务来定,这里只是给大家一个启发。

####负责分发跳转的activity

/*** 负责分发跳转的activity*/
public class ProcessActivity extends AppCompatActivity {private static final String TAG = ProcessActivity.class.getSimpleName().toString();public static final String FIRST = "/first";public static final String SECOND = "/second";public static final String THIRD = "/third";public static final String URI = "uri";public static final String ISSHOWSPLASH = "isShowSplash";public static final String INFOMATION = "infomation";private ImageView iv_bg;String path;Uri uri;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_process);iv_bg = (ImageView) findViewById(R.id.iv_bg);try {distribute();} catch (Exception e) {Log.e(TAG, "分发异常");}}private void distribute() {uri = getIntent().getData();if (uri != null) {//url部分Log.e(TAG, "uri -----> " + uri);// scheme部分String scheme = uri.getScheme();Log.e(TAG, "scheme -----> " + scheme);// host部分String host = uri.getHost();Log.e(TAG, "host -----> " + host);// 访问路劲path = uri.getPath();Log.e(TAG, "path -----> " + path);// Query部分String query = uri.getQuery();Log.e(TAG, "query -----> " + query);//获取指定参数值String isShowSplash = uri.getQueryParameter(ISSHOWSPLASH);Log.e(TAG, "isShowSplash -----> " + isShowSplash);String infomation = uri.getQueryParameter(INFOMATION);Log.e(TAG, "infomation -----> " + infomation);//===============================以上为log信息方便理解==============================>if (path != null && !path.isEmpty()) {/***  是否展示欢迎页面*  很多情况下从外部开启APP需要展示广告或者欢迎页面,这里模拟下一欢迎页*/if (isShowSplash.equals("true")) {iv_bg.setVisibility(View.VISIBLE);new Handler().postDelayed(new Runnable() {@Overridepublic void run() {iv_bg.setVisibility(View.INVISIBLE);controlActivity(path, uri);finish();}},2000);}else {controlActivity(path, uri);finish();}}} else {finish();}}/*** 根据Path确定开启哪个Activity* @param path* @param uri*/private void controlActivity(String path, Uri uri) {if (path.equals(FIRST)) {Intent intent = new Intent(this, FirstActivity.class);intent.putExtra(INFOMATION, uri.getQueryParameter(INFOMATION));startActivity(intent);} else if (path.equals(SECOND)) {Intent intent = new Intent(this, SecondActivity.class);intent.putExtra(INFOMATION, uri.getQueryParameter(INFOMATION));intent.putExtra(URI, uri);startActivity(intent);} else if (path.equals(THIRD)) {Intent intent = new Intent(this, ThirdActivity.class);intent.putExtra(INFOMATION, uri.getQueryParameter(INFOMATION));intent.putExtra(URI, uri);startActivity(intent);}}}

####使用

btn_1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("external://open.app.example/first?isShowSplash=true&infomation=Path---->FirstActivity******isShowSplash---->true")));}});btn_2.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("external://open.app.example/second?isShowSplash=false&infomation=Path---->SecondActivity******isShowSplash---->false")));}});btn_3.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("external://open.app.example/third?isShowSplash=true&infomation=Path---->ThirdActivity******isShowSplash---->true")));}});btn_4.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("external://open.app.example/home?isShowSplash=true&infomation=首页")));}});

在需要使用的地方只需要添加uri即可。

###加下来看一下比较酷炫的效果—web开启Activity
先看一下效果图:

是不是很炫 ,我们看一下实现原理 :

首先我这里写了一个本地的html文件,放在了asserts下面 ,代码非常简单如下:

<html><body style="background-color:yellow"><p style="font-size:20px;text-align:center;"><h1>web跳转Activity</h1></p><p style="font-size:20px;text-align:center;" ><a href="external://open.app.example/home?isShowSplash=false&infomation=我是携带的信息">我是首页,不展示欢迎页</a></p><p style="font-size:20px;text-align:center;"><a href="external://open.app.example/first?isShowSplash=false&infomation=我是携带的信息">我是第一个Activity,不展示欢迎页</a></p><p style="font-size:20px;text-align:center;"><a href="external://open.app.example/second?isShowSplash=true&infomation=我是携带的信息">我是第二个Activity,展示欢迎页</a></p><p style="font-size:20px;text-align:center;"><a href="external://open.app.example/third?isShowSplash=true&infomation=我是携带的信息">我是第三个Activity,展示欢迎页</a></p></body></html>

这个文件放在了asserts下面,方便使用。

然后我们去加载web页面就可以啦 ,点击就能实现跳转啦,就是这么简单。

String ASSERTS_PATH  ="file:///android_asset/" ;WebView wv_test = (WebView) findViewById(R.id.wv_test);wv_test.loadUrl(ASSERTS_PATH+"index.html");

还有不明白的可以去看我的demo 非常详细。

DEMO下载地址:
http://download.csdn.net/detail/github_33304260/9873191

扫码关注公众号“伟大程序猿的诞生“,更多干货新鲜文章等着你~

公众号回复“资料获取”,获取更多干货哦~

有问题添加本人微信号“fenghuokeji996” 或扫描博客导航栏本人二维码

酷炫的外部开启Activity新姿势相关推荐

  1. 给Python代码加上酷炫进度条的几种姿势

    作者 | 刘早起 来源 | 早起Python(ID: zaoqi-python) 大家好,在下载某些文件的时候你一定会不时盯着进度条,在写代码的时候使用进度条可以便捷的观察任务处理情况,除了使用pri ...

  2. 酷炫实现WebView与Native完美融合

    ##前言 首先看个效果图: 这里背景是native的,左侧边栏也是native的,右侧内容是透明web页面,是不是很酷炫的样子,而且我们还可以自己加蒙版背景,是不是很酷. 这个场景非常适合左侧目录是本 ...

  3. 手机扫一扫,现实物体隔空「复制粘贴」进电脑!北大校友的AI新研究,现在变成AR酷炫应用...

    十三  白交 发自 凹非寺 量子位 报道 | 公众号 QbitAI 魔法变现实,酷炫又实用. 还记得两年前,Zach King(男巫)的爆红魔术吗? 不仅从纸直接蹦出一个手机,还直接扔进了电脑里形成虚 ...

  4. 电脑复制粘贴_手机扫一扫,现实物体隔空复制粘贴进电脑!北大校友的AI新研究,现在变成AR酷炫应用...

    本文经AI新媒体量子位(ID:QbitAI)授权转载,转载请联系出处 十三  白交 发自 凹非寺 魔法变现实,酷炫又实用. 还记得两年前,Zach King(男巫)的爆红魔术吗? 不仅从纸直接蹦出一个 ...

  5. 手机扫一扫,现实物体隔空「复制粘贴」进电脑!北大校友的AI新研究,现在变成AR酷炫应用

    魔法变现实,酷炫又实用. 还记得两年前,Zach King(男巫)的爆红魔术吗? 不仅从纸直接蹦出一个手机,还直接扔进了电脑里形成虚拟的天猫页面. 现在,不用去羡慕男巫了,人人都可以把身边的东西&qu ...

  6. 【Android】Anroid5.0+新控件---酷炫标题栏的简单学习

    Android5.0+推出的新控件感觉特别酷,最近想模仿大神做个看图App出来,所以先把这些新控件用熟悉了. 新控件的介绍.使用等等网上相应的文章已经特别多了,题主也没那能力去写篇详解出来,本篇随笔记 ...

  7. Win11新特性:在平板锁屏界面还有酷炫的3D视差效果

    在深入挖掘 Windows 11 系统之后,用户再次发现了隐藏的 Windows 10 Mobile 保留功能.知名破解达人 ADeltaX 表示,如果你的设备有合适的硬件,Windows 11 将在 ...

  8. #开工新姿势#开启一年新征程,云社区叫你来充电啦!

    摘要:这有份开工红包等你来拿哟~~ 一年之计在于春 值此春暖花开.开学复工之季 华为云社区"内容共创计划"再次来袭! 无论你是正在读书的学生开发者,还是经验丰富的职场技术人,都非常 ...

  9. 微信朋友圈+html+字体颜色,微信新功能 酷炫的彩色微信名字 朋友圈彩色昵称设置方法...

    原标题:微信新功能 酷炫的彩色微信名字 朋友圈彩色昵称设置方法 这几天有几位微民们问小编,说看到朋友的微信昵称变成了彩色字体,好奇这怎么回事,觉得非常好玩,那怎样才可以设置彩色字体呢? 希望小编能教大 ...

  10. 狂拽酷炫新体验!技嘉凤凰版B85装机实战

    1 技嘉 B85N 凤凰版概况介绍 回顶部 [PConline评测]这年头,装小型主机和迷你主机才是主流,因此ITX迷你主板也越来越受欢迎.近期技嘉再次创新,推出了一款"凤凰版"B ...

最新文章

  1. 《团队合作大坑合集》
  2. 在不重装系统的情况下撤底删除oracle数据库及oralce的相关软件
  3. android 不可点击状态,Android系统.如何使用setClickable同时设置所有按钮可点击或不可点击?...
  4. 电脑安装了mysql,但找不到mysql服务
  5. 《Python Cookbook 3rd》笔记(4.11):同时迭代多个序列
  6. 作者:孙卫强(1976-),男,博士,上海交通大学教授、博士生导师,主要研究方向为大数据网络、信息通信网等。...
  7. Spyder清除Variable Explorer手动安装protobuf3.0(为了配置windows的python接口)
  8. IEnumerableT 接口主要成员
  9. 深度有趣 | 29 方言种类分类
  10. Windows Azure Web Site (12) Azure Web Site配置文件
  11. 当在keil破解时出现的TOOLS.INI_TOOLCHAIN NOT INSTALLED的解决办法。
  12. 公众号要如何排版?这几个必备公众号排版技巧千万不要错过哦
  13. phpstorm 免费生成 激活码 保证有效
  14. NAT(网络地址转换)
  15. 打开Docx文件的方法
  16. 自主存取控制方法中-----------用户权限的“授权”与“收回”
  17. idea插件Translate 谷歌无法翻译 TKK失败,请检查网络连接
  18. 【ArcGIS Pro微课1000例】0020:ArcGIS Pro中河流(曲线)、湖泊(水体色)图例制作案例教程
  19. 为避免反射炫光计算机屏幕应怎样摆放,除了膜,电脑屏幕上还有种涂层,随便擦可就毁了!...
  20. No module named _lzma

热门文章

  1. JavaScript中清空数组的三种方式对比以及JavaScript常用数组操作方法
  2. 随手记_vscode怎样加命令行参数进行调试(python)
  3. opencv图像分析与处理(15)- 图像压缩中的编码方法:霍夫曼编码、Golomb编码、Rice编码、算术编码及其实现
  4. 数值分析(5)-分段低次插值和样条插值
  5. 彻底理解数字图像处理中的卷积-以Sobel算子为例
  6. 根据已有的WSDL文件进行WebService服务开发和部署
  7. 基于分割的PTD渐进三角网加密滤波(SBF)算法
  8. linux运维视频教程
  9. Spring 源码学习:day1
  10. Spring Data REST PATCH请求远程代码执行漏洞(CVE-2017-8046) 本地复现方法