
HBuilderX 1.4.0 更新后 CSS 中条件编译失败的临时解决方案
一些同学更新 HBuilderX 1.4.0 后,运行至 App 或微信小程序时,控制台会报错提示条件编译的某个变量未定义。

临时解决方案:
下载附件中的 build.zip,打开 HBuilderX 的安装目录,找到 HBuilderX/plugins/uniapp/ 目录。
将下载的 build.zip 包解压至该目录,覆盖同名的 build 目录即可。
注:该问题不会影响打包,只会造成开发期间的问题,不用顾虑打包的问题。
一些同学更新 HBuilderX 1.4.0 后,运行至 App 或微信小程序时,控制台会报错提示条件编译的某个变量未定义。
临时解决方案:
下载附件中的 build.zip,打开 HBuilderX 的安装目录,找到 HBuilderX/plugins/uniapp/ 目录。
将下载的 build.zip 包解压至该目录,覆盖同名的 build 目录即可。
注:该问题不会影响打包,只会造成开发期间的问题,不用顾虑打包的问题。
收起阅读 »
更新HBuilderX 1.4后,uni-app打包APP失败
提示 app-plus.distribute.sdkConfigs.push.igexin.icons 不能为空
使用了个推,但是在视图配置中并没找到相关设置,在源码文件上加上图标路径,会报错不能是STRING
提示 app-plus.distribute.sdkConfigs.push.igexin.icons 不能为空
使用了个推,但是在视图配置中并没找到相关设置,在源码文件上加上图标路径,会报错不能是STRING

年末大礼:uni-app1.4新增百度、支付宝小程序。插件市场重磅上线!
在2018年的年尾,DCloud为开发者送上一份新年大礼:
- uni-app新增百度、支付宝小程序,从此一次开发,发布所有平台:iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序!
- uni-app插件市场上线了!https://ext.dcloud.net.cn/,支持前端组件、js sdk、页面模板、项目模板、原生插件等多种类型。还支持原生插件的云打包。
uni-app被我们定义为终极跨端框架,经过今年的不停完善迭代,我们认为它已经对得起这个称号了。
uni-app完全站在多端时代的新视角重新设计最佳开发模式,在跨端复用厚度、便利度、条件编译、布局及单位统一、跨端组件库、可商用程度方面拥有明显的优势。经得起较真党仔细对比。
uni-app虽然可以把丰富的微信生态的组件和sdk引入到App中,但百度支付宝等其他平台无法顺利支持微信的自定义组件。
由此我们决定基于vue组件方式,大力发展真正的跨8端通用的组件和sdk模式。
之前很多热情的开发者制作了通用的组件、模板,但在各种轮子的需求者和制造者之间还没有足够好的对接平台。
插件市场的诞生,将提升所有uni-app开发者的效率和重用程度。
过去很多开发者呼吁DCloud建立原生插件市场,吐槽5+SDK的插件方式和文档不够好。
uni-app由于内置了weex,所以uni-app插件市场支持weex的扩展插件,并且云打包机也升级,不用本地配原生开发环境,云端可直接打包weex扩展插件。
uni-app进一步新增了uni.requireNativePlugin的api,在vue页面和nvue页面均可使用这个api调用weex插件的能力。参考https://ask.dcloud.net.cn/article/35412。
欢迎大家积极参与插件市场的作品提交,不管是前端插件还是原生插件。
欢迎各家做开发者服务SDK的公司积极提交插件作品,共享DCloud 370万开发者资源。机构合作请联系bd@dcloud.io。
DCloud为插件作者提供了荣誉+经济回报的双激励模式,
让轮子制造者
- 感受到做一个轮子发布到8大平台的成就感,
- 感受到被数百万开发者点赞和应用到数亿手机用户侧的荣誉感,
- 更有打赏、销售(二期)等变现模式,让作者有更强的动力完善和制作更多好用的轮子。
DCloud还将于下月举办插件开发大赛,评选优秀插件作者,给予更多奖励。
欢迎访问插件市场:https://ext.dcloud.net.cn/
最后,祝各位开发者新年快乐。在新的2019年,移动互联网将变成彻底的多端时代,祝所有uni-app的开发者把握潮流、抓住先机、快速崛起、收获满满!
FAQ:
Q:插件市场的前端组件不是基于npm?
插件市场支持npm,这取决于插件作者是否自己上传到npm并在插件市场的说明中提供基于node的使用方式。
DCloud官方的uni ui是已经上传了npm的,并且和uni-app的cli兼容。
另外多说一下,uni-app支持cli模式,可以使用其他ide开发,但目录结构是src、dist这样的结构,和hx里新建的uni-app目录结构不一样。
中国数百万前端开发者,很多开发者不熟悉node。所以我们的插件市场也必须支持非npm方式。另外我们的插件市场会有防刷和评价机制,和npm也不同。
Q:老的5+app是否支持uni-app的原生插件
否。
目前5+app的原生扩展方式是基于webview桥的,这个方式在uni-app里也可以使用。
但uni-app插件市场的原生插件,是基于weex的。这种插件只能在uni-app里使用。
5+app目前没有计划引入weex插件。
uni-app其实已经在很多方面超过了5+app,建议开发者陆续都升级到uni-app。
Q:插件市场提交插件为什么要实名认证,是否可以作者自己贴赞赏码?
插件作者如果不实名认证,也可以提交插件,但这样的插件不会显示平台的赞赏按钮。
因为平台需要知道你是谁,才能给你分账。
不实名的作者提交的插件,在市场上不会上推荐位,也没有蓝v标记。
用户在选择比较插件时,也会倾向于加蓝v的作者的作品。
因为插件还是会涉及一些数据隐私、广告等问题,不实名的作品大家用着不踏实。
但这个实名信息并不会公开给公众,只是DCloud平台备案这些信息,然后给作者的昵称后面加个蓝v。
平台统一的赞赏有很多功能,根据赞赏情况会排序、推荐插件。
用户选择插件时也会参考赞赏这个关键指标。
作者的排行也依赖于赞赏数据,这些也有助于插件作者的身价提升。
DCloud也会给优秀插件作者各种奖励。
Q:插件市场的审核机制是什么?
目前只有原生插件有审核机制,前端的组件、sdk、模板无需审核,提交后可直接上线。
原生插件涉及的安全隐患大,我们需要先把关。
在2018年的年尾,DCloud为开发者送上一份新年大礼:
- uni-app新增百度、支付宝小程序,从此一次开发,发布所有平台:iOS、Android、H5、微信小程序、支付宝小程序、百度小程序、头条小程序、QQ小程序!
- uni-app插件市场上线了!https://ext.dcloud.net.cn/,支持前端组件、js sdk、页面模板、项目模板、原生插件等多种类型。还支持原生插件的云打包。
uni-app被我们定义为终极跨端框架,经过今年的不停完善迭代,我们认为它已经对得起这个称号了。
uni-app完全站在多端时代的新视角重新设计最佳开发模式,在跨端复用厚度、便利度、条件编译、布局及单位统一、跨端组件库、可商用程度方面拥有明显的优势。经得起较真党仔细对比。
uni-app虽然可以把丰富的微信生态的组件和sdk引入到App中,但百度支付宝等其他平台无法顺利支持微信的自定义组件。
由此我们决定基于vue组件方式,大力发展真正的跨8端通用的组件和sdk模式。
之前很多热情的开发者制作了通用的组件、模板,但在各种轮子的需求者和制造者之间还没有足够好的对接平台。
插件市场的诞生,将提升所有uni-app开发者的效率和重用程度。
过去很多开发者呼吁DCloud建立原生插件市场,吐槽5+SDK的插件方式和文档不够好。
uni-app由于内置了weex,所以uni-app插件市场支持weex的扩展插件,并且云打包机也升级,不用本地配原生开发环境,云端可直接打包weex扩展插件。
uni-app进一步新增了uni.requireNativePlugin的api,在vue页面和nvue页面均可使用这个api调用weex插件的能力。参考https://ask.dcloud.net.cn/article/35412。
欢迎大家积极参与插件市场的作品提交,不管是前端插件还是原生插件。
欢迎各家做开发者服务SDK的公司积极提交插件作品,共享DCloud 370万开发者资源。机构合作请联系bd@dcloud.io。
DCloud为插件作者提供了荣誉+经济回报的双激励模式,
让轮子制造者
- 感受到做一个轮子发布到8大平台的成就感,
- 感受到被数百万开发者点赞和应用到数亿手机用户侧的荣誉感,
- 更有打赏、销售(二期)等变现模式,让作者有更强的动力完善和制作更多好用的轮子。
DCloud还将于下月举办插件开发大赛,评选优秀插件作者,给予更多奖励。
欢迎访问插件市场:https://ext.dcloud.net.cn/
最后,祝各位开发者新年快乐。在新的2019年,移动互联网将变成彻底的多端时代,祝所有uni-app的开发者把握潮流、抓住先机、快速崛起、收获满满!
FAQ:
Q:插件市场的前端组件不是基于npm?
插件市场支持npm,这取决于插件作者是否自己上传到npm并在插件市场的说明中提供基于node的使用方式。
DCloud官方的uni ui是已经上传了npm的,并且和uni-app的cli兼容。
另外多说一下,uni-app支持cli模式,可以使用其他ide开发,但目录结构是src、dist这样的结构,和hx里新建的uni-app目录结构不一样。
中国数百万前端开发者,很多开发者不熟悉node。所以我们的插件市场也必须支持非npm方式。另外我们的插件市场会有防刷和评价机制,和npm也不同。
Q:老的5+app是否支持uni-app的原生插件
否。
目前5+app的原生扩展方式是基于webview桥的,这个方式在uni-app里也可以使用。
但uni-app插件市场的原生插件,是基于weex的。这种插件只能在uni-app里使用。
5+app目前没有计划引入weex插件。
uni-app其实已经在很多方面超过了5+app,建议开发者陆续都升级到uni-app。
Q:插件市场提交插件为什么要实名认证,是否可以作者自己贴赞赏码?
插件作者如果不实名认证,也可以提交插件,但这样的插件不会显示平台的赞赏按钮。
因为平台需要知道你是谁,才能给你分账。
不实名的作者提交的插件,在市场上不会上推荐位,也没有蓝v标记。
用户在选择比较插件时,也会倾向于加蓝v的作者的作品。
因为插件还是会涉及一些数据隐私、广告等问题,不实名的作品大家用着不踏实。
但这个实名信息并不会公开给公众,只是DCloud平台备案这些信息,然后给作者的昵称后面加个蓝v。
平台统一的赞赏有很多功能,根据赞赏情况会排序、推荐插件。
用户选择插件时也会参考赞赏这个关键指标。
作者的排行也依赖于赞赏数据,这些也有助于插件作者的身价提升。
DCloud也会给优秀插件作者各种奖励。
Q:插件市场的审核机制是什么?
目前只有原生插件有审核机制,前端的组件、sdk、模板无需审核,提交后可直接上线。
原生插件涉及的安全隐患大,我们需要先把关。

MUI框架样式做的手机端省市区城市地区选择器
基于MUI框架样式做的手机端省市区城市地区选择器
支持省市区,省市,省多方位选择
还有一个年月日时间日期选择功能
非常的简单实用,效果相当不错
基于MUI框架样式做的手机端省市区城市地区选择器
支持省市区,省市,省多方位选择
还有一个年月日时间日期选择功能
非常的简单实用,效果相当不错
下载地址:https://www.sucaihuo.com/js/2028.html
收起阅读 »
【企业简介】广东优势智云信息科技有限公司
广东优势智云信息科技有限公司(以下简称优势智云)是一家位于广州市天河软件园的高科技软件企业,公司于2018年10月16日,在广东股权交易中心成功挂牌,股权代码为:892400。公司自2016年成立至今,始终专注于企业级移动应用产品开发与项目实施,凭借过硬的技术储备和优秀的行业人才,秉承集中优势服务企业的理念,不断开拓创新,与客户共同成长共同进步。
总部设立在广州,在华东、华南、和华北区域设有深圳办、南昌办、武汉办、上海办、郑州办等多个分支办事机构。总部下设市场部、综合管理部、产品与解决方案部、交付与服务部、产品研发部、财务部等业务部门,员工总共有70余人,其中80%以上为研发人员;本科以上学历的员工占95%以上。
作为一家专注企业移动化的国家高新技术企业,得益于在政府、金融、能源、运营商、教育、交通等多个领域的沉淀,结合各行业企业移动化战略发展方向,将移动互联创新成果深度融合到各个领域之中,客户行业包括了政府、金融、能源、运营商、教育、交通等众多行业,并获得市场一致好评。
优势智云基于移动混合云架构服务平台,通过内部互联与外部创新,形成一套整合、完备的企业移动化解决方案,帮助客户从梳理业务痛点、行业诉求及价值需求出发,到敏捷开发,数据整合,移动中间件平台保障,多环境部署管理,再到后续运维升级,形成完美闭环。公司旨在帮助政府及企业建立专属的政府及企业级移动应用系统,让更多政府及企业快速高效安全的接入移动互联网,实现从移动互联协同时代到生态圈的跨变。。
1.公司logo:
2.公司名称:
广东优势智云信息科技有限公司
Guandong You Shi Zhi Yun Information Technolony Co.,Ltd
3.联系电话:
全国统一咨询热线:400-008-1668
公司固话:020-38373334
4.公司网站: http://www.yszyun.com
邮箱:marketing@yszyun.com
联系QQ:123089893
广东优势智云信息科技有限公司(以下简称优势智云)是一家位于广州市天河软件园的高科技软件企业,公司于2018年10月16日,在广东股权交易中心成功挂牌,股权代码为:892400。公司自2016年成立至今,始终专注于企业级移动应用产品开发与项目实施,凭借过硬的技术储备和优秀的行业人才,秉承集中优势服务企业的理念,不断开拓创新,与客户共同成长共同进步。
总部设立在广州,在华东、华南、和华北区域设有深圳办、南昌办、武汉办、上海办、郑州办等多个分支办事机构。总部下设市场部、综合管理部、产品与解决方案部、交付与服务部、产品研发部、财务部等业务部门,员工总共有70余人,其中80%以上为研发人员;本科以上学历的员工占95%以上。
作为一家专注企业移动化的国家高新技术企业,得益于在政府、金融、能源、运营商、教育、交通等多个领域的沉淀,结合各行业企业移动化战略发展方向,将移动互联创新成果深度融合到各个领域之中,客户行业包括了政府、金融、能源、运营商、教育、交通等众多行业,并获得市场一致好评。
优势智云基于移动混合云架构服务平台,通过内部互联与外部创新,形成一套整合、完备的企业移动化解决方案,帮助客户从梳理业务痛点、行业诉求及价值需求出发,到敏捷开发,数据整合,移动中间件平台保障,多环境部署管理,再到后续运维升级,形成完美闭环。公司旨在帮助政府及企业建立专属的政府及企业级移动应用系统,让更多政府及企业快速高效安全的接入移动互联网,实现从移动互联协同时代到生态圈的跨变。。
1.公司logo:
2.公司名称:
广东优势智云信息科技有限公司
Guandong You Shi Zhi Yun Information Technolony Co.,Ltd
3.联系电话:
全国统一咨询热线:400-008-1668
公司固话:020-38373334
4.公司网站: http://www.yszyun.com
邮箱:marketing@yszyun.com
联系QQ:123089893

HBuilderX Android平台uniapp依赖库列表
目前HBuilder X android 平台 uniapp所有依赖库列表
默认集成依赖库
- com.alibaba:fastjson 版本v1.1.46
- androidx.recyclerview:recyclerview:1.0.0
- androidx.legacy:legacy-support-v4:1.0.0
- androidx.appcompat:appcompat:1.0.0
- android-gif-drawable 版本v1.2.28
其他功能模块依赖库
- 小米push 版本v3.6.12
- 个推push 默认版本v3.3.7.0 google专版v4.4.3.13
- 百度Android定位 版本v7.5.0
- 百度地图 版本v5.4.1
- 高德Android定位 版本v6.4.5
- 高德地图 版本v9.7.2
- 微信SDK 版本v6.8.0
- 新浪微博 版本v12.5.0
- QQ 版本v3.5.12.2
- 小米登录 版本1.6.6
- 友盟 版本v9.7.1
- 百度语音 版本v3.4.1.101
- 穿山甲广告 版本v3.2.5.1
- 广点通广告 版本v4.270.1140
- 360广告 版本v5.17.3157
- LiteAVSDK 版本v6.3.7089
- 腾讯x5内核 版本v4.3.0.326_44226
- com.huawei.hms:push:5.0.2.300
- com.huawei.agconnect:agcp:1.4.1.300
版本号会跟随HBuilder X 更新而修改
目前HBuilder X android 平台 uniapp所有依赖库列表
默认集成依赖库
- com.alibaba:fastjson 版本v1.1.46
- androidx.recyclerview:recyclerview:1.0.0
- androidx.legacy:legacy-support-v4:1.0.0
- androidx.appcompat:appcompat:1.0.0
- android-gif-drawable 版本v1.2.28
其他功能模块依赖库
- 小米push 版本v3.6.12
- 个推push 默认版本v3.3.7.0 google专版v4.4.3.13
- 百度Android定位 版本v7.5.0
- 百度地图 版本v5.4.1
- 高德Android定位 版本v6.4.5
- 高德地图 版本v9.7.2
- 微信SDK 版本v6.8.0
- 新浪微博 版本v12.5.0
- QQ 版本v3.5.12.2
- 小米登录 版本1.6.6
- 友盟 版本v9.7.1
- 百度语音 版本v3.4.1.101
- 穿山甲广告 版本v3.2.5.1
- 广点通广告 版本v4.270.1140
- 360广告 版本v5.17.3157
- LiteAVSDK 版本v6.3.7089
- 腾讯x5内核 版本v4.3.0.326_44226
- com.huawei.hms:push:5.0.2.300
- com.huawei.agconnect:agcp:1.4.1.300
版本号会跟随HBuilder X 更新而修改
收起阅读 »
跨域问题解决方案
解决No 'Access-Control-Allow-Origin' header is present on the requested resource.跨域问题
解决方法 通过服务端设置返回参数
1.在后台写一个过滤器过滤器来改写请求头,直接给出代码
public class CusFilter implements Filter {
//...
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest)servletRequest;
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
String method = request.getMethod();
if(method.equalsIgnoreCase("OPTIONS")){
servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
}else{
filterChain.doFilter(servletRequest, servletResponse);
}
}
}
2.在web.xml修改过滤器配置
解决No 'Access-Control-Allow-Origin' header is present on the requested resource.跨域问题
解决方法 通过服务端设置返回参数
1.在后台写一个过滤器过滤器来改写请求头,直接给出代码
public class CusFilter implements Filter {
//...
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest)servletRequest;
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", origin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
response.setHeader("Access-Control-Allow-Credentials", "true");
String method = request.getMethod();
if(method.equalsIgnoreCase("OPTIONS")){
servletResponse.getOutputStream().write("Success".getBytes("utf-8"));
}else{
filterChain.doFilter(servletRequest, servletResponse);
}
}
}
2.在web.xml修改过滤器配置

Vue集成jpush之Android篇
一、首先先参考极光官方集成指南
参考https://github.com/jpush/jpush-hbuilder-demo
HBuilder 项目集成第三方插件,需先参考 HBuilder 官方的离线打包教程,将您的 HBuilder 项目集成进 Android 工程中。另外,还需要在极光官网根据你的包名申请APPKey。以上工作完成之后再执行以下步骤:
1.拷贝demo中 ./android/app/src/main/java/io.dcloud.feature.jpush 文件夹至你 Android Studio 工程的 /src/main/java/ 目录下。注意:RInformation.java文件不需要拷贝过来。
2.拷贝 ./jpush.js 到你 Android Studio 工程的 /assets/apps/HBuilder应用名/js/ 下。
3.在 /assets/apps/你的应用名/www/manifest.json 文件中添加:
"Push": {
"description": "消息推送"
}
4.在 /assets/data/dcloud_properties.xml 中添加(如果已存在 Push feature,可以直接修改):
<feature name="Push" value="io.dcloud.feature.jpush.JPushService" />
5.在 app/build.gradle 中添加:
android {
...
defaultConfig {
applicationId "com.***.***"// JPush上注册的包名
...
ndk {
// 选择要添加的对应 cpu 类型的 .so 库。
abiFilters 'armeabi', 'armeabi-v7a', 'x86'//,'arm64-v8a', 'x86_64', 'mips', 'mips64'
// 还可以添加 , 'x86_64', 'mips', 'mips64'
}
manifestPlaceholders = [
JPUSH_PKGNAME: applicationId,
JPUSH_APPKEY : "*****", // JPush上注册的包名对应的 appkey
JPUSH_CHANNEL: "developer-default", // 暂时填写默认值即可
]
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
...
dependencies {
...
compile 'cn.jiguang.sdk:jpush:3.1.8'
compile 'cn.jiguang.sdk:jcore:1.2.6'
}
6.在 AndroidManifest.xml 中添加:
<receiver
android:name="io.dcloud.feature.jpush.JPushReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTRATION" /> <!-- Required 用户注册SDK的 intent -->
<action android:name="cn.jpush.android.intent.UNREGISTRATION" />
<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!-- Required 用户接收SDK消息的 intent -->
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!-- Required 用户接收SDK通知栏信息的 intent -->
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!-- Required 用户打开自定义通知栏的 intent -->
<action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> <!-- Optional 用户接受 Rich Push Javascript 回调函数的intent -->
<action android:name="cn.jpush.android.intent.CONNECTION" /> <!-- 接收网络变化 连接/断开 since 1.6.3 -->
<category android:name="${JPUSH_PKGNAME}" />
</intent-filter>
</receiver>
二、添加相关处理代码
1.在vue中static文件加下新建jpush文件夹,然后将【一.2】中相同的jpush.js文件复制进来。
2.在Vue中,index.html中加入
<script src="static/jpush/jpush.js"></script>
然后加入相关方法,如下:
// 控制台输出日志
function outLog(msg) {
console.log(msg);
}
// 界面弹出吐司提示
function outLine(msg) {
mui.toast(msg);
}
var setTagsWithAlias = function () {
var tag1 = '...'
var tag2 = ''
var tag3 = ''
var alias = 'test'
var tags = []
if (tag1) {
tags.push(tag1)
}
if (tag2) {
tags.push(tag2)
}
if (tag3) {
tags.push(tag3)
}
window.plus.Push.setTagsWithAlias(tags, alias)
}
var getRegistrationID = function () {
window.plus.Push.getRegistrationID(function (data) {
if (data.length != 0) {
outLine('getRegistrationID>>>>' + data)
}
})
}
var getLaunchAppCacheNotification = function () {
if (mui.os.android) {
window.plus.Push.getLaunchAppCacheNotification(function (data) {
if (data.alert) {
outLine('cache:' + data.alert)
}
})
}
}
var receiveNotification = function (event) {
var content
if (mui.os.ios) {
content = window.plus.Push.receiveNotification.aps.alert
} else {
outLine('receiveNotification---else')
content = window.plus.Push.receiveNotification.alert
}
outLine(content)
}
var openNotification = function () {
var content
if (mui.os.ios) {
content = window.plus.Push.openNotification.aps.alert
} else {
content = window.plus.Push.openNotification.alert
window.plus.Push.clearLaunchAppCacheNotification()
}
outLine(content)
}
var receiveMessage = function () {
var msg
if (mui.os.ios) {
msg = window.plus.Push.receiveMessage.content
} else {
msg = window.plus.Push.receiveMessage.message
}
outLine(msg)
}
var onAliasAndTagsSet = function (event) {
var result = 'result code: ' + event.arguments.resultCode + ' '
result += 'tags: ' + event.arguments.tags + ' '
result += 'alias: ' + event.arguments.alias + ' '
mui.alert(result)
outLine(result)
}
var init = function () {
outLog('isInit:' + localStorage.getItem('isInit'))
outLine('isInit:' + localStorage.getItem('isInit'))
window.plus.Push.setDebugMode(true)
window.plus.Push.init()
getLaunchAppCacheNotification()
outLine('mui.os.android is ' + mui.os.android)
if (localStorage.getItem('isInit')) {
getRegistrationID()
} else {
localStorage.setItem('isInit', true)
}
}
document.addEventListener("plusready", init, false)
document.addEventListener('jpush.onGetRegistrationId', (rId) => {
console.log('registration id: ' + rId)
outLine('jpush::registration id: ' + rId)
localStorage.setItem("registrationId", rId)
// setTagsWithAlias()
}, false)
document.addEventListener("jpush.receiveMessage", receiveMessage, false)
document.addEventListener("jpush.receiveNotification", receiveNotification, false)
document.addEventListener("jpush.openNotification", openNotification, false)
document.addEventListener("jpush.setTagsWithAlias", onAliasAndTagsSet, false)
3.Android Studio,在manifest.json中permissions下,还需要添加以下代码
"Runtime": {
"description": "运行环境"
},
"XMLHttpRequest": {
"description": "跨域网络请求"
},
"NativeObj": {},
"Device": {}
这些是我在项目里需要的,各人按自己的项目增减。若有提示未打包什么模块,参考hbuilder官网。
4.Android Studio,在JPushReceiver中onReceive方法下稍微改写一下,我改写是为了更好的查看日志,不改也可以,不影响集成。
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (JPushInterface.ACTION_REGISTRATION_ID.equals(action)) {
String rId = JPushInterface.getRegistrationID(context);
Log.d(TAG, "regID:" + rId);
JPushService.transmitGetRegistrationId(rId);
} else if (JPushInterface.ACTION_CONNECTION_CHANGE.equals(action)) {
boolean state = JPushInterface.getConnectionState(context);
Log.d(TAG, "当前连接状态::" + state);
} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(action)) {
handlingMessageReceive(intent);
} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(action)) {
handlingNotificationReceive(context, intent);
} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(action)) {
handlingNotificationOpen(context,
intent);
} else {
Log.d(TAG, "Unhandled intent - " + action);
}
}
当然,在app完全退出即进程被杀情况下,不能接收到推送,还有就是我还不知道怎么根据不同的通知跳转Vue中不同的页面,大家知道怎么做的话或者哪里写的不对,欢迎给我留言。
到这里,集成就结束了。这个排版我实在不太会排,第一次发分享,也不知道怎么贴图,要想看的清晰点可以查看附件。
一、首先先参考极光官方集成指南
参考https://github.com/jpush/jpush-hbuilder-demo
HBuilder 项目集成第三方插件,需先参考 HBuilder 官方的离线打包教程,将您的 HBuilder 项目集成进 Android 工程中。另外,还需要在极光官网根据你的包名申请APPKey。以上工作完成之后再执行以下步骤:
1.拷贝demo中 ./android/app/src/main/java/io.dcloud.feature.jpush 文件夹至你 Android Studio 工程的 /src/main/java/ 目录下。注意:RInformation.java文件不需要拷贝过来。
2.拷贝 ./jpush.js 到你 Android Studio 工程的 /assets/apps/HBuilder应用名/js/ 下。
3.在 /assets/apps/你的应用名/www/manifest.json 文件中添加:
"Push": {
"description": "消息推送"
}
4.在 /assets/data/dcloud_properties.xml 中添加(如果已存在 Push feature,可以直接修改):
<feature name="Push" value="io.dcloud.feature.jpush.JPushService" />
5.在 app/build.gradle 中添加:
android {
...
defaultConfig {
applicationId "com.***.***"// JPush上注册的包名
...
ndk {
// 选择要添加的对应 cpu 类型的 .so 库。
abiFilters 'armeabi', 'armeabi-v7a', 'x86'//,'arm64-v8a', 'x86_64', 'mips', 'mips64'
// 还可以添加 , 'x86_64', 'mips', 'mips64'
}
manifestPlaceholders = [
JPUSH_PKGNAME: applicationId,
JPUSH_APPKEY : "*****", // JPush上注册的包名对应的 appkey
JPUSH_CHANNEL: "developer-default", // 暂时填写默认值即可
]
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
...
dependencies {
...
compile 'cn.jiguang.sdk:jpush:3.1.8'
compile 'cn.jiguang.sdk:jcore:1.2.6'
}
6.在 AndroidManifest.xml 中添加:
<receiver
android:name="io.dcloud.feature.jpush.JPushReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTRATION" /> <!-- Required 用户注册SDK的 intent -->
<action android:name="cn.jpush.android.intent.UNREGISTRATION" />
<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!-- Required 用户接收SDK消息的 intent -->
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!-- Required 用户接收SDK通知栏信息的 intent -->
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!-- Required 用户打开自定义通知栏的 intent -->
<action android:name="cn.jpush.android.intent.ACTION_RICHPUSH_CALLBACK" /> <!-- Optional 用户接受 Rich Push Javascript 回调函数的intent -->
<action android:name="cn.jpush.android.intent.CONNECTION" /> <!-- 接收网络变化 连接/断开 since 1.6.3 -->
<category android:name="${JPUSH_PKGNAME}" />
</intent-filter>
</receiver>
二、添加相关处理代码
1.在vue中static文件加下新建jpush文件夹,然后将【一.2】中相同的jpush.js文件复制进来。
2.在Vue中,index.html中加入
<script src="static/jpush/jpush.js"></script>
然后加入相关方法,如下:
// 控制台输出日志
function outLog(msg) {
console.log(msg);
}
// 界面弹出吐司提示
function outLine(msg) {
mui.toast(msg);
}
var setTagsWithAlias = function () {
var tag1 = '...'
var tag2 = ''
var tag3 = ''
var alias = 'test'
var tags = []
if (tag1) {
tags.push(tag1)
}
if (tag2) {
tags.push(tag2)
}
if (tag3) {
tags.push(tag3)
}
window.plus.Push.setTagsWithAlias(tags, alias)
}
var getRegistrationID = function () {
window.plus.Push.getRegistrationID(function (data) {
if (data.length != 0) {
outLine('getRegistrationID>>>>' + data)
}
})
}
var getLaunchAppCacheNotification = function () {
if (mui.os.android) {
window.plus.Push.getLaunchAppCacheNotification(function (data) {
if (data.alert) {
outLine('cache:' + data.alert)
}
})
}
}
var receiveNotification = function (event) {
var content
if (mui.os.ios) {
content = window.plus.Push.receiveNotification.aps.alert
} else {
outLine('receiveNotification---else')
content = window.plus.Push.receiveNotification.alert
}
outLine(content)
}
var openNotification = function () {
var content
if (mui.os.ios) {
content = window.plus.Push.openNotification.aps.alert
} else {
content = window.plus.Push.openNotification.alert
window.plus.Push.clearLaunchAppCacheNotification()
}
outLine(content)
}
var receiveMessage = function () {
var msg
if (mui.os.ios) {
msg = window.plus.Push.receiveMessage.content
} else {
msg = window.plus.Push.receiveMessage.message
}
outLine(msg)
}
var onAliasAndTagsSet = function (event) {
var result = 'result code: ' + event.arguments.resultCode + ' '
result += 'tags: ' + event.arguments.tags + ' '
result += 'alias: ' + event.arguments.alias + ' '
mui.alert(result)
outLine(result)
}
var init = function () {
outLog('isInit:' + localStorage.getItem('isInit'))
outLine('isInit:' + localStorage.getItem('isInit'))
window.plus.Push.setDebugMode(true)
window.plus.Push.init()
getLaunchAppCacheNotification()
outLine('mui.os.android is ' + mui.os.android)
if (localStorage.getItem('isInit')) {
getRegistrationID()
} else {
localStorage.setItem('isInit', true)
}
}
document.addEventListener("plusready", init, false)
document.addEventListener('jpush.onGetRegistrationId', (rId) => {
console.log('registration id: ' + rId)
outLine('jpush::registration id: ' + rId)
localStorage.setItem("registrationId", rId)
// setTagsWithAlias()
}, false)
document.addEventListener("jpush.receiveMessage", receiveMessage, false)
document.addEventListener("jpush.receiveNotification", receiveNotification, false)
document.addEventListener("jpush.openNotification", openNotification, false)
document.addEventListener("jpush.setTagsWithAlias", onAliasAndTagsSet, false)
3.Android Studio,在manifest.json中permissions下,还需要添加以下代码
"Runtime": {
"description": "运行环境"
},
"XMLHttpRequest": {
"description": "跨域网络请求"
},
"NativeObj": {},
"Device": {}
这些是我在项目里需要的,各人按自己的项目增减。若有提示未打包什么模块,参考hbuilder官网。
4.Android Studio,在JPushReceiver中onReceive方法下稍微改写一下,我改写是为了更好的查看日志,不改也可以,不影响集成。
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (JPushInterface.ACTION_REGISTRATION_ID.equals(action)) {
String rId = JPushInterface.getRegistrationID(context);
Log.d(TAG, "regID:" + rId);
JPushService.transmitGetRegistrationId(rId);
} else if (JPushInterface.ACTION_CONNECTION_CHANGE.equals(action)) {
boolean state = JPushInterface.getConnectionState(context);
Log.d(TAG, "当前连接状态::" + state);
} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(action)) {
handlingMessageReceive(intent);
} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(action)) {
handlingNotificationReceive(context, intent);
} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(action)) {
handlingNotificationOpen(context,
intent);
} else {
Log.d(TAG, "Unhandled intent - " + action);
}
}
当然,在app完全退出即进程被杀情况下,不能接收到推送,还有就是我还不知道怎么根据不同的通知跳转Vue中不同的页面,大家知道怎么做的话或者哪里写的不对,欢迎给我留言。
到这里,集成就结束了。这个排版我实在不太会排,第一次发分享,也不知道怎么贴图,要想看的清晰点可以查看附件。

iOS uni-app原生插件开发文档
请移步 新的文档 此文档已停止维护!!!
iOS uni-app原生插件开发文档
一、文档概述
本文档主要介绍如何在uni-app中基于WeexSDK 开发iOS原生插件。
更多说明请参考uni-app原生插件开发指南。
1.1、阅读对象
在您阅读此文档时,首先要知道uni-app支持weex插件,同时我们假定您已经具备了相应iOS应用开发经验,学习过 weex 知识并能够理解相关概念。此外,您也应该对HTML,JavaScript,CSS等有一定的了解,并且熟悉在JavaScript和Objective-C环境下的JSON格式数据操作等。
1.2、开发前准备
- OS X 10.14.0+
- Xcode 11.0+
- 学习weex 0.26.0版本框架API,weex扩展API for iOS
- 下载开发插件需要的SDK包 最新版本的SDK包,找到里面的HBuilder-uniPluginDemo文件夹,里面包含HBuilder-uniPlugin插件开发工程,后面会用到。
- 下载开发插件时会用到的js代码的开发工具HBuilderX(下载地址),下载哪个版本的HBuilderX需要注意下,保持和上条中提到的SDK包(在下载SDK包的下载界面中有版本相关的文字描述如下图),它提到的版本号一致。
- 确定SDK包里的Xcode工程HBuilder-uniPlugin内是否引用了SDK包里的liblibWeex.a库和weex-main-jsfm.js文件
二、 插件开发(以RichAlert插件为例)
2.1、 首先用Xcode创建静态.a库工程libWeexDCRichAlert 或(静态Framework工程),如何创建静态库工程请自行百度,下面提供了2个连接供参考。
iOS如何制作.a库
iOS如何制作静态Framework库
2.2、 在下载的工程包里找到HBuilder-uniPluginDemo文件夹,然后打开HBuilder-uniPlugin工程,把刚创建的静态库工程引入到HBuilder-uniPlugin工程,引入后的样子如下图所示,至于如何把静态库工程引入到HBuilder-uniPlugin工程里去,请自行百度,很简单的。
然后,修改libWeexDCRichAlert工程的iOS Deployment Target为8.0,如下图所示:
然后,在静态库工程libWeexDCRichAlert的 Header Search Paths 中添加引用如下图所示:
然后,在HBuilder-uniPlugin工程的Link Binary With Libraries中添加libWeexDCRichAlert.a库;然后,在Target Dependencies 中,添加插件工程的libWeexDCRichAlert的targets,如下图所示:
2.3、 配置需要注册的插件,打开HBuilder-uniPlugin工程里的info.plist 文件 加入节点,需要严格按要求配置,如下图所示:
其中,hooksClass的值是类名,是给有些插件需要在app启动时做初始化或者获取系统事件用的,如果没有可以不填为空;
plugins下的每一项是weex扩展模块或组件能力相关的配置信息,里面包含name(填weex模块或组件类名对应的js层用到的字符串,js层中将通过该字符串来使用原生层的模块或组件),class(填weex模块或组件类名),type(填module或component,一定不能配置错),注意不支持weex的handler扩展。
2.4 开始具体代码开发,分三步:其中第二步看情况(有需要在app启动时初始化或者获取系统事件用的,可以有第2步,如果没有则跳过这步)
第一步,在静态库libWeexDCRichAlert工程里,新建模块类DCRichAlertModule,注意命名加前缀防止冲突(如何具体开发模块或组件请参考,weex官方扩展iOS能力)
第二步,在静态库libWeexDCRichAlert工程里,新建DCRichAlertProxy类(注意命名加前缀防止冲突),继承 NSObject
遵守UniPluginProtocol协议 ,用来在app启动时初始化或者获取系统事件用的,这个类里尽量不要有其他的过多代码逻辑。如下图:
第三步,用之前下载好的HBuilderX开发工具 新建uni-app项目,选择默认模版,然后在index.vue文件里面编写下面示例的js代码,也可以再创建一个.nvue文件编写下面示例的js代码。 注意:后缀为.vue的文件只支持使用module(module也只支持异步方法不支持同步方法),不支持使用component,但是后缀为.nvue的文件两者都可以使用并且module同步异步都支持。
示例
引用方式
const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert');
调用
dcRichAlert.show({
position: 'bottom',
title: "提示信息",
titleColor: '#FF0000',
content: "<a href='https://uniapp.dcloud.io/' value='Hello uni-app'>uni-app</a> 是一个使用 Vue.js 开发跨平台应用的前端框架!\n免费的\n免费的\n免费的\n重要的事情说三遍",
contentAlign: 'left',
checkBox: {
title: '不再提示',
isSelected: true
},
buttons: [{
title: '取消'
},
{
title: '否'
},
{
title: '确认',
color: '#3F51B5'
}
]
}, result => {
switch (result.type) {
case 'button':
console.log("callback---button--" + result.index);
break;
case 'checkBox':
console.log("callback---checkBox--" + result.isSelected);
break;
case 'a':
console.log("callback---a--" + JSON.stringify(result));
break;
case 'backCancel':
console.log("callback---backCancel--");
break;
}
});
然后运行导出,可以得到编译后的代码,
然后把这些代码考到HBuilder-uniPlugin工程的Pandora目录下的www目录下
如下图,其中红矩形框起来的,control.xml里的appid和目录的名称都是appid,是从HBuilderX开发工具中导出来的 资源包里的manifest.json的id,三者值需要一致
三、本地调试插件的代码
然后就可以运行HBuilder-uniPlugin工程调试代码了,效果如下图所示:
如果调试过程中遇到问题,可能是原生的问题也可能是js代码的问题,如果是原生的问题,直接修改原生代码就可以了,但是如果是js代码的问题,需要修改.nvue或.vue的代码这个时候就需要重新导出编译后的代码(编译导出代码有可能会报错,注意控制台的日志信息,千万不要把有问题的资源拿去调试),拷贝到HBuilder-uniPlugin工程的Pandora目录下的www目录下,然后务必删除之前的app,再重新运行工程。
如果运行测试没任何问题,就可以进行下面的生成插件包的步骤了。
四、生成插件包
此步骤应该在您插件所有接口封装完毕,并在调试工程中测试完成后,再进行以下操作,说明中均以示例插件libWeexDCRichAlert为例进行的操作。在实际操作时,需将所有出现的libWeexDCRichAlert替换成您自己的插件名字,而且在插件开发过程中给文件命名或类命名时提倡增加前缀,以避免和其它模块冲突
如示例中插件类Module的类名是“DCRichAlertModule” ,其中“DC”就是前缀(作者标识)!
Module扩展和Component扩展在引用中的name 需要前缀加入你自己的标识,防止插件冲突。
如示例中配置的name为“DCloud-RichAlert”,其中“DCloud”就是标识!
4.1 编译生成插件静态库.a文件
.a库必须是真机环境的,并且需要支持armv7和arm64架构,且Build Active Architecture Only设置为NO,您可以在终端用以下命令查看.a库支持的架构:
lipo -info libWeexDCRichAlert.a
4.2 编写package.json文件,按下列链接配置
点击查看详细配置说明
iOS平台 package.json 详细说明请查看这篇文档前面部分,会帮助您更好的理解如何配置 https://ask.dcloud.net.cn/article/35764
iOS 插件包 至少需要包含:package.json文件 和 ios文件夹(名称必须是小写的ios)里面包含 .a (.a库必须是lib开头命名,比如libWeexDCRichAlert.a)或framework。
4.3 生成.zip包
将DCloud-RichAlert文件夹打成zip包,zip包的名称为(DCloud-RichAlert.zip)然后准备提交插件市场,其中DCloud-RichAlert文件夹名称和package.json 里id的值一致,zip包的名称是id值。
五、如果想要共享给其他开发者,把这个插件提交插件市场
不提交插件市场,也可以把生成的插件放到HBuilderX里,然后提交云端打包使用,提交到云端打包之前确保插件在本地是调试通的,否则云端打包出问题,增加排查问题的难度。
<a id="isPlatformVersionAtLeast"/>
六、编写原生代码时注意事项
目前 HBuilderX 正式版云端打包机使用的Xcode版本为 10.X,Xcode11.0 及以上版本对@available(, *)
的实现做了调整打包后的.a
库不兼容低版本的Xcode, 所以如果使用Xcode 11.0及以上版本开发插件并且插件中代码用到了@available(, *)
关键字请按下图修改,否则可能导致打包失败。报错 Undefined symbols "___isPlatformVersionAtLeast"
(使用 HBuilderX alpha 版本没有此问题,正式版云端打包机近期会更新到最新的Xcode版本)
Tips
开发uni-app原生插件时注意不要开发广点通广告插件和穿山甲广告插件,目前不支持。
获取 UIViewController
因为 uni 框架机制,module 的 weexInstance 没有绑定 viewController,故
weexInstance.viewController
值为 nil,如果想通过 UIViewController 来跳转页面可使用下面的方法获取 UIViewController**
// 获取当前显示的 UIViewController
+ (UIViewController *)dc_findCurrentShowingViewController {
//获得当前活动窗口的根视图
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];
return currentShowingVC;
}
+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc
{
// 递归方法 Recursive method
UIViewController *currentShowingVC;
if ([vc presentedViewController]) {
// 当前视图是被presented出来的
UIViewController *nextRootVC = [vc presentedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if ([vc isKindOfClass:[UITabBarController class]]) {
// 根视图为UITabBarController
UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if ([vc isKindOfClass:[UINavigationController class]]){
// 根视图为UINavigationController
UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else {
// 根视图为非导航类
currentShowingVC = vc;
}
return currentShowingVC;
}
获取页面可访问图片资源存储路径 (vue页面需要注意,nvue页面不存这个问题)
有些插件可能需要返回本地的图片路径给页面来显示,如果页面是
vue
的话是使用 WKWebview 渲染,访问本地图片资源可能会存在跨域问题访问不到图片资源,所以需要将图片存放到指定路径下,按照下面的方法获取图片存储路径即可
原生端实现
// 引用头文件
#import "PDRCoreApp.h"
#import "PDRCoreAppManager.h"
#import "PDRCoreAppInfo.h"
// 获取路径信息
PDRCoreAppInfo *appinfo = [PDRCore Instance].appManager.getMainAppInfo;
// 将图片存储到 appinfo.documentPath 路径下即可,可以创建子目录;
// 示例,原生图片存储路径为
NSString *imgPath = [appinfo.documentPath stringByAppendingPathComponent:@"test.png"];
js 端获取图片路径有两种方式
// 1.使用相对路径
var relativePath = "_doc/test.png"
// 2.使用平台的绝对路径
var docPath = plus.io.convertLocalFileSystemURL("_doc/");
var absolutePath = docPath + 'test.png'
欢迎有原生开发能力的朋友入群一起交流学习(入群请提供注册邮箱):
DCloud原生开发者群:
1群:256775471(已满)
2群:814228233(已满)
3群:455763866
Android原生插件开发参考:https://ask.dcloud.net.cn/article/35416
更多uni-app原生插件文档参考:uni-app原生插件开发指南
请移步 新的文档 此文档已停止维护!!!
iOS uni-app原生插件开发文档
一、文档概述
本文档主要介绍如何在uni-app中基于WeexSDK 开发iOS原生插件。
更多说明请参考uni-app原生插件开发指南。
1.1、阅读对象
在您阅读此文档时,首先要知道uni-app支持weex插件,同时我们假定您已经具备了相应iOS应用开发经验,学习过 weex 知识并能够理解相关概念。此外,您也应该对HTML,JavaScript,CSS等有一定的了解,并且熟悉在JavaScript和Objective-C环境下的JSON格式数据操作等。
1.2、开发前准备
- OS X 10.14.0+
- Xcode 11.0+
- 学习weex 0.26.0版本框架API,weex扩展API for iOS
- 下载开发插件需要的SDK包 最新版本的SDK包,找到里面的HBuilder-uniPluginDemo文件夹,里面包含HBuilder-uniPlugin插件开发工程,后面会用到。
- 下载开发插件时会用到的js代码的开发工具HBuilderX(下载地址),下载哪个版本的HBuilderX需要注意下,保持和上条中提到的SDK包(在下载SDK包的下载界面中有版本相关的文字描述如下图),它提到的版本号一致。
- 确定SDK包里的Xcode工程HBuilder-uniPlugin内是否引用了SDK包里的liblibWeex.a库和weex-main-jsfm.js文件
二、 插件开发(以RichAlert插件为例)
2.1、 首先用Xcode创建静态.a库工程libWeexDCRichAlert 或(静态Framework工程),如何创建静态库工程请自行百度,下面提供了2个连接供参考。
iOS如何制作.a库
iOS如何制作静态Framework库
2.2、 在下载的工程包里找到HBuilder-uniPluginDemo文件夹,然后打开HBuilder-uniPlugin工程,把刚创建的静态库工程引入到HBuilder-uniPlugin工程,引入后的样子如下图所示,至于如何把静态库工程引入到HBuilder-uniPlugin工程里去,请自行百度,很简单的。
然后,修改libWeexDCRichAlert工程的iOS Deployment Target为8.0,如下图所示:
然后,在静态库工程libWeexDCRichAlert的 Header Search Paths 中添加引用如下图所示:
然后,在HBuilder-uniPlugin工程的Link Binary With Libraries中添加libWeexDCRichAlert.a库;然后,在Target Dependencies 中,添加插件工程的libWeexDCRichAlert的targets,如下图所示:
2.3、 配置需要注册的插件,打开HBuilder-uniPlugin工程里的info.plist 文件 加入节点,需要严格按要求配置,如下图所示:
其中,hooksClass的值是类名,是给有些插件需要在app启动时做初始化或者获取系统事件用的,如果没有可以不填为空;
plugins下的每一项是weex扩展模块或组件能力相关的配置信息,里面包含name(填weex模块或组件类名对应的js层用到的字符串,js层中将通过该字符串来使用原生层的模块或组件),class(填weex模块或组件类名),type(填module或component,一定不能配置错),注意不支持weex的handler扩展。
2.4 开始具体代码开发,分三步:其中第二步看情况(有需要在app启动时初始化或者获取系统事件用的,可以有第2步,如果没有则跳过这步)
第一步,在静态库libWeexDCRichAlert工程里,新建模块类DCRichAlertModule,注意命名加前缀防止冲突(如何具体开发模块或组件请参考,weex官方扩展iOS能力)
第二步,在静态库libWeexDCRichAlert工程里,新建DCRichAlertProxy类(注意命名加前缀防止冲突),继承 NSObject
遵守UniPluginProtocol协议 ,用来在app启动时初始化或者获取系统事件用的,这个类里尽量不要有其他的过多代码逻辑。如下图:
第三步,用之前下载好的HBuilderX开发工具 新建uni-app项目,选择默认模版,然后在index.vue文件里面编写下面示例的js代码,也可以再创建一个.nvue文件编写下面示例的js代码。 注意:后缀为.vue的文件只支持使用module(module也只支持异步方法不支持同步方法),不支持使用component,但是后缀为.nvue的文件两者都可以使用并且module同步异步都支持。
示例
引用方式
const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert');
调用
dcRichAlert.show({
position: 'bottom',
title: "提示信息",
titleColor: '#FF0000',
content: "<a href='https://uniapp.dcloud.io/' value='Hello uni-app'>uni-app</a> 是一个使用 Vue.js 开发跨平台应用的前端框架!\n免费的\n免费的\n免费的\n重要的事情说三遍",
contentAlign: 'left',
checkBox: {
title: '不再提示',
isSelected: true
},
buttons: [{
title: '取消'
},
{
title: '否'
},
{
title: '确认',
color: '#3F51B5'
}
]
}, result => {
switch (result.type) {
case 'button':
console.log("callback---button--" + result.index);
break;
case 'checkBox':
console.log("callback---checkBox--" + result.isSelected);
break;
case 'a':
console.log("callback---a--" + JSON.stringify(result));
break;
case 'backCancel':
console.log("callback---backCancel--");
break;
}
});
然后运行导出,可以得到编译后的代码,
然后把这些代码考到HBuilder-uniPlugin工程的Pandora目录下的www目录下
如下图,其中红矩形框起来的,control.xml里的appid和目录的名称都是appid,是从HBuilderX开发工具中导出来的 资源包里的manifest.json的id,三者值需要一致
三、本地调试插件的代码
然后就可以运行HBuilder-uniPlugin工程调试代码了,效果如下图所示:
如果调试过程中遇到问题,可能是原生的问题也可能是js代码的问题,如果是原生的问题,直接修改原生代码就可以了,但是如果是js代码的问题,需要修改.nvue或.vue的代码这个时候就需要重新导出编译后的代码(编译导出代码有可能会报错,注意控制台的日志信息,千万不要把有问题的资源拿去调试),拷贝到HBuilder-uniPlugin工程的Pandora目录下的www目录下,然后务必删除之前的app,再重新运行工程。
如果运行测试没任何问题,就可以进行下面的生成插件包的步骤了。
四、生成插件包
此步骤应该在您插件所有接口封装完毕,并在调试工程中测试完成后,再进行以下操作,说明中均以示例插件libWeexDCRichAlert为例进行的操作。在实际操作时,需将所有出现的libWeexDCRichAlert替换成您自己的插件名字,而且在插件开发过程中给文件命名或类命名时提倡增加前缀,以避免和其它模块冲突
如示例中插件类Module的类名是“DCRichAlertModule” ,其中“DC”就是前缀(作者标识)!
Module扩展和Component扩展在引用中的name 需要前缀加入你自己的标识,防止插件冲突。
如示例中配置的name为“DCloud-RichAlert”,其中“DCloud”就是标识!
4.1 编译生成插件静态库.a文件
.a库必须是真机环境的,并且需要支持armv7和arm64架构,且Build Active Architecture Only设置为NO,您可以在终端用以下命令查看.a库支持的架构:
lipo -info libWeexDCRichAlert.a
4.2 编写package.json文件,按下列链接配置
点击查看详细配置说明
iOS平台 package.json 详细说明请查看这篇文档前面部分,会帮助您更好的理解如何配置 https://ask.dcloud.net.cn/article/35764
iOS 插件包 至少需要包含:package.json文件 和 ios文件夹(名称必须是小写的ios)里面包含 .a (.a库必须是lib开头命名,比如libWeexDCRichAlert.a)或framework。
4.3 生成.zip包
将DCloud-RichAlert文件夹打成zip包,zip包的名称为(DCloud-RichAlert.zip)然后准备提交插件市场,其中DCloud-RichAlert文件夹名称和package.json 里id的值一致,zip包的名称是id值。
五、如果想要共享给其他开发者,把这个插件提交插件市场
不提交插件市场,也可以把生成的插件放到HBuilderX里,然后提交云端打包使用,提交到云端打包之前确保插件在本地是调试通的,否则云端打包出问题,增加排查问题的难度。
<a id="isPlatformVersionAtLeast"/>
六、编写原生代码时注意事项
目前 HBuilderX 正式版云端打包机使用的Xcode版本为 10.X,Xcode11.0 及以上版本对@available(, *)
的实现做了调整打包后的.a
库不兼容低版本的Xcode, 所以如果使用Xcode 11.0及以上版本开发插件并且插件中代码用到了@available(, *)
关键字请按下图修改,否则可能导致打包失败。报错 Undefined symbols "___isPlatformVersionAtLeast"
(使用 HBuilderX alpha 版本没有此问题,正式版云端打包机近期会更新到最新的Xcode版本)
Tips
开发uni-app原生插件时注意不要开发广点通广告插件和穿山甲广告插件,目前不支持。
获取 UIViewController
因为 uni 框架机制,module 的 weexInstance 没有绑定 viewController,故
weexInstance.viewController
值为 nil,如果想通过 UIViewController 来跳转页面可使用下面的方法获取 UIViewController**
// 获取当前显示的 UIViewController
+ (UIViewController *)dc_findCurrentShowingViewController {
//获得当前活动窗口的根视图
UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];
return currentShowingVC;
}
+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc
{
// 递归方法 Recursive method
UIViewController *currentShowingVC;
if ([vc presentedViewController]) {
// 当前视图是被presented出来的
UIViewController *nextRootVC = [vc presentedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if ([vc isKindOfClass:[UITabBarController class]]) {
// 根视图为UITabBarController
UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else if ([vc isKindOfClass:[UINavigationController class]]){
// 根视图为UINavigationController
UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];
currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];
} else {
// 根视图为非导航类
currentShowingVC = vc;
}
return currentShowingVC;
}
获取页面可访问图片资源存储路径 (vue页面需要注意,nvue页面不存这个问题)
有些插件可能需要返回本地的图片路径给页面来显示,如果页面是
vue
的话是使用 WKWebview 渲染,访问本地图片资源可能会存在跨域问题访问不到图片资源,所以需要将图片存放到指定路径下,按照下面的方法获取图片存储路径即可
原生端实现
// 引用头文件
#import "PDRCoreApp.h"
#import "PDRCoreAppManager.h"
#import "PDRCoreAppInfo.h"
// 获取路径信息
PDRCoreAppInfo *appinfo = [PDRCore Instance].appManager.getMainAppInfo;
// 将图片存储到 appinfo.documentPath 路径下即可,可以创建子目录;
// 示例,原生图片存储路径为
NSString *imgPath = [appinfo.documentPath stringByAppendingPathComponent:@"test.png"];
js 端获取图片路径有两种方式
// 1.使用相对路径
var relativePath = "_doc/test.png"
// 2.使用平台的绝对路径
var docPath = plus.io.convertLocalFileSystemURL("_doc/");
var absolutePath = docPath + 'test.png'
欢迎有原生开发能力的朋友入群一起交流学习(入群请提供注册邮箱):
DCloud原生开发者群:
1群:256775471(已满)
2群:814228233(已满)
3群:455763866
Android原生插件开发参考:https://ask.dcloud.net.cn/article/35416
更多uni-app原生插件文档参考:uni-app原生插件开发指南