
uni-app 整包升级/更新方案
官方已发布APP升级中心,支持原生APP整包升级和wgt资源包升级,我们强烈推荐您使用,详见https://uniapp.dcloud.io/uniCloud/upgrade-center
==================================
如下是官方APP升级中心发布之前的文章,供老用户参考,新用户推荐使用https://uniapp.dcloud.io/uniCloud/upgrade-center。
使用 uni-app 开发,可将代码编译到iOS、Android、微信小程序等多个平台,升级时也需考虑多平台同步升级。
uni-app发布为小程序的升级模式较简单,只需将开发完的代码提交小程序后台,待审核通过后用户将自动升级。
App端的升级,又分为整包更新和资源热更新两种。
- 整包更新,即常规的整个App安装包重新下载安装。
- 资源热更新,即App并重新安装,里面的js等前端代码进行更新。
资源热更新另见文档:http://ask.dcloud.net.cn/article/35667
本文重点讲解整包更新。
一般iOS Appstore的安装包,无法直接更新。App启动后检查有新版本,只能调整到Appstore,然后用户在Appstore的详情页点击更新按钮。
而Android App,可以直接下载新的apk,只要包名和证书不变,就可以覆盖安装。
App升级,强烈推荐使用uniCloud。
- 把apk存放到uniCloud的cdn上,可以免费使用
- 有现成的插件,不用写升级逻辑,打好安装包,发布管理,检查升级都可以直接用,详见:https://ext.dcloud.net.cn/plugin?id=4470
如果不使用uniCloud,自己也可以写升级逻辑,下文讲解了常见的逻辑,但下文不是DCloud约定的强制逻辑,只是一般性常见做法的介绍。
接口约定
如下数据接口约定仅为示例,开发者可以自定义接口参数。
请求地址:https://www.example.com/update
请求方法:GET
请求数据:
{
"appid": plus.runtime.appid,
"version": plus.runtime.version
}
响应数据:
{
"status":1,//升级标志,1:需要升级;0:无需升级
"note": "修复bug1;\n修复bug2;",//release notes
"url": "http://www.example.com/uniapp.apk" //更新包下载地址
}
客户端实现
App启动时,向服务端上报当前版本号,服务端判断是否提示升级。
在App.vue的onLaunch中,发起升级检测请求,如下:
onLaunch: function () {
//#ifdef APP-PLUS
var server = "https://www.example.com/update"; //检查更新地址
var req = { //升级检测数据
"appid": plus.runtime.appid,
"version": plus.runtime.version
};
uni.request({
url: server,
data: req,
success: (res) => {
if (res.statusCode == 200 && res.data.status === 1) {
uni.showModal({ //提醒用户更新
title: "更新提示",
content: res.data.note,
success: (res) => {
if (res.confirm) {
plus.runtime.openURL(res.data.url);
}
}
})
}
}
})
//#endif
}
注意:App的升级检测代码必须使用条件编译,否则在非App环境由于不存在plus相关API,将会报错。
升级地址URL,如果是自行托管的App,就提供自己的包地址。如果是打开应用市场,那URL如下:
if (plus.os.name=="Android") {
appurl = "market://details?id=io.dcloud.hellouniapp"; //这个是通用应用市场,如果想指定某个应用商店,需要单独查这个应用商店的包名或scheme及参数
}
else{
appurl = "itms-apps://itunes.apple.com/cn/app/hello-uni-app/id1417078253";
}
服务端实现
根据客户端上报的版本号,比对服务端最新版本号,决定是否需要升级,若需升级则返回升级信息(rease notes、更新包地址等)
实现示例:
- 【推荐】通过uniCloud的云函数模板,快速实现升级检查逻辑,详情参考:https://ext.dcloud.net.cn/plugin?id=4470
- php示例代码:
header("Content-type:text/json");
$appid = $_GET["appid"];
$version = $_GET["version"]; //客户端版本号
$rsp = array("status" => 0); //默认返回值,不需要升级
if (isset($appid) && isset($version)) {
if ($appid === "__UNI__123456") { //校验appid
if ($version !== "1.0.1") { //这里是示例代码,真实业务上,最新版本号及relase notes可以存储在数据库或文件中
$rsp["status"] = 1;
$rsp["note"] = "修复bug1;\n修复bug2;"; //release notes
$rsp["url"] = "http://www.example.com/uniapp.apk"; //应用升级包下载地址
}
}
}
echo json_encode($rsp);
exit;
常见问题
- 版本检测需要打包app,真机运行基座无法测试。因为真机运行的plus.runtime.version是固定值。
官方已发布APP升级中心,支持原生APP整包升级和wgt资源包升级,我们强烈推荐您使用,详见https://uniapp.dcloud.io/uniCloud/upgrade-center
==================================
如下是官方APP升级中心发布之前的文章,供老用户参考,新用户推荐使用https://uniapp.dcloud.io/uniCloud/upgrade-center。
使用 uni-app 开发,可将代码编译到iOS、Android、微信小程序等多个平台,升级时也需考虑多平台同步升级。
uni-app发布为小程序的升级模式较简单,只需将开发完的代码提交小程序后台,待审核通过后用户将自动升级。
App端的升级,又分为整包更新和资源热更新两种。
- 整包更新,即常规的整个App安装包重新下载安装。
- 资源热更新,即App并重新安装,里面的js等前端代码进行更新。
资源热更新另见文档:http://ask.dcloud.net.cn/article/35667
本文重点讲解整包更新。
一般iOS Appstore的安装包,无法直接更新。App启动后检查有新版本,只能调整到Appstore,然后用户在Appstore的详情页点击更新按钮。
而Android App,可以直接下载新的apk,只要包名和证书不变,就可以覆盖安装。
App升级,强烈推荐使用uniCloud。
- 把apk存放到uniCloud的cdn上,可以免费使用
- 有现成的插件,不用写升级逻辑,打好安装包,发布管理,检查升级都可以直接用,详见:https://ext.dcloud.net.cn/plugin?id=4470
如果不使用uniCloud,自己也可以写升级逻辑,下文讲解了常见的逻辑,但下文不是DCloud约定的强制逻辑,只是一般性常见做法的介绍。
接口约定
如下数据接口约定仅为示例,开发者可以自定义接口参数。
请求地址:https://www.example.com/update
请求方法:GET
请求数据:
{
"appid": plus.runtime.appid,
"version": plus.runtime.version
}
响应数据:
{
"status":1,//升级标志,1:需要升级;0:无需升级
"note": "修复bug1;\n修复bug2;",//release notes
"url": "http://www.example.com/uniapp.apk" //更新包下载地址
}
客户端实现
App启动时,向服务端上报当前版本号,服务端判断是否提示升级。
在App.vue的onLaunch中,发起升级检测请求,如下:
onLaunch: function () {
//#ifdef APP-PLUS
var server = "https://www.example.com/update"; //检查更新地址
var req = { //升级检测数据
"appid": plus.runtime.appid,
"version": plus.runtime.version
};
uni.request({
url: server,
data: req,
success: (res) => {
if (res.statusCode == 200 && res.data.status === 1) {
uni.showModal({ //提醒用户更新
title: "更新提示",
content: res.data.note,
success: (res) => {
if (res.confirm) {
plus.runtime.openURL(res.data.url);
}
}
})
}
}
})
//#endif
}
注意:App的升级检测代码必须使用条件编译,否则在非App环境由于不存在plus相关API,将会报错。
升级地址URL,如果是自行托管的App,就提供自己的包地址。如果是打开应用市场,那URL如下:
if (plus.os.name=="Android") {
appurl = "market://details?id=io.dcloud.hellouniapp"; //这个是通用应用市场,如果想指定某个应用商店,需要单独查这个应用商店的包名或scheme及参数
}
else{
appurl = "itms-apps://itunes.apple.com/cn/app/hello-uni-app/id1417078253";
}
服务端实现
根据客户端上报的版本号,比对服务端最新版本号,决定是否需要升级,若需升级则返回升级信息(rease notes、更新包地址等)
实现示例:
- 【推荐】通过uniCloud的云函数模板,快速实现升级检查逻辑,详情参考:https://ext.dcloud.net.cn/plugin?id=4470
- php示例代码:
header("Content-type:text/json");
$appid = $_GET["appid"];
$version = $_GET["version"]; //客户端版本号
$rsp = array("status" => 0); //默认返回值,不需要升级
if (isset($appid) && isset($version)) {
if ($appid === "__UNI__123456") { //校验appid
if ($version !== "1.0.1") { //这里是示例代码,真实业务上,最新版本号及relase notes可以存储在数据库或文件中
$rsp["status"] = 1;
$rsp["note"] = "修复bug1;\n修复bug2;"; //release notes
$rsp["url"] = "http://www.example.com/uniapp.apk"; //应用升级包下载地址
}
}
}
echo json_encode($rsp);
exit;
常见问题
- 版本检测需要打包app,真机运行基座无法测试。因为真机运行的plus.runtime.version是固定值。

个推的推送成功解决
首先声明,个推推送,官方文档是,android可以推送通知和透传消息,ios只能推送透传消息。
但在mui实现的时候,android端推送的通知,点击以后无法监听。经过苦逼的程序猿的苦苦探求,终于发现可以解决的一种方式了:
首先推送的时候,不能用通知推送,用透传消息的方式进行推送(透传消息可以监听到的),然后通过mui的的创建通知的方法,把获取的到的透传消息转为通知,这个时候的通知点击的时候就可以监听了,这个方法本人经过试验,可以成功的。代码如下
document.addEventListener("plusready", function() {
// 监听点击消息事件
plus.push.addEventListener("click", function(msg) {
// showAlert(JSON.stringify(msg))
switch(msg.payload) {
case "LocalMSG":
showAlert("点击通知本地创建消息启动:" + msg.content);
break;
default:
showAlert("点击离线推送消息启动:" + msg.content);
break;
}
}, false);
// 监听在线消息事件
plus.push.addEventListener("receive", function(msg) {
if(msg.aps) { // Apple APNS message
showAlert("接收到在线APNS消息:");
} else {
showAlert("接收到在线透传消息:" + msg.content );
}
createLocalPushMsg(msg);
}, false);
}, false);
function showAlert(tiltle) {
alert(tiltle);
}
function bindAlias(alias) {
var PushManager = plus.android.importClass("com.igexin.sdk.PushManager");
var mainActivity = plus.android.runtimeMainActivity();
var i = PushManager.getInstance().bindAlias(mainActivity, alias);
}
function unbindAlias(alias) {
var PushManager = plus.android.importClass("com.igexin.sdk.PushManager");
var mainActivity = plus.android.runtimeMainActivity();
var i = PushManager.getInstance().unBindAlias(mainActivity, alias);
}
function getClientid() {
var PushManager = plus.android.importClass("com.igexin.sdk.PushManager");
var mainActivity = plus.android.runtimeMainActivity();
return PushManager.getInstance().getClientid(mainActivity);
}
//创建本地通知
function createLocalPushMsg(msg){
var options = {cover:false};
var str = msg.content;
plus.push.createMessage( str, "LocalMSG", options );
}
//拉起服务的代码是这样的 :这个代码经测试,有或没有都可以收到通知消息
function startService() {
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass('android.content.Intent');
var intent = new Intent();
// var serviceName = 'com.igexin.sdk.PushServiceForUser';
var serviceName = 'com.igexin.sdk.PushService';//把这里换成其他Service的名字,也可以实现拉取自定义的Service
intent.setClassName(main, serviceName);
main.startService(intent);
}
首先声明,个推推送,官方文档是,android可以推送通知和透传消息,ios只能推送透传消息。
但在mui实现的时候,android端推送的通知,点击以后无法监听。经过苦逼的程序猿的苦苦探求,终于发现可以解决的一种方式了:
首先推送的时候,不能用通知推送,用透传消息的方式进行推送(透传消息可以监听到的),然后通过mui的的创建通知的方法,把获取的到的透传消息转为通知,这个时候的通知点击的时候就可以监听了,这个方法本人经过试验,可以成功的。代码如下
document.addEventListener("plusready", function() {
// 监听点击消息事件
plus.push.addEventListener("click", function(msg) {
// showAlert(JSON.stringify(msg))
switch(msg.payload) {
case "LocalMSG":
showAlert("点击通知本地创建消息启动:" + msg.content);
break;
default:
showAlert("点击离线推送消息启动:" + msg.content);
break;
}
}, false);
// 监听在线消息事件
plus.push.addEventListener("receive", function(msg) {
if(msg.aps) { // Apple APNS message
showAlert("接收到在线APNS消息:");
} else {
showAlert("接收到在线透传消息:" + msg.content );
}
createLocalPushMsg(msg);
}, false);
}, false);
function showAlert(tiltle) {
alert(tiltle);
}
function bindAlias(alias) {
var PushManager = plus.android.importClass("com.igexin.sdk.PushManager");
var mainActivity = plus.android.runtimeMainActivity();
var i = PushManager.getInstance().bindAlias(mainActivity, alias);
}
function unbindAlias(alias) {
var PushManager = plus.android.importClass("com.igexin.sdk.PushManager");
var mainActivity = plus.android.runtimeMainActivity();
var i = PushManager.getInstance().unBindAlias(mainActivity, alias);
}
function getClientid() {
var PushManager = plus.android.importClass("com.igexin.sdk.PushManager");
var mainActivity = plus.android.runtimeMainActivity();
return PushManager.getInstance().getClientid(mainActivity);
}
//创建本地通知
function createLocalPushMsg(msg){
var options = {cover:false};
var str = msg.content;
plus.push.createMessage( str, "LocalMSG", options );
}
//拉起服务的代码是这样的 :这个代码经测试,有或没有都可以收到通知消息
function startService() {
var main = plus.android.runtimeMainActivity();
var Intent = plus.android.importClass('android.content.Intent');
var intent = new Intent();
// var serviceName = 'com.igexin.sdk.PushServiceForUser';
var serviceName = 'com.igexin.sdk.PushService';//把这里换成其他Service的名字,也可以实现拉取自定义的Service
intent.setClassName(main, serviceName);
main.startService(intent);
}
收起阅读 »

应用切到前台,自动刷新当前页面
有一个问题:应用长时间停留在后台,再切回前台,因为应用长时间未刷新页面,导致的页面数据过于陈旧,与数据库不一致。
由此引申出来的需求:应用切换到后台1分钟之后,再切换到前台,自动刷新页面。
js 实现:
(function () {
var pauseTimestamp;
// 切到前台的时候
document.addEventListener( "resume", function () {
//切换到前台的时间戳
var resumeTimestamp = Date.now();
//如果应用已经切到后台1分钟以上了
if(resumeTimestamp - pauseTimestamp > 60000){
// if(resumeTimestamp - pauseTimestamp > 5000){
//刷新当前页
location.reload();
}
} );
// 切到后台的时候
document.addEventListener( "pause", function () {
//得到当前时间戳
pauseTimestamp = Date.now();
} );
})();
有一个问题:应用长时间停留在后台,再切回前台,因为应用长时间未刷新页面,导致的页面数据过于陈旧,与数据库不一致。
由此引申出来的需求:应用切换到后台1分钟之后,再切换到前台,自动刷新页面。
js 实现:
(function () {
var pauseTimestamp;
// 切到前台的时候
document.addEventListener( "resume", function () {
//切换到前台的时间戳
var resumeTimestamp = Date.now();
//如果应用已经切到后台1分钟以上了
if(resumeTimestamp - pauseTimestamp > 60000){
// if(resumeTimestamp - pauseTimestamp > 5000){
//刷新当前页
location.reload();
}
} );
// 切到后台的时候
document.addEventListener( "pause", function () {
//得到当前时间戳
pauseTimestamp = Date.now();
} );
})();
收起阅读 »

这样就可以在每次启动的时候自动启动啦!
这样就可以在每次启动的时候自动启动啦!
Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架
ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作
Hibernate提供了对关系型数据库增删改成操作
2.1主流的ORM框架
?JPA Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系(只有接口规范)
?Hibernate 最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL
?MyBatis 本是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架
?Apache DBUtils 、Spring JDBCTemplate
2.2Hibernate 优势
?Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
?Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作 session.save(User);
?Hibernate使用java的反射机制
?Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系。。
这样就可以在每次启动的时候自动启动啦!
Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架
ORM 就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作
Hibernate提供了对关系型数据库增删改成操作
2.1主流的ORM框架
?JPA Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系(只有接口规范)
?Hibernate 最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL
?MyBatis 本是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架
?Apache DBUtils 、Spring JDBCTemplate
2.2Hibernate 优势
?Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码
?Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作 session.save(User);
?Hibernate使用java的反射机制
?Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系。。

PHP编程中如何将多种数据存入一个字段里
无论是商品,拍品,还是产品。都有所对应的规格,不同的拍品所对应的规格不同,那么所填写的规格也就不同,对于某些产品来说有些规格需要填写,而有写规格不需要填写,那么在设计数据字段是为了避免不必要的字段,我们可以把所有的规格都存入了一个字段里。下面就来分享一下源码。
1、Php插入数据库。
php代码如下:
$spec="";
if($data['size']!=""){
$spec.="尺寸".":".$data['size'].",";
}
if($data['weight']!=""){
$spec.="重量".":".$data['weight'].",";
}
if($data['diameter']!=""){
$spec.="直径".":".$data['diameter'].",";
}
if($data['chang']!=""){
$spec.="长".":".$data['chang'].",";
}
if($data['height']!=""){
$spec.="高".":".$data['height'].",";
}
$data['spec']=rtrim($spec,",");
2、查询规格代码。
php代码如下:
<php>$array=explode(',',$list['spec']);
foreach($array as $k=>$v){
$arr[]=explode(':',$v);
};
foreach($arr as $k=>$v){
$t[$v[0]]=$v[1];
};
</php>
<li class=" ">
<span class="">尺寸</span>
<input class="cans1" type="text" <php>if(array_key_exists("尺寸",$t)){ $s=$t['尺寸']; }</php> value='{$s}' name="size" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
<li class=" ">
<span class="">重量</span>
<input class="cans2 " type="text" <php>if(array_key_exists("重量",$t)){ $z=$t['重量'];}</php> value='{$z}' name="weight" placeholder="0"/>
<span class="cans">单位(g)</span>
</li>
<li class=" ">
<span class="">直径</span>
<input class="cans3" type="text" <php>if(array_key_exists("直径",$t)){ $j=$t['直径'];}</php> value='{$j}' name="diameter" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
<li class=" ">
<span class="">长</span>
<input class="cans4" type="text" <php>if(array_key_exists("长",$t)){ $c=$t['长'];}</php> value='{$c}' name="chang" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
<li class=" ">
<span class="">高</span>
<input class="cans5" type="text" <php>if(array_key_exists("高",$t)){ $g=$t['高'];}</php> value='{$g}' name="height" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
那么到这里就结束了,现在大家应该知道如何存储了吧,如果大家还是存在疑问的话,可以留言咨询。
本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。
无论是商品,拍品,还是产品。都有所对应的规格,不同的拍品所对应的规格不同,那么所填写的规格也就不同,对于某些产品来说有些规格需要填写,而有写规格不需要填写,那么在设计数据字段是为了避免不必要的字段,我们可以把所有的规格都存入了一个字段里。下面就来分享一下源码。
1、Php插入数据库。
php代码如下:
$spec="";
if($data['size']!=""){
$spec.="尺寸".":".$data['size'].",";
}
if($data['weight']!=""){
$spec.="重量".":".$data['weight'].",";
}
if($data['diameter']!=""){
$spec.="直径".":".$data['diameter'].",";
}
if($data['chang']!=""){
$spec.="长".":".$data['chang'].",";
}
if($data['height']!=""){
$spec.="高".":".$data['height'].",";
}
$data['spec']=rtrim($spec,",");
2、查询规格代码。
php代码如下:
<php>$array=explode(',',$list['spec']);
foreach($array as $k=>$v){
$arr[]=explode(':',$v);
};
foreach($arr as $k=>$v){
$t[$v[0]]=$v[1];
};
</php>
<li class=" ">
<span class="">尺寸</span>
<input class="cans1" type="text" <php>if(array_key_exists("尺寸",$t)){ $s=$t['尺寸']; }</php> value='{$s}' name="size" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
<li class=" ">
<span class="">重量</span>
<input class="cans2 " type="text" <php>if(array_key_exists("重量",$t)){ $z=$t['重量'];}</php> value='{$z}' name="weight" placeholder="0"/>
<span class="cans">单位(g)</span>
</li>
<li class=" ">
<span class="">直径</span>
<input class="cans3" type="text" <php>if(array_key_exists("直径",$t)){ $j=$t['直径'];}</php> value='{$j}' name="diameter" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
<li class=" ">
<span class="">长</span>
<input class="cans4" type="text" <php>if(array_key_exists("长",$t)){ $c=$t['长'];}</php> value='{$c}' name="chang" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
<li class=" ">
<span class="">高</span>
<input class="cans5" type="text" <php>if(array_key_exists("高",$t)){ $g=$t['高'];}</php> value='{$g}' name="height" placeholder="0"/>
<span class="cans">单位(cm)</span>
</li>
那么到这里就结束了,现在大家应该知道如何存储了吧,如果大家还是存在疑问的话,可以留言咨询。
本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处。
收起阅读 »
uni-app 跨平台应用开发视频教程促销中!!只需88元即可学习全套课程
uni-app 跨平台应用开发教程已经发布
一套代码可以发布为ios Android app、小程序。
课程总计25节 覆盖了开发中常用的知识点,知识点覆盖率 90% 以上!
通过课程您将学会:
1、uni-app
2、小程序
3、vue 基础
课程购买地址
https://ke.qq.com/course/323825?tuin=4f8da6

uni-app 跨平台应用开发教程已经发布
一套代码可以发布为ios Android app、小程序。
课程总计25节 覆盖了开发中常用的知识点,知识点覆盖率 90% 以上!
通过课程您将学会:
1、uni-app
2、小程序
3、vue 基础
课程购买地址
https://ke.qq.com/course/323825?tuin=4f8da6

uni-app的markdown富文本编辑器插件
此插件仅简单封装了一下,有复杂需求的可以自己扩展,图片上传需要在插件里配置uni.upload的url以及回调信息.
参数名 | 类型 | 描述 |
---|---|---|
textareaData | String | 绑定的markdown文本 |
textareaHtml | String | markdwon转义后的html |
showPreview | Boolean | 是否显示预览view |

HBuilder
其实我是一个不太爱吐曹的,今儿把我惹急了
HBuilder确实是个不错的工具,用了近两年了,很不错
前两天接到一个项目,要做NFC卡读取的,结果输入了密钥,死活都验证不通过,找了各种方式,无果
最后放弃了,得出的结论是,HBuilder现阶段压根没法实现NFC卡的读取,逼的我去学原生安卓来实现功能,还好比较简单,要源码的可以找我
然后HBuilder升级到9.x版本,真机调试安卓4.X版本的系统,死活说 Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES],
最后找到8.x版本才正常运行起来
好吧,哥被搞的没脾气了,拜托好好整,哥还要依赖你赚钱的
其实我是一个不太爱吐曹的,今儿把我惹急了
HBuilder确实是个不错的工具,用了近两年了,很不错
前两天接到一个项目,要做NFC卡读取的,结果输入了密钥,死活都验证不通过,找了各种方式,无果
最后放弃了,得出的结论是,HBuilder现阶段压根没法实现NFC卡的读取,逼的我去学原生安卓来实现功能,还好比较简单,要源码的可以找我
然后HBuilder升级到9.x版本,真机调试安卓4.X版本的系统,死活说 Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES],
最后找到8.x版本才正常运行起来
好吧,哥被搞的没脾气了,拜托好好整,哥还要依赖你赚钱的

使用5+sdk的方式,封装一个环信或融云等im厂商的原生sdk到js层,给自己的js用
集成环信或融云等IM,满足IOS和andriod之间的语音及视频通信
集成环信或融云等IM,满足IOS和andriod之间的语音及视频通信

如何简单的将xml格式数据转换成array数据
对于将xml格式数据转换成array数据,很多初学者应该都不知道,那么今天就来为大家分析解答一下吧。
PHP中的$_POST和file_get_content('php://input')
$_POST
老规矩,查看官方文档,全世界都会骗你,但是文档不会骗你。
$HTTP_POST_VARS [已弃用]$_POST -- $HTTP_POST_VARS [已弃用] — HTTP POST 变量当 HTTP POST 请求的 Content-Type 是 application/x-www-form-urlencoded 或 multipart/form-data 时,会将变量以关联数组形式传入当前脚本。$HTTP_POST_VARS 包含相同的信息,但它不是一个超全局变量。 (注意 $HTTP_POST_VARS 和 $_POST 是不同的变量,PHP 处理它们的方式不同)
一看文档就知道全部信息了,$_POST支持的request中的header中的content-type的类型只有application/x-www-form-urlencoded 或 multipart/form-data 。
当我们使用guzzle的时候它会根据你传入的params是否是数组进行判断,如果不是数组会在body中。但是如果是数组它就会按照json方式进行传递,content-type会application/json的方式当然不会被$_POST进行处理。所以,这边是没有毛病的。但是,难道因为用了这个组件就不进行这个类型处理了吗?显然不行。
php://input
php:// — 访问各个输入/输出流(I/O streams)PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype="multipart/form-data" 的时候 php://input 是无效的。Note: 在 PHP 5.6 之前 php://input 打开的数据流只能读取一次; 数据流不支持 seek 操作。 不过,依赖于 SAPI 的实现,请求体数据被保存的时候, 它可以打开另一个 php://input 数据流并重新读取。 通常情况下,这种情况只是针对 POST 请求,而不是其他请求方式,比如 PUT 或者 PROPFIND。
这个东西说实话,就是$_POST基于这个进行封装处理了一层。它能够获取到最原始的数据,不管你是什么content-type,它都能够获取到数据。所以,当我们的post的过来的数据是原始数据的时候,比如说是application/json或者' application/x-json,text/xml, application/xml,application/x-xml这些时候,$_POST都是无法获取到数据的。此刻,我们就需要通过php://input进行获取原始数据了。但是,原始数据并不是我们想要的最终格式。因此,我们需要进行封装一层。
parseRequest
request类其实是很好写的,但是一般的类中对post方式传递参数还是老方式。因此,我改写了一般的类中获取post的参数,对于所有post请求方式的方法,针对不同的content-type进行数据获取和原始数据的解析,弄成我们想要的最终数组。
核心代码:
public static function post($key = NULL, $default = NULL) { $data = [];if(in_array($_SERVER['CONTENT_TYPE'],self::$formats['json'])){ $data = file_get_contents('php://input'); $data = json_decode($data,true); } if(in_array($_SERVER['CONTENT_TYPE'],self::$formats['xml'])){ $data = file_get_contents('php://input'); $data = DataParser::toArray($data); } if($key==null && !empty($data)){ return $data; }if(!empty($data)){ return isset($data[$key]) ? $data[$key] : $default; } return static::lookup($_POST, $key, $default); }
在类中我们会定义几个conten-type的format数组,通过$_SERVER['CONTENT_TYPE']来进行判断处理,针对性的进行数据获取和转换。
protected static $formats = array( 'html' => array('text/html', 'application/xhtml+xml'), 'txt' => array('text/plain'),'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), 'css' => array('text/css'), 'json'=> array('application/json', 'application/x-json'), 'xml' => array('text/xml', 'application/xml', 'application/x-xml'),'rdf' => array('application/rdf+xml'), 'atom' => array('application/atom+xml'), 'rss' => array('application/rss+xml'), );
针对xml格式的数据,同时封装了数据处理类
public static function toArray($xml) { if (!$xml) { return false; } // 检查xml是否合法 $xml_parser = xml_parser_create();if (!xml_parse($xml_parser, $xml, true)) { xml_parser_free($xml_parser); return false; } libxml_disable_entity_loader(true); $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $data; }
就是简单的将xml格式数据转换成array数据。如果大家还存在疑问的话,可以留言咨询。本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处!
对于将xml格式数据转换成array数据,很多初学者应该都不知道,那么今天就来为大家分析解答一下吧。
PHP中的$_POST和file_get_content('php://input')
$_POST
老规矩,查看官方文档,全世界都会骗你,但是文档不会骗你。
$HTTP_POST_VARS [已弃用]$_POST -- $HTTP_POST_VARS [已弃用] — HTTP POST 变量当 HTTP POST 请求的 Content-Type 是 application/x-www-form-urlencoded 或 multipart/form-data 时,会将变量以关联数组形式传入当前脚本。$HTTP_POST_VARS 包含相同的信息,但它不是一个超全局变量。 (注意 $HTTP_POST_VARS 和 $_POST 是不同的变量,PHP 处理它们的方式不同)
一看文档就知道全部信息了,$_POST支持的request中的header中的content-type的类型只有application/x-www-form-urlencoded 或 multipart/form-data 。
当我们使用guzzle的时候它会根据你传入的params是否是数组进行判断,如果不是数组会在body中。但是如果是数组它就会按照json方式进行传递,content-type会application/json的方式当然不会被$_POST进行处理。所以,这边是没有毛病的。但是,难道因为用了这个组件就不进行这个类型处理了吗?显然不行。
php://input
php:// — 访问各个输入/输出流(I/O streams)PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype="multipart/form-data" 的时候 php://input 是无效的。Note: 在 PHP 5.6 之前 php://input 打开的数据流只能读取一次; 数据流不支持 seek 操作。 不过,依赖于 SAPI 的实现,请求体数据被保存的时候, 它可以打开另一个 php://input 数据流并重新读取。 通常情况下,这种情况只是针对 POST 请求,而不是其他请求方式,比如 PUT 或者 PROPFIND。
这个东西说实话,就是$_POST基于这个进行封装处理了一层。它能够获取到最原始的数据,不管你是什么content-type,它都能够获取到数据。所以,当我们的post的过来的数据是原始数据的时候,比如说是application/json或者' application/x-json,text/xml, application/xml,application/x-xml这些时候,$_POST都是无法获取到数据的。此刻,我们就需要通过php://input进行获取原始数据了。但是,原始数据并不是我们想要的最终格式。因此,我们需要进行封装一层。
parseRequest
request类其实是很好写的,但是一般的类中对post方式传递参数还是老方式。因此,我改写了一般的类中获取post的参数,对于所有post请求方式的方法,针对不同的content-type进行数据获取和原始数据的解析,弄成我们想要的最终数组。
核心代码:
public static function post($key = NULL, $default = NULL) { $data = [];if(in_array($_SERVER['CONTENT_TYPE'],self::$formats['json'])){ $data = file_get_contents('php://input'); $data = json_decode($data,true); } if(in_array($_SERVER['CONTENT_TYPE'],self::$formats['xml'])){ $data = file_get_contents('php://input'); $data = DataParser::toArray($data); } if($key==null && !empty($data)){ return $data; }if(!empty($data)){ return isset($data[$key]) ? $data[$key] : $default; } return static::lookup($_POST, $key, $default); }
在类中我们会定义几个conten-type的format数组,通过$_SERVER['CONTENT_TYPE']来进行判断处理,针对性的进行数据获取和转换。
protected static $formats = array( 'html' => array('text/html', 'application/xhtml+xml'), 'txt' => array('text/plain'),'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), 'css' => array('text/css'), 'json'=> array('application/json', 'application/x-json'), 'xml' => array('text/xml', 'application/xml', 'application/x-xml'),'rdf' => array('application/rdf+xml'), 'atom' => array('application/atom+xml'), 'rss' => array('application/rss+xml'), );
针对xml格式的数据,同时封装了数据处理类
public static function toArray($xml) { if (!$xml) { return false; } // 检查xml是否合法 $xml_parser = xml_parser_create();if (!xml_parse($xml_parser, $xml, true)) { xml_parser_free($xml_parser); return false; } libxml_disable_entity_loader(true); $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $data; }
就是简单的将xml格式数据转换成array数据。如果大家还存在疑问的话,可以留言咨询。本文由专业的郑州app开发公司燚轩科技整理发布,原创不易,如需转载请注明出处!
收起阅读 »
拦截再按一次退出应用,改成单击back隐藏到后台
大家好,今天在给大家分享一下uniapp开发经验。关于常规的我就不说了。相信大家在开发的过程中难免会遇到需要APP后台运行的功能,这个使用5+就可以实现的。
let main = plus.android.runtimeMainActivity();
//为了防止快速点按返回键导致程序退出重写quit方法改为隐藏至后台
plus.runtime.quit = function(){
main.moveTaskToBack(false);
};
//重写toast方法如果内容为 ‘再按一次退出应用’ 就隐藏应用,其他正常toast
plus.nativeUI.toast = (function(str){
if(str == '再按一次退出应用'){
main.moveTaskToBack(false);
return false;
}else{
uni.showToast({
title:str,
icon:'none',
})
}
});
大家好,今天在给大家分享一下uniapp开发经验。关于常规的我就不说了。相信大家在开发的过程中难免会遇到需要APP后台运行的功能,这个使用5+就可以实现的。
let main = plus.android.runtimeMainActivity();
//为了防止快速点按返回键导致程序退出重写quit方法改为隐藏至后台
plus.runtime.quit = function(){
main.moveTaskToBack(false);
};
//重写toast方法如果内容为 ‘再按一次退出应用’ 就隐藏应用,其他正常toast
plus.nativeUI.toast = (function(str){
if(str == '再按一次退出应用'){
main.moveTaskToBack(false);
return false;
}else{
uni.showToast({
title:str,
icon:'none',
})
}
});
其他功能插件:
1、uniapp图片裁剪插件
2、swiper + scroll-view 实现下拉刷新

uniapp离线打包和升级这样可以不???????????
Android试了下,将unpackage->dist->build->app-plus->appname 下面的文件全部打包压缩成wgt.
然后在程序里面检查wgt进行安装.发现UI会变动wgt里面的ui,具体没细看.IOS看.
有这样做的小伙伴么.
那么,
问题一:
离线打包,是不是可以直接用 unpackage下面的的资源 + 5+plus离线打包的壳自己打包,这个有没有啥问题.
问题二:
android 连结HX运行起来的UI和云端打包的UI居然不一致(居中和不居中的问题)??
Android是8.1.0.
问题三:
mac下面
HX 0.1.47.20180821-alpha 无法升级到 0.1.47.20180823-alpha
直接把应用程序里面的HX删掉,安装官网最新的0.1.47.20180823-alpha版本,打开还是HX 0.1.47.20180821-alpha.
Android试了下,将unpackage->dist->build->app-plus->appname 下面的文件全部打包压缩成wgt.
然后在程序里面检查wgt进行安装.发现UI会变动wgt里面的ui,具体没细看.IOS看.
有这样做的小伙伴么.
那么,
问题一:
离线打包,是不是可以直接用 unpackage下面的的资源 + 5+plus离线打包的壳自己打包,这个有没有啥问题.
问题二:
android 连结HX运行起来的UI和云端打包的UI居然不一致(居中和不居中的问题)??
Android是8.1.0.
问题三:
mac下面
HX 0.1.47.20180821-alpha 无法升级到 0.1.47.20180823-alpha
直接把应用程序里面的HX删掉,安装官网最新的0.1.47.20180823-alpha版本,打开还是HX 0.1.47.20180821-alpha.