APICloud开发记录【持续】
文章目录
1、开发要求
Web Storm 2018.1
2、创建项目
2.1 WebStorm插件操作
- 基本插件安装:https://docs.apicloud.com/Dev-Tools/webStorm-apicloud-plugin
- WebStorm Wifi真机同步和Wifi真机预览:https://docs.apicloud.com/Dev-Tools/webStorm-wifi-sync
(1) 除了IOS一块,其余均建议阅读并操作
(2) 将webStorm-APICloud加入到项目中
(3) 安装好需要的插件
2.2 网页创建
- https://www.apicloud.com 官网注册账号
- https://www.apicloud.com/console 点击【创建应用】
具体创建应用操作步骤:https://docs.apicloud.com/APICloud/creating-first-app
2.3 下载代码
(1) 采用SVN下载代码,然后导入到Web Storm
(2) 采用Subversion
2.4 App创建以及测试
(1) 新建一个底部导航应用
(2) 启动Wifi真机测试
- 开启服务
- 手机输入ip以及端口,点击连接;然后在Web Storm中右键项目,点击【Wifi真机同步】
3、Api的方法
具体API:https://docs.apicloud.com/Client-API/
API.js文档:https://docs.apicloud.com/Front-end-Framework/framework-dev-guide#37
3.1 监听返回键
api.addEventListener({
name: 'keyback'
}, function (ret, err) {
api.confirm({
title: '提示',
msg: "确认退出应用?",
buttons: ['确定', '取消']
}, function (ret, err) {
var index = ret.buttonIndex;
if (index == 1) {
api.closeWin();
}
return;
});
});
3.2 拨打电话
api.call({
type: 'tel', // 直接拨打,无任何提示
number: '10086' // 电话号码
});
参数说明:https://docs.apicloud.com/Client-API/api#7
3.3 跨页面执行js脚本
execScript:在指定 window 或者 frame 中执行脚本,对于 frameGroup 里面的 frame 也有效,若 name 和 frameName 都未指定,则在当前 window 中执行脚本,具体执行逻辑见补充说明。
execScript({params})
4、config.xml文件说明
<?xml version="1.0" encoding="UTF-8"?><widget id="A6080528176396" version="0.0.1">
<name>demo1_nav</name> <!--app的名称-->
<description>
Example For APICloud.
</description>
<author email="[email protected]" href="http://www.apicloud.com">
Developer
</author>
<content src="grid.html"/> <!--默认app进入的主页地址-->
<preference name="appBackground" value="rgba(0,0,0,0)"/>
<preference name="windowBackground" value="rgba(0,0,0,0)"/>
<preference name="frameBackgroundColor" value="rgba(0,0,0,0)"/>
<preference name="autoLaunch" value="true"/>
<preference name="autoUpdate" value="true"/>
<preference name="smartUpdate" value="false"/>
<preference name="debug" value="false"/>
<preference name="statusBarAppearance" value="true"/>
<permission name="location"/>
<permission name="internet"/>
<access origin="*"/>
</widget>
5、 WeiUI集成
5.1 将样式以及JS加入到项目中
- 下载zip,将build中的weui.css样式文件加入到项目中的css文件夹中
https://github.com/lihongxun945/jquery-weui/releases
5.2 weiUI官网
- 在WeiUi官网查看对应组件的样式,并移植到页面中
6、上拉刷新
如果页面条目过多,需要进行分页显示,用户上滑数据加载下一页数据,具体实现如下:
6.1 父页面[只有header]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo-header</title>
<!--标准mui.css-->
<link rel="stylesheet" href="../../css/mui.min.css">
<!--App自定义的css-->
<link rel="stylesheet" type="text/css" href="../../css/app.css"/>
<link rel="stylesheet" type="text/css" href="../../css/my.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav" id="topbar">
<a class=" mui-icon mui-icon-left-nav mui-pull-left" href="#" onclick="goBeforePage()"></a>
<h1 class="mui-title" id="title">示例</h1>
</header>
<div class="mui-content">
<ul class="mui-table-view mui-table-view-chevron" id="showResult">
</ul>
</div>
<script src="../../js/mui.js"></script>
<script type="text/javascript" src="../../script/api.js"></script>
<script type="text/javascript" src="../../js/request.js"></script>
<script type="text/javascript" src="../../js/dot.min.js"></script>
<script type="text/javascript" src="../../js/toastUtils.js"></script>
<script type="text/javascript" src="../../js/error.js"></script>
<script type="text/javascript">
apiready = function () {
var header = $api.byId('topbar');
//适配iOS7+,Android4.4+状态栏沉浸式效果,详见config文档statusBarAppearance字段
// $api.fixStatusBar(header);
//动态计算header的高度,因iOS7+和Android4.4+上支持沉浸式效果,
//因此header的实际高度可能为css样式中声明的44px加上设备状态栏高度
//其中,IOS状态栏高度为20px,Android为25px
var headerH = $api.offset(header).h;
//frame的高度为当前window高度减去header和footer的高度
var frameH = api.winHeight - headerH;
api.openFrame({
name: 'detection-search-result-list',
url: './detection-search-result-list.html',
rect: {
x: 0,
y: headerH,
w: api.winWidth,
h: frameH
},
pageParam: {
itemsId: api.pageParam.itemsName,
itemsId: api.pageParam.itemsId
},
bounces: true,
bgColor: 'rgba(0,0,0,0)',
vScrollBarEnabled: true,
hScrollBarEnabled: true
});
$api.dom('#title').innerHTML = api.pageParam.itemsName;
};
// 返回上一个页面
function goBeforePage() {
api.closeWin();
}
</script>
</body>
</html>
6.2 子页面[list页面]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>检测-检测记录</title>
<!--标准mui.css-->
<link rel="stylesheet" href="../../css/mui.min.css">
<!--App自定义的css-->
<link rel="stylesheet" type="text/css" href="../../css/app.css"/>
<link rel="stylesheet" type="text/css" href="../../css/my.css"/>
</head>
<body>
<div class="mui-content">
<ul class="mui-table-view mui-table-view-chevron" id="showResult">
</ul>
</div>
<script src="../../js/mui.js"></script>
<script type="text/javascript" src="../../script/api.js"></script>
<script type="text/javascript" src="../../js/request.js"></script>
<script type="text/javascript" src="../../js/dot.min.js"></script>
<script id="searchResultTemp" type="text/x-dot-template">
{{ for(var x in it) { }}
<li class="mui-table-view-cell mui-collapse">
<a class="mui-navigate-right" href="#">{{=it[x].date}}</a>
<ul class="mui-table-view mui-table-view-chevron">
{{ for(var t in it[x].result) { }}
<li class="mui-table-view-cell"><a href="#">
{{? it[x].result[t].userName!==null }}
{{=it[x].result[t].userName}}
{{?? it[x].result[t].userName==null}}
----
{{??}}
{{?}}
{{=it[x].result[t].detectionResult}}
{{=it[x].result[t].detectionAnalysis}}
{{? it[x].result[t].age!==null }}
{{=it[x].result[t].age}}岁
{{?? it[x].result[t].age==null}}
----
{{??}}
{{?}}
{{? it[x].result[t].sex === "0" }}
女
{{?? it[x].result[t].sex === "1"}}
男
{{??}}
{{?}}
</a>
</li>
{{ } }}
</ul>
</li>
{{ } }}
</script>
<script type="text/javascript" src="../../js/toastUtils.js"></script>
<script type="text/javascript" src="../../js/error.js"></script>
<script type="text/javascript">
var pageIndex = 0;
var pageSize = 15;
var userId = "";
var itemsId = "";
apiready = function () {
api.addEventListener({name: 'scrolltobottom'}, function (ret, err) {
toDoRequest();
});
userId = $api.getStorage(CURRENT_USER)["id"];
itemsId = api.pageParam.itemsId;
toDoRequest();
};
// 刷新 初始化加载
function toDoRequest() {
showProgress('加载中', '加载数据中.....');
API.detection.getDetectionByItems(userId, itemsId, pageIndex, pageSize, function (ret, err) {
api.refreshHeaderLoadDone(); //复位下拉刷新
api.hideProgress();
if (!globalException(err)) {
return;
}
pageIndex++;
if(ret["data"]==null||ret["data"].length==0){
showToast('无更多数据加载',1000);
return ;
}
var evaluation = doT.template($api.dom('#searchResultTemp').innerHTML);
$api.dom('#showResult').innerHTML += evaluation(ret["data"]);
});
}
</script>
</body>
</html>
7、异步请求
$api.get('http://192.168.2.66:8081/app/index', function (ret) {
alert($api.jsonToStr(ret));
}, 'json');
api.ajax({
url: 'http://192.168.2.66:8081/app/index',
method: 'get',
},function(e){
alert($api.jsonToStr(e));
});
8、dot.js[模板引擎]
当使用web方式显示数据列表时,使用js模板可以有效提高开发效率。使用方式如下:
8.1 下载地址
https://github.com/olado/doT
8.2 在页面引用dot.min.js
<script type="text/javascript" src="../../script/api.js"></script>
<script type="text/javascript" src="../../js/dot.min.js"></script>
8.3 定义页面模板
<ul class="mui-table-view mui-grid-view mui-grid-12">
<div id="itemsDataDiv"></div>
<script id="itemsDataTemp" type="text/x-dot-template">
{{ for(var x in it) { }}
<li class="mui-table-view-cell mui-media mui-col-xs-3 mui-col-sm-3">
<a href="#" onclick="goToItems(3)" tapmode>
<img src="../../image/cbd.jpg" class="indeximg"/>
<div class="mui-media-body">{{=it[x].itemsName}}</div>
</a>
</li>
{{ } }}
</script>
</ul>
8.4 js驱动模板
apiready = function () {
doFindAllItems();
};
// 查询所有的检测项目
function doFindAllItems(){
//TODO:
var data = [
{itemsName:"A",itemsIcon:"../../image/cbd.jpg",},
{itemsName:"B",itemsIcon:"../../image/cbd.jpg",},
{itemsName:"C",itemsIcon:"../../image/cbd.jpg",},
{itemsName:"D",itemsIcon:"../../image/cbd.jpg",},
];
//
var evaluation = doT.template($api.dom('#itemsDataTemp').innerHTML);
$api.dom('#itemsDataDiv').innerHTML = evaluation(data);
}
8.5 参考链接
- https://www.jianshu.com/p/f671201df514
- dot github:https://github.com/olado/doT
- https://xhl.me/archives/dot-template/
- 基于dot.js HTML模板渲染:https://www.apicloud.com/source_code/278
9、Git管理
9.1 创建项目
- 在APICloud中创建新的项目
- 在git中创建repository,命名为demoApp
- 编写项目,即widget
![]()
9.2 提交项目
1 在与widget同级的情况下,运行git bash,然后输入
$ git init
2 与远程库(demoApp)关联
git remote add origin https://github.com/xx/demoApp.git
3 推送代码到远程库
$ git add .
$ git commit -m "commit message"
$ git push -u origin master
9.3 与APICloud关联
9.4 云编译
当做完以上操作后,之后进行云编译,然后下载App.
9.5 官方说明git管理
10、各个项目模板参考
11、Android Stduio 设置代理访问
在本机安装shadowsockets 然后设置本机ip端口为1081 ,最后file->setting->System Settings-> Http Proxy
配置完毕后,进行测试
12、自定义模块开发
开发之前,下载【模块开发SDK】,地址:https://docs.apicloud.com/Download/download
12.1 自定义模块开发[Eclipse]
在用Android Studio打包模块并测试,发现so文件并不能加载,具体原因因为调试环境限制,暂时不明确(AS可以开发不需要so文件的模块,调用无问题)。故采用Eclipse开发模块。具体步骤如下:
1、下载SDK模块开发项目,并导入到Eclipse工作空间
2、创建 apiDigital 模块,并加入代码
3、加入需要的依赖,并build path
4、加入需要的libXXX.so库
5、映射
package com.apicloud.apiDigital;
import com.uzmap.pkg.uzcore.UZWebView;
import com.uzmap.pkg.uzcore.uzmodule.UZModule;
import com.uzmap.pkg.uzcore.uzmodule.UZModuleContext;
import com.xmgh.digitalreader.proxy.DigitalReaderProxy;
/**
* 该类映射至Javascript中apiDigital对象<br>
* <br>
* <strong>Js Example:</strong><br>
* var module = api.require('apiDigital');<br>
* module.xxx();
*
* @author fangping
*/
public class APIDigitalModule extends UZModule {// 需要继承UZModule
private static DigitalReaderProxy digitalReaderProxy = null;
public APIDigitalModule(UZWebView webView) {
super(webView);
}
/**
* <strong>函数</strong><br>
* <br>
* 该函数映射至Javascript中moduleDemo对象的showAlert函数<br>
* <br>
* <strong>JS Example:</strong><br>
* moduleDemo.showValue(argument);
*
* @param moduleContext
* (Required)
*/
public void jsmethod_showValue(final UZModuleContext moduleContext)
throws JSONException {
JSONObject ret = new JSONObject();
ret.put("msg", "Hello");
moduleContext.success(ret, false);
}
}
6、导出jar,只导出该模块的代码即可
然后点击【Finish】即可。
7、资源修改
8、页面调用
9、打包的项目结构,新建一个与模块名一致的文件夹
文件夹说明:
res_apiDigital(可选目录):
1)、该目录命名规范必须为“res_”开头,后面跟模块名。例如“res_apiDigital”。
2)、res_apiDigital目录中内容审核: res_apiDigital的根路径下最多仅允许包含res子目录和AndroidManifest.xml文件,如图:
这两个文件对应项目中的:
sources: source目录为必须目录。
1)、该目录为模块的代码导出的JAR文件及其依赖的JAR所在目录,可存放多个JAR文件。
2)、该目录下均存放的.jar后缀名的文件,如apiDigital.jar、digitalreaderproxylibrary.jar.jar、tencent.jar。
4)、该目录下不允许存放名为android-support-v4.jar的文件。
5)、该目录下不允许存放名类似为apiEngine v1.1.0.jar的文件。
截图如下:
target:该目录为可选目录。
实际复制模块项目中的:
1)、该目录为模块用到的so库其依赖的so库所在目录,可存放多个so文件。
2)、该目录允许包含子目录,如armeabi-v7a、arm64、x86、mips等,这些子目录均为可选。
10、新建module.json,添加内容如下
{
name:'apiDigital',
class:'com.apicloud.apiDigital.APIDigitalModule'
}
11、压缩打包成zip即可
12、加入自定义模块,并添加到项目中.页面调用模块,不再累述
13、注意
-
res中需要去掉以下配置,以防冲突导致app编译失败
<resources> <string name="app_name">apiDigital</string> </resources> -
AndroidManifest.xml只加入对应的权限以及其他Activity,多余的去掉
-
加入so库,不需要加入
libsec.so
14、参考
- so库问题:https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=67144&extra=page%3D2%26filter%3Dtypeid%26typeid%3D63
- 视频:https://www.apicloud.com/video_play/8_14
- 模块打包文件目录要求:https://docs.apicloud.com/Module-Dev/Module-audit-specification-Android
12.2 自定义模块开发[AS]
12.3 模块开发之上传文件
代码:
package com.apicloud.apiDigital;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
import org.json.JSONException;
import org.json.JSONObject;
import com.uzmap.pkg.uzcore.uzmodule.UZModuleContext;
public class UploadUtil {
private static final int TIME_OUT = 180 * 1000; // 超时时间
private static final String CHARSET = "utf-8"; // 设置编码
/**
* android上传文件到服务器
*
* @param file
* 需要上传的文件
* @param RequestURL
* 请求的rul
* @param userId
* @param itemsId
* @param batchCode
* @param moduleContext
* @return 返回响应的内容
*/
public static String uploadFile(File file, String RequestURL,
String itemsId, String userId, String batchCode, UZModuleContext moduleContext) {
String result = null;
String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
String PREFIX = "--", LINE_END = "\r\n";
String CONTENT_TYPE = "multipart/form-data"; // 内容类型
DataOutputStream dos = null;
InputStream is = null;
try {
URL url = new URL(RequestURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(TIME_OUT);
conn.setConnectTimeout(TIME_OUT);
conn.setDoInput(true); // 允许输入流
conn.setDoOutput(true); // 允许输出流
conn.setUseCaches(false); // 不允许使用缓存
conn.setRequestMethod("POST"); // 请求方式
conn.setRequestProperty("Charset", CHARSET); // 设置编码
conn.setRequestProperty("connection", "keep-alive");
conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary="
+ BOUNDARY);
conn.connect();
if (file != null) {
/**
* 当文件不为空,把文件包装并且上传
*/
dos = new DataOutputStream(conn.getOutputStream());
//
StringBuffer sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
sb.append("Content-Disposition: form-data;name=\"itemsId\"");
sb.append(LINE_END);
sb.append(LINE_END);
sb.append(itemsId);
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
// 用户
sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
sb.append("Content-Disposition: form-data;name=\"userId\"");
sb.append(LINE_END);
sb.append(LINE_END);
sb.append(userId);
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
//
sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
sb.append("Content-Disposition: form-data;name=\"batchCode\"");
sb.append(LINE_END);
sb.append(LINE_END);
sb.append(batchCode);
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
/**
* 这里重点注意: name里面的值为服务器端需要key 只有这个key 才可以得到对应的文件
* filename是文件的名字,包含后缀名的 比如:abc.png
*/
sb.append("Content-Disposition: form-data; name=\"Fdata\"; filename=\""
+ file.getName() + "\"" + LINE_END);
sb.append("Content-Type: application/octet-stream; charset="
+ CHARSET + LINE_END);
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
is = new FileInputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1) {
dos.write(bytes, 0, len);
}
is.close();
dos.write(LINE_END.getBytes());
byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END)
.getBytes();
dos.write(end_data);
dos.flush();
/**
* 获取响应码 200=成功 当响应成功,获取响应的流
*/
int res = conn.getResponseCode();
if (res == 200) {
// is = conn.getInputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));
StringBuffer sb1 = new StringBuffer();
int ss;
while ((ss = in.read()) != -1) {
sb1.append((char) ss);
}
result = sb1.toString();
JSONObject ret = new JSONObject();
ret.put("msg", result);
ret.put("identity", 1);
file.delete();// 删除上传
moduleContext.success(ret, true);
}else{
JSONObject ret = new JSONObject();
ret.put("msg", "请求失败,请联系后台管理员");
ret.put("identity", -1);
moduleContext.success(ret, true);
}
}
} catch (MalformedURLException e) {
JSONObject ret = new JSONObject();
try {
ret.put("msg", e.getMessage());
ret.put("identity", -1);
} catch (JSONException e1) {
e1.printStackTrace();
}
moduleContext.success(ret, true);
e.printStackTrace();
} catch (Exception e) {
JSONObject ret = new JSONObject();
try {
ret.put("msg", e.getMessage());
ret.put("identity", -1);
} catch (JSONException e1) {
e1.printStackTrace();
}
moduleContext.success(ret, true);
e.printStackTrace();
} finally {
try {
if (dos != null) {
dos.close();
}
if (is != null) {
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
13、自定义拍照模板
1 效果如下:
2 步骤如下
自定义模板scanner.html页面
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="maximum-scale=1.0, minimum-scale=1.0, user-scalable=0, initial-scale=1.0, width=device-width" />
<meta name="format-detection" content="telephone=no, email=no, date=no, address=no">
<title>Hello APP</title>
<link rel="stylesheet" type="text/css" href="../css/api.css" />
<style>
html,body {
padding-top: 80px;
background-color: transparent;
padding-left: 0%;
}
/*.box{width: 18%;height: 80px;margin: 0 auto;background: #fff;}*/
.box{width: 400px;height: 100px;margin: 0 auto; border: 2px dotted #f3f3f7; margin-left:-15%;
/*旋转90度*/
-webkit-transform: rotate(90deg); /* Safari and Chrome */
-moz-transform: rotate(90deg); /* Firefox */
-moz-transform: rotate(90deg); /* Firefox */
-ms-transform: rotate(90deg); /* IE 9 */
-o-transform: rotate(90deg); /* Opera */
transform: rotate(90deg);}
.linebox {
width: 173px;
float: left;
margin-left: 25%;
margin-top: 16px;
}
.line{display: block; width:5px;height:30px;float: left; margin:25PX 25PX;border: 2px dotted #f3f3f7; }
.Rightbox {
float: left;
margin-left: 70px;
margin-top: 32px;
}
.circle{display: block; width:40px;height:30px;border-radius:40%; border: 2px dotted #f3f3f7; } /**f3f3f7**/
</style>
</head>
<body>
<!--<a class="button" tapmode="active" onclick="fnTakePhoto()">拍照 </a>-->
<div class="box">
<span class="linebox" id="lineBox">
<span class="line"></span>
<span class="line"></span>
</span>
<div class="Rightbox">
<span class="circle"></span>
</div>
</div>
</body>
<script type="text/javascript" src="../../../script/api.js"></script>
</html>
页面调用js
// 切换手机拍照
function doChangePhoto() {
var header = $api.dom('header'); // 获取 header 标签元素
var headerH = $api.fixStatusBar(header);
var FNPhotograph = api.require('FNPhotograph');
var curdate = new Date();
var photoPath = 'fs://FNPhotograph/' + curdate.getTime() + '.jpg';
exitFlag = false;
FNPhotograph.open({
path: photoPath,
album: true,
quality: 'high',
qualityValue:100
}, function (ret) {
if (ret.eventType == 'show') {
api.openFrame({
name: 'scanner',
url: './photo/scanner.html',
bounces: true,
rect: { // 推荐使用Margin布局,用于适配屏幕的动态变化
x: 30, // main页面距离win顶部的高度
y: 80, // main页面距离win底部的高度
// w: 'auto' // main页面的宽度 自适应屏幕宽度
w: 'auto',
h: '430px',
},
bounces: false,
});
} else if (ret.eventType == 'takePhoto') {
console.log(JSON.stringify(ret));
var imagePath = ret.imagePath;
if (imagePath != null) {
api.openWin({
name: 'detection-takephoto-submit',
url: './photo/detection-takephoto-submit.html',
rect: {
w: api.winWidth,
h: api.winWidth
},
pageParam: {imagePath: imagePath}
});
}
} else if (ret.eventType == 'close') {
// document.getElementById('abc').src = ret.imagePath;
// api.closeFrame({
// name: 'scanner'
goToBeforePage();
}
});
}
14、调用模块说明
14.1 调用定位模块说明
15、App抓包
15.1 安装说明
首先下载安装Fiddler,运行后选择菜单Tools->Fiddler Options。
选中"Decrpt HTTPS traffic",Fiddler就可以截获HTTPS请求:
选中"Allow remote computers to connect",是允许别的机器把HTTP/HTTPS请求发送到Fiddler上来:
配置完成后重启Fiddler。
15.2 安装证书【安卓不装】
1.获取当前电脑的IP地址,例如我这里是:192.168.2.65
2.在iPhone中打开safari并访问地址http://192.168.2.65:8888,点"FiddlerRoot certificate"然后安装证书:
15.3 手机设置代理
在iPhone上打开设置->无线局域网,点击当前WIFI后面的i图标查看当前连接信息,滚动到底部的HTTP代理,切换为“手动”:
15.4 使用过程报错
使用中弹出:
creation of the root certificate was not successful
解决如下:
cd d:\Program Files\Fiddler
makecert.exe -r -ss my -n "CN=DO_NOT_TRUST_FiddlerRoot, O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com" -sky signature -eku 1.3.6.1.5.5.7.3.1 -h 1 -cy authority -a sha1 -m 120 -b 09/05/2012
再安装证书
16、app更新
16.1 版本更新
16.2 云更新
17、ios证书
现在apicloud官方不提供测试版本的IOS证书, 所以这里使用一个工具去生成IOS证书。
- 使用的是Appuploader:http://www.appuploader.net/index.php 下载并安装
1.创建免费的苹果开发者账号的过程
2.申请ios证书步骤说明,这一步主要弄证书以及描述文件即可
3.打包ios的步骤说明
4.apicloud官方说明一些问题
- iOS证书相关问题:https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=5033
- iOS证书及描述文件制作流程 :https://docs.apicloud.com/Dev-Guide/iOS-License-Application-Guidance
5.博客说明ios证书
地址:https://blog.csdn.net/xxw888/article/details/76083152
6.注意
苹果端安装ipa,采用第三方去安装。扫描二维码以及ipa安装,会报安装失败等错误。
18、集成极光推送
18.1 集成步骤
1.app加入极光模块
2.极光官网绑定app
3.修改config.xml,在配置文件中,加入以下配置
<feature name="ajpush">
<param name="channel" value="developer-danqiusheng" />
<param name="app_key" value="93458e2fe2c88736b455b743" /> <!--上面的AppKey-->
</feature>
4.推送
18.2 链接
- 论坛极光示例说明:https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=1841&highlight=ajpush
- 推送API:https://docs.apicloud.com/Client-API/Open-SDK/ajpush
19、问题
19.1 $api 和 api的区别
$api 是前端框架中定义的对象,引入api.js即可用,无需等待apiready事件。
api是引擎拓展的对象,apiready事件之后使用,封装了平台的基础功能。
19.2 api.ajax post请求
api.ajax({
url: 'http://10.5.5.130:8080/api/digital/items/save',
method: 'POST',
timeout: 30,
dataType: 'json',
cache:false,
headers: { "Content-Type":"application/json"},
// returnAll: false,
// 注意body
data: { body: JSON.stringify({ itemsName: '123',itemsCode:"123"})}
}, function (ret, err) {
console.log(JSON.stringify(ret))
});
参考地址:https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=12260&page=1
19.3 替换logo
1.端设置中修改icon和启动项图标;
2.本地icon/icon150x150.png和launch/launch1080x1920.png文件已经替换并提交到svn
19.4 touch事件被阻止
浏览器调试,touch事件被阻止
Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080
document.addEventListener('touchmove', func ,{passive:false}); // 注册下拉事件