快应用开发技术难点,以及不同手机厂商兼容性问题(会持续更新)

目录

一、首次接触快应用

二、开发工具

三、技术难点

1、文件(语音、图片等)转base64

2、 base64转音频文件

四、兼容性问题集合

1、返回首页

2、语音播放接口

3、获取事件对象,比如阻止事件冒泡,如何获取当前的事件对象

4、自定义文件引入



一、首次接触快应用

由于项目需要,第一次接触快应用的开发。但是在项目开发完成,进入到测试阶段才发现。华为厂商自己创造了一套文档,有些接口在其他机型(如:vivo、小米)上直接报错,不兼容,咨询了华为快应用技术支持,回复的答案是:建议分开两套代码维护,即:华为机型一套代码,其他的,另一套代码,这是多么悲伤的故事。所以在项目中,遇到兼容性的问题,总结了下来,方便后续查找。

二、开发工具

快应用联盟,使用 IDE 工具进行编码、调试、测试、上传等功能。

华为,使用 华为快应用IDE 工具进行编码、调试、测试、上传等功能。


附上 快应用联盟官方文档华为快应用文档 链接

三、技术难点

1、文件(语音、图片等)转base64

文档上没有接口,能直接把文件转为base64编码,这里提供一个可行的解决方案。base64-arraybuffer结合 '@system.file'。

a、 在需要把文件转bse64的页面中,引入这两个文件,其中,base64-arraybuffer,为 npm i

 base64-arraybuffer导入依赖。

import file from '@system.file'
const base64Arraybuffer = require('base64-arraybuffer')

 b、获取文件路径后,执行如下代码:

    getBase64(type) {
      file.readArrayBuffer({
        uri: this.currUri, // this.currUri 是文件路径
        success: (data) => {
          console.log('buffer.length: ' + data.buffer.length)
          const base64 = base64Arraybuffer.encode(data.buffer)
          console.log(base64)
        },
        fail: function (data, code) {
          console.log(`handling fail, code = ${code}`)
        }
      })
    },

2、 base64转音频文件

语音播放功能,接口返回base64编码,需要在快应用播放。使用`@system.audio`。audio接收一个播放的音频媒体 uri,因此要把base64转换成uri。有效方案如下:

a、导入依赖文件

  import audio from '@system.audio'
  import file from '@system.file'
  import base642uint8 from '../../../helper/base642uint8'

base642uint8.js文件,是我本地得,通过base64转为uintArray。在此附上代码:


const barf = (s, i) => {
    throw new Error(`Not a valid base64 string. Found "${s[i]}" at index ${i}.`);
}
/**
 * base64 转为 decode
 * @param {*} base64 
 */
const decode = (base64) => {
    const charCode2Index = [
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1,
        62,                                     // +
        -1, -1, -1,
        63,                                     // /
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // 0-9
        -1, -1, -1,
        0,                                      // =
        -1, -1, -1,
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9,           // A-J
        10, 11, 12, 13, 14, 15, 16, 17, 18, 19, // K-T
        20, 21, 22, 23, 24, 25,                 // U-Z
        -1, -1, -1, -1, -1, -1,
        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, // a-j
        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, // k-t
        46, 47, 48, 49, 50, 51                  // u-z
    ]
    const base64_length = base64.length;
    const output_length = base64_length / 4 * 3;
    if (output_length !== (output_length | 0)) {
        throw new Error("base64 is not a valid base64 encoding.");
    }
    const output = new Uint8Array(output_length);
    let c1, c2, c3, c4,
        i = 3, j = 0;
    for (; i < base64.length; i += 4) {
        c1 = charCode2Index[base64.charCodeAt(i - 3)]; // 00010011 = 19 = T
        c2 = charCode2Index[base64.charCodeAt(i - 2)]; // 00010110 = 22 = W
        c3 = charCode2Index[base64.charCodeAt(i - 1)]; // 00000101 =  5 = F
        c4 = charCode2Index[base64.charCodeAt(i)];     // 00101110 = 46 = u

        if (c1 === -1 || c1 === undefined) {
            barf(base64, i - 3)
        }
        if (c2 === -1 || c2 === undefined) {
            barf(base64, i - 2)
        }
        if (c3 === -1 || c3 === undefined) {
            barf(base64, i - 1)
        }
        if (c4 === -1 || c4 === undefined) {
            barf(base64, i)
        }
        output[j++] = c1 << 2 | c2 >> 4; // 010011xx | xxxx0001 = 01001101 =  77 = M
        output[j++] = c2 << 4 | c3 >> 2; // 0110xxxx | xx000001 = 01100001 =  97 = a
        output[j++] = c3 << 6 | c4;      // 01xxxxxx | 00101110 = 01101110 = 110 = n
    }
    if (base64[base64_length - 1] === "=") {
        const padding = base64[base64_length - 2] === "=" ? 2 : 1;
        return output.subarray(0, output_length - padding);
    }
    return output;
}

export default {
    decode,
}

 b、封装方法

    // base64 => 音频文件
    getAudioFile(base64) {
      const arrayBuffer = base642uint8.decode(base64)
      const randomNumber = new Date().getTime()
      file.writeArrayBuffer({
        uri: `${this.voiceUriPrefix}${randomNumber}.m4a`,
        buffer: arrayBuffer,
        success: () => {
          this.voiceUriArr.push(`${this.voiceUriPrefix}${randomNumber}.m4a`)
          if (this.voiceIndex + 1 === this.voiceArr.length) {
            this.loading = false
          }
        },
        fail: (data, code) => {
          console.log(`handling fail, code = ${code}`)
        }
      })
    },

 

四、兼容性问题集合

1、返回首页

非华为机型:

router.back({
    path:'/' , //  '/',默认为 `manifest.json`文件配置的文件入口,`entry`的值
})

华为机型:

router.back({
    path: '/pages/Home'   // entry的值
})

2、语音播放接口

非华为机型:

引入`import texttoaudio from '@service.texttoaudio'`,具体使用方法,点击跳转

华为机型:

引入`import mltts from '@service.ml.tts'`,具体使用方法,点击跳转

3、获取事件对象,比如阻止事件冒泡,如何获取当前的事件对象

非华为机型:

    <text class="iconfont icon-del" 
        @click="clickDeleteImage(evt, value2, index2, $idx)"> 删除
    <text>

     // 点击删除图片
    clickDeleteImage(evt, delItem, delInd, itemIndex) {
      // 需要阻止冒泡
      evt.stopPropagation()
    },

华为机型:

传入的时候不用加event对象,接受的时候要加evt,传入的时候默认会在最后补上一个

    <text class="iconfont icon-del" 
        @click="clickDeleteImage(value2, index2, $idx)"> 删除
    <text>

     // 点击删除图片
    clickDeleteImage(delItem, delInd, itemIndex, evt) {
      // 需要阻止冒泡
      evt.stopPropagation()
    },

4、自定义文件引入

比如,iconfont.css 需要引入 iconfont.ttf 文件,两个文件所在目录如下图:

如何引入?

非华为机型:

@font-face {
  font-family: iconfont; /* project id 1009460 */
  src: url('/assets/styles/iconfont.ttf');   // 可以
  // src: url('../../../assets/styles/iconfont.ttf');  // 也可以,但是在华为机上不行
}

华为机型:

@font-face {
  font-family: iconfont; /* project id 1009460 */
  src: url('/assets/styles/iconfont.ttf');   // 在非华为机上也可以引入成功

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值