Apicloud

创建第一个app

https://docs.apicloud.com/APICloud/creating-first-app

开发工具下载

https://www.apicloud.com/devtools

源码地址

https://github.com/apicloudcom

signature 源码

https://github.com/apicloudcom/APICloud-Modules/tree/master/signature/android/sourceCode

打包发布APP-云编译

注意项:

1. 如果装的话,需要将之前【调试的 loader】 先卸载后再装,否则提示“安装失败,安装包版本太低”等问题

步骤:

1. 修改 logo(png格式)

2. 修改启动页

3. 云编译,打包

 

资源:


搞定抠图
https://www.gaoding.com/

在线PS
http://www.uupoop.com/

 

拷贝模拟器中的文件?

在安卓手机 文件管理器  / $MuMu共享文件夹

APP运行的文件是存在于 /UZMap/APP目录 下

在电脑上有对应的文件夹与之对应

APICloud七天在线培训课教程

https://github.com/apicloudcom/APICloud-7Days-Online-Training-Tutorials

 

课程第一天 https://docs.apicloud.com/Seven/Day1

 

一周一APP 完整技术架构和流程

https://github.com/xiaoqiang730730/vue_apicloud/blob/master/doc/oneweekoneapp.md

 

 

 

AUI框架

https://github.com/liulangnan/aui

http://www.auicss.com/

 

 

APICloud WiFi 真机预览效果

https://docs.apicloud.com/Dev-Tools/wifi-debug

 

 

 

与 Vue 整合开发的相关资料

方式一: vue-cli + vant

【运行方式】 启动 Vue 服务器,然后在 手机应用上同步才可以看到效果  【注意】 浏览器中是看不到效果的,因为创建 vue 组件是在 api_ready 下才成功创建的。

 

vue 脚手架开发

https://github.com/xiaoqiang730730/vue_apicloud/tree/master/doc

vant 移动端UI库

https://youzan.github.io/vant/#/zh-CN/quickstart

 

 

 

vue: command not found

【解决办法】 写全命令路径

​/usr/local/Cellar/node/6.2.2/lib/node_modules/vue-cli/bin/vue init xiaoqiang730730/vue_apicloud ee-app-vant 

 

 

 

Vue项目中如何使用APICloud的接口

直接调用即可,不过需要在模拟器中进行调用才行。在浏览器中,会提示找不到对象

例如,在点击函数中,双向数据绑定:

this.msg = api.systemType

 

 

 

 

知识点积累

路由跳转

this.$router.push('/register');
 
引入库

采用全局导入组件的方式【推荐】

cnpm i vant -S

 

在 src/main.js 全部导入 vant 的组件

import Vant from 'vant';

import 'vant/lib/vant-css/index.css';


Vue.use(Vant);

 

 

 

之前的babel方式,有点麻烦,【不推荐使用】

.barelrc 配置。当然安装依赖什么的,就直接参考文档安装即可。

vue init xiaoqiang730730/vue_apicloud my-project

cnpm install

cnpm i babel-plugin-import -D
cnpm i vant -S

cnpm run start

 

 

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime", ["import", {
    "libraryName": "vant",
    "libraryDirectory": "es",
    "style": true
  }]],
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
    }
  }
}

2. 使用组件

关闭elint验证, config/index.js, 配置选项:

useEslint: false,

 

<van-button type="default">清空</van-button>

import { Button } from "vant";



export default {
  name: "HelloWorld",

  components: {
    [Button.name]: Button
  },

};



3. APICloud 源代码配置,采用热更新的方式,其中配置方式,可参考方式二中的 相关文章

主要步骤

(1)APIStudio 新建项目

(2)网页云控制台,模块/编译自定义 Loader

 

 

编辑 模板案例 中的  index.html 文件,修改结构 和 js 代码

 

<body>
    <div id="wrap">
        <div id="header">
        </div>
        <div id="main" class="flex-con">
        </div>
    </div>
</body>
<script type="text/javascript" src="./script/api.js"></script>
<script type="text/javascript">
    window.apiready = function(){

        var header = $api.byId('header');
        //适配iOS 7+,Android 4.4+状态栏
        $api.fixStatusBar(header);

        var headerPos = $api.offset(header);
        var main = $api.byId('main');
        var mainPos = $api.offset(main);
        api.openFrame({
            name: 'main',
            //url: 'dist/html/index.html',
            //url: 'html/main.html',
            //url: 'http://172.16.5.6:8010/index.html',
            url: 'http://172.16.5.6:8080',
            bounces: true,
            rect: {
                x: 0,
                y: headerPos.h,
                w: 'auto',
                h: mainPos.h
            }
        });

    };
</script>

方式二: vue + sui

史上最快的开发方式,基于webpack2+vue2搭建的apicloud脚手架 
https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=55876&extra=&page=1

SUI 淘宝的移动端UI框架

http://m.sui.taobao.org/getting-started/

 

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"
    />
    <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
    <title>入口页面</title>
    <!-- <link rel="stylesheet" href="./res/css/sm.min.css"> -->
    <link rel="stylesheet" href="//g.alicdn.com/msui/sm/0.6.2/css/sm.min.css">

    <style>
        .bar-nav {
            background-color: #0099FF;
        }

        .bar-nav .title {
            color: #fff;
        }
    </style>
</head>

<body style="background-color: #fff">
    <!-- <header class="bar bar-nav">
        <a class="icon icon-me pull-left open-panel"></a>
        <h1 class="title">标题222</h1>
    </header>

     -->
    <div id="app">

        <p>
            <!-- 使用 router-link 组件来导航. -->
            <!-- 通过传入 `to` 属性指定链接. -->
            <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
            <router-link to="/foo">Go to Foo</router-link>
            <router-link to="/bar">Go to Bar</router-link>
        </p>
        <!-- 路由出口 -->
        <!-- 路由匹配到的组件将渲染在这里 -->
        <router-view></router-view>

    </div>
</body>

<!-- 引入 APICloud 库 -->
<script src="./src/public/api.js"></script>


<!-- 引入 Vue 和 Vue 路由 -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>


<script>
    window.apiready = function () {

        // 1. 定义 (路由) 组件。
        // 可以从其他文件 import 进来
        const Foo = { template: '<div>foo</div>' }
        const Bar = { template: '<div>bar</div>' }

        // 2. 定义路由
        // 每个路由应该映射一个组件。 其中"component" 可以是
        // 通过 Vue.extend() 创建的组件构造器,
        // 或者,只是一个组件配置对象。
        // 我们晚点再讨论嵌套路由。
        const routes = [
            { path: '/foo', component: Foo },
            { path: '/bar', component: Bar }
        ]

        // 3. 创建 router 实例,然后传 `routes` 配置
        // 你还可以传别的配置参数, 不过先这么简单着吧。
        const router = new VueRouter({
            routes: routes // (缩写) 相当于 routes: routes
        })

        // 4. 创建和挂载根实例。
        // 记得要通过 router 配置参数注入路由,
        // 从而让整个应用都有路由功能
        const app = new Vue({
            router: router
        }).$mount('#app')


    };
</script>

</html>

其他技术知识点

APP store 开发流程

https://github.com/xiaoqiang730730/vue_apicloud/blob/master/doc/appstore.md

 

vue中调用api的模块

https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=100823&highlight=vue

命令行工具

https://docs.apicloud.com/Dev-Tools/apicloud-cli

 

npm install -g apicloud-cli

找到安装目录
/usr/local/Cellar/node/6.2.2/bin/apicloud


export PATH=/usr/local/Cellar/node/6.2.2/bin:$PATH

可以将PATH写到 系统的路径里  /etc/profile
也可以写到用户的 配置环境里 如果用的是bash  则在用户目录~/.bash_profile 添加路径
把修改后的文件用source命令生效下就行  也可以重启下系统

vi ~/.bash_profile
source ~/.bash_profile

vue-cli启动

npm run wifistart

 

https://github.com/xiaoqiang730730/vue_apicloud/blob/master/doc/oneweekoneapp.md

_apiConfig.xml

可以把content改成http://xxxx:8080, 就能够运行vue的项目了。

在安装自定义loader之后,按照如图所示,

这个时候就需求apicloud-cli了,2个步骤

wifi开启同步 apicloud wifiStart --port 8686 或者 npm run wifistart

wifi服务同步所有文件 apicloud wifiSync --project ./src --updateAll true --port 8686 或者 npm run wifiupdateall


参考模块

拍照模块 FNPhotograph

https://docs.apicloud.com/Client-API/Func-Ext/FNPhotograph

支持距离调整等

 

 

组件化,结合vue的实现代码

<template>
  <div class="camera">
    <van-icon @click="takePhoto" name="photograph" class="btn" />
  </div>
</template>

<script>

/*
使用说明

<take-photo 
  v-if="showCamera" 
  v-on:before-close="closeCamera" 
 &nbsp;:exam-student-id="'xxxx-xxx-xxx'"
 &nbsp;:exam-index="0"
  ></take-photo> 

this.showCamera = true;

closeCamera: function(imagePath) {
  alert("closeCamera")
  alert(imagePath)
  this.showCamera = false;
},

import TakePhoto from './TakePhoto'

components: {
  TakePhoto
},
*/

export default {
  name: 'TakePhoto',

  props: [
    'examStudentId',
    'examIndex',
  ],

  mounted() {
    alert("开始拍照!");

    // 拍照
    var FNPhotograph = api.require('FNPhotograph');

    FNPhotograph.openCameraView({
      rect: {
        x: 0,
        y: 0,
        w: 'auto',
        h: api.winHeight - 100
      },
      orientation: 'landscapeRight',
      fixedOn: api.frameName
    }, function(ret) {

      if (!ret.status) {
        alert('相机打开失败,请确认已经授权使用相机!');
      }
      // alert('openCameraView ret:'+JSON.stringify(ret));


    
    })
  },

  methods: {
    takePhoto: function() {

      var examPhotoPath = this.EXAM_PHOTO_PATH;

      examPhotoPath += this.examStudentId;
      examPhotoPath += '/' + this.examIndex;

      // 拍照
      var FNPhotograph = api.require('FNPhotograph');

      FNPhotograph.takePhoto({
        quality: 'medium',
        path: examPhotoPath,
        album: false
      }, (ret) => {
        var imagePath = (ret.imagePath);

        FNPhotograph.closeCameraView((ret) => {
          if (ret) {
            alert("拍照成功!");

            this.$emit("before-close", imagePath);
          }
        });
      });
    },
  },
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.camera {
  position: absolute;
  z-index: 999;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: #000000;
}

.btn {
  position: absolute;
  bottom: 10px;
  left: 50%;
  margin-left: -30px;
  width: 60px;
  line-height: 50px;
  cursor: pointer;
  font-size:40px;
  text-align: center;
  color:white;
  border:2px solid white; 
  border-radius:50%;
  padding:5px;
}

</style>


 

 

 

 

拍照旋转问题

【解决方法】将图片通过 css 样式旋转,即可纠正旋转的照片

style="transform:rotate(-90deg); " 

 

获取旋转角度,注意要传入图片路径,官方代码中没有包含图片路径参数。

        FNPhotograph.getRotateDegree({
          imgPath: imagePath
        }, function(ret) {
          if (ret) {
              alert(JSON.stringify(ret));
          }
        });

 

 

 

 

编译自定义Loader后,调用摄像头代码,如下:

      var FNPhotograph = api.require('FNPhotograph');
      FNPhotograph.open({
          path: 'fs://savePath',
          album: false ,
          quality: 'medium'    //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; quality: 'low'
      }, function(ret){

        if (ret.eventType == "show") {

        } else if (ret.eventType == "takePhoto") {

          alert(ret.imagePath);

          FNPhotograph.close();

        } else if (ret.eventType == "close") {
          alert("close");
          
        } else {
          alert(JSON.stringify(ret));
        }
      });

 

拍照像素问题

设为低像素

      FNPhotograph.takePhoto({
        quality: 'low',
        qualityValue: 12,
        path: examPhotoPath,

自定义Frame操作

      FNPhotograph.openCameraView({
        rect: {
            x: 0,
            y: 0,
            w: 'auto',
            h: 'auto'
        },
        orientation: 'landscapeLeft',
        fixedOn: api.frameName
      }, function(ret) {
        alert('sss'+JSON.stringify(ret));
        FNPhotograph.takePhoto({
            quality: 'medium',
            path: 'fs://FNPhotograph/01.png',
            album: false
        }, function(ret) {
            alert(ret.imagePath);

            FNPhotograph.close(
              function(ret) {
                  if (ret) {
                      alert(JSON.stringify(ret));
                  }
            });
        });
      });

 

参考:https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=73629&highlight=openCameraView

 

 

 

 

模块使用流程

1. 添加模块,同步代码
2. 编译自定义 loader,使用自定义Loader进行测试

 

前置摄像头

setCamera

设置前置/后置摄像头(注意此方法与openCameraView配合使用)

setCamera({params})

params

camera:

  • 类型:字符串
  • 描述:(可选项)摄像头
  • 默认值:back
  • 取值范围:
    • front:前置摄像头
    • back:后置摄像头

trans 转换模块的使用

转换图片编码等

          var trans = api.require('trans');
          trans.decodeImgToBase64({
              imgPath: ret.imagePath
          }, (ret, err) => {
              if (ret.status) {
                  
                  // console.log(ret.base64Str);
           ...

 

socketManager 通讯模块

状态定义:

101 //创建成功

102 //连接成功

https://docs.apicloud.com/Client-API/Func-Ext/socketManager#3

创建连接、发送数据等操作

https://docs.apicloud.com/Client-API/Func-Ext/socketManager#3

var socketManager = api.require("socketManager");

socketManager.createSocket({
    host: '192.168.10.1',
    port: 6001
}, function(ret, err) {
    if (ret) {
        alert(JSON.stringify(ret));
    } else {
        alert(JSON.stringify(err));
    }
});

 

SocketManager发送16进制数据

https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=74184&extra=page%253D1

 

  • 下载图片 base64 编码多了1个等于号  => 直接字符串替换掉

 

 

 

 

Mac 下 TCP/UDP 测试工具

https://www.jianshu.com/p/ca1910ac691a

 

ajax模块

上传多个文件

api.ajax({
  url: url,
  method: 'post',
  timeout: 60*60*2,
  headers: {
    'token': this.token
  },
  data: {
    files: {
      "file": ['fs://1.jpg', 'fs://2.jpg']
    }
  }
}, (ret, err) => {
  if (ret) {
  ...

后台接收

@Login
@PostMapping("question/uploadpic")
@ApiOperation("上传1个考生正常考试抓取的图片")
public R uploadpic(@RequestParam String examStudentID, 
        @RequestParam("file") MultipartFile[] files) {
...

发送字符串数组

api.ajax({
  url: url,
  method: 'post',
  timeout: 60*60*2,
  headers: {
&nbsp; &nbsp; 'Content-Type': 'application/json;charset=utf-8',
    'token': this.token
  },
  data: {
    &nbsp;body: examPhotoList
  }
}, (ret, err) => {
  if (ret) {
  ...

后台接收

@Login
@PostMapping("question/uploadpic")
@ApiOperation("上传1个考生正常考试抓取的图片")
public R uploadpic(@RequestParam String examStudentID, 
        &nbsp;@RequestBody List<Object> base64StrList) {
...

遇到的问题:

JsonMappingException: Can not deserialize instance of java.lang.Integer out of START_OBJECT token

【解决方法】 前端传递的是对象,而后端接受的是 List,类型不匹配

示例代码

简单登录效果实现

https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=47580https://community.apicloud.com/bbs/forum.php?mod=viewthread&tid=47580

技术知识点

ajax 的封装

  // 自定义的ajax接口
  // obj 参数:
  // {
  //   method: 'get'  'post'
  //   url: ''
  //   data: {},
  //   sucess: (ret) => {}
  //   fail: (ret) => {}
  // }
  Vue.prototype.eeAjax = function (obj) {
    if (this.token == null) {      
      this.$router.push("/")
      return ;
    }

    var prefix = "http://192.168.1.111:8080/ee-server";
    obj.url = prefix + obj.url;
    if (obj.data) {
      var arr = [];
      for (var k in obj.data) {
        arr.push( k + "=" + obj.data[k]);
      }

      if (arr.length >= 0) {
        obj.url += "?";
        obj.url += arr.join('&')
      }
    }

    // 表单方式提交数据或文件
    api.ajax({
      url: obj.url,
      method: 'get',
      headers: {
        'Content-Type': 'application/json;charset=utf-8',
        'token': this.token
      }    
    }, (ret, err) => {
      if (ret) {
        if (ret.code == 0) {
          obj.success && obj.success(ret);
        } else if (ret.code == 403) {
          // token失效,请重新登录
          alert(ret.msg);     
          this.$router.push("/")
        } else {
          obj.fail && obj.fail(ret)
        }
      }
    });
  }

全局变量实现

export default function install (Vue, options) {

  // 服务器信息记录
  Vue.prototype.KEY_SERVER_INFO = "KEY_SERVER_INFO";

  Vue.prototype.getGLibExamStudent = function () {
    return Vue.prototype.gLibExamStudent;
  }

}


// main.js
import utils from './utils';
Vue.use(utils); //将全局函数当做插件来进行注册

 

系统参数存储

  // 同步获取app参数
  var dbIndex = api.getPrefs({
    sync: true,
    key: 'dbIndex'
  });

  // 设置app参数
  if (!dbIndex) {
    api.setPrefs({
        key: 'dbIndex',
        value: '1'
    });
  }

 

获取摄像头图像或系统相册中的图片

https://docs.apicloud.com/Client-API/api#20

    api.getPicture({
        sourceType: 'library',
        encodingType: 'jpg',
        mediaValue: 'pic',
        destinationType: 'base64',
        allowEdit: false,
        quality: 50,
        targetWidth: 100,
        targetHeight: 100,
        saveToPhotoAlbum: false
    }, function(ret, err) {
        if (ret) {
            alert(JSON.stringify(ret));
        } else {
            alert(JSON.stringify(err));
        }
    });

 

写文件

var dbf = dbFilePath + "/" + dbIndex + "/" + (dbFileCount++);

api.writeFile({
    path: dbf,
    data: imgData
}, function(ret, err) {
    if (ret.status) {
        alert("保存成功");
    } else {
        alert("dbFilePath保存失败:" + JSON.stringify(err));
    }
});

数据库操作

https://docs.apicloud.com/Client-API/Func-Ext/db

https://www.cnblogs.com/mr-yuan/p/6696288.html

 

CSS 边框测试代码

  border-bottom-color: #ff0000;
  border-bottom-style: solid;
  border-bottom-width: 5px; 

 

Vue 默认图片显示

data: { 
     noPhoto: 'this.src="' + require("../assets/StartExam/NoPhoto.gif") + '"',
}

<img v-bind:src="stu.photo"&nbsp;:onerror="noPhoto">

 

Java Base64图片编码

注意生成的图片前面有前缀表示

            // 保存图片数据,转换成 Base64 编码
            Byte[] photo = worker.getPhoto();
            int n = photo.length;
            
            byte[] b = new byte[n];
            for (int i = 0; i < n; i++) {
                b[i] = photo[i];
            }
            // 保存 Base64 编码格式显示
            examStudentForm.setPhoto("data:image/jpeg;base64," + 
                    Base64.encodeBase64String(b));
            

 

前端中的显示:

{

noPhoto: 'this.src="' + require("../assets/StartExam/NoPhoto.png") + '"',


<img style="transform:rotate(-90deg); " v-bind:src="'data:image/jpg;base64,'+photo" :onerror="noPhoto">

问题及解决

该操作仅对使用 git-svn 检出的 SVN 项目有效.如果是标准 Git 项目,直接使用 push 命令即可.

重新用 apistudio 工具从网站检出之后,将检出的文件夹 替换 编译即可。

 

Vue 区分开发版本还是发布版本

下面2个表达式,可以在 vue 的组件总直接来使用

开发版本
process.env.NODE_ENV === 'development'

发布版本
process.env.NODE_ENV === 'production'



// 组件中的使用
this.isDev = (process.env.NODE_ENV === 'development');

 

文件操作模块

fs 模块使用手册

https://docs.apicloud.com/Client-API/Func-Ext/fs#31

使用模块时,需要先添加模块,才能使用这些功能

 

      var fs = api.require('fs');

      var bakDir = "fs://exam/bak";
      // var ret = fs.createDirSync({
      //     path: bakDir
      // });
      // if (ret.status) {
      //     alert('创建成功!');
      // } else {
      //     alert('创建失败!');
      // }


      var ret = fs.existSync({

      var ret = fs.openSync({


      var ret = fs.writeSync({
          fd: this.bak.fd,
          data: JSON.stringify(this.stuExamList),
          overwrite: true
      });
      // if (ret.status) {
      //     alert('保存成功!');
      // } else {
      //     alert('保存失败!');
      // }

加密模块

signature

https://docs.apicloud.com/Client-API/Func-Ext/signature

 

添加模块

      var signature = api.require('signature');

      signature.desECB({
        data: txt,
        key: '4OzEDGPUvkym9SkU'
      }, (ret, err) => {
        if (!ret.status) {

signature 源码

https://github.com/apicloudcom/APICloud-Modules/tree/master/signature/android/sourceCode

 

 

参照源代码

Java 端

import org.apache.commons.codec.binary.Base64;

str = new String(Base64.decodeBase64(afterDecrypt.getBytes("UTF-8")));

【注意】测试时候的字符一定要准确

 

Wifi模块

https://docs.apicloud.com/Client-API/Device-Access/bgnWiFi

 

 

与apicloud配套使用的vant框架

环境搭建

cnpm install -g @vue/cli-init

vue init xiaoqiang730730/vue_apicloud si-app-vant

去除eslint的验证

config/index.js

useEslint: false,

 

启动项目

npm run start

编译加上传

npm run build && gulp upload
posted @ 2023-04-12 16:52  lvye1221  阅读(36)  评论(0编辑  收藏  举报