uni-appx开发鸿蒙插件示例

参考:https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin.html

uni-appx开发鸿蒙插件示例

新建步骤拆解

右键点击uni_modules目录 -> 新建插件

创建插件

在HBuilder X 中选中你的项目下uni_modules目录,右键选择新建uni_modules插件, 例如 uts-api

选择类型 uts插件

为了避免和插件市场的其他插件冲突,建议起一个自己的插件前缀名称。

uts插件目录结构

package.json

package.json 为 uni_modules 插件配置清单文件,负责描述插件的基本配置。


上面是一个默认的清单文件示例,关于 package.json 更多描述详见

插件的目录结构

根目录 index.uts 文件是程序主入口。如果插件根目录下没有 index.uts,则会在编译到不同平台时,寻找分平台的目录下的 index.uts 文件。

比如编译到 app-harmony 平台时,如果 uts 插件根目录没有 index.uts,会寻找 utssdk/app-harmony/index.uts。如果也没有找到,会报错。

当同时存在分平台目录的 index.uts 和根目录 index.uts 时,会优先获取具体的分平台目录。

开发者有多种组织自己代码的方式:

  1. 在插件根目录的 index.uts 中写条件编译代码。简单的业务一个文件搞定
  2. 在插件根目录 index.uts 中写条件编译,import 分平台的文件
  3. 不写根目录的 index.uts,直接在分平台目录写 index.uts。不跨端时,比如只做一个 Android 插件,这样写比较简单

插件对外暴露能力的总入口在 interface.uts ,他与 index.uts的关系是声明和实现的关系

App原生配置

鸿蒙原生配置

app-harmony文件夹存放uts插件编译到鸿蒙时的代码逻辑,目前仅支持uts文件。

目录名/文件名用途
index.uts主入口,interface.uts声明的能力在harmony平台下的实现

HBuilderX项目中uts插件目录结构

在 uni-app / uni-app x 的项目工程下,提供了独立的目录 utssdk,来存放 uts 插件。

当然官方更推荐使用 uni_modules 方式,这是更好的包管理方案。

首先确保项目根目录存在 uni_modules 文件夹,如果不存在,需要手动创建一个,目前HB也有创建uni_modules 的指引,还是比较方便的。

编写interface.uts

插件 uts-api 创建完成后,我们需要确定插件对外暴露的 API。

为了多端统一规范的定义对外暴露的接口,获得更好的语法提示和多端一致性约束,标准做法是在 interface.uts 文件中统一定义插件要暴露的 API 类型、 API 的参数类型、返回值类型、错误码类型、错误接口等信息,然后在各端的 index.uts 中做具体的业务实现。

打开 interface.uts 文件,键入下面的源码, 为了方便说明,源码的每个部分的作用都用注释来说明

// 定义 API的参数类型,基本数据类型的参数无需定义,复杂类型参数建议使用自定义type
/**
 * myApi 异步函数的参数,在type里定义函数需要的参数以及api成功、失败的相关回调函数。
 */
export type MyApiOptions = {
  paramA : boolean
  success ?: (res : MyApiResult) => void
  fail ?: (res : MyApiFail) => void
  complete ?: (res : any) => void
}

// 定义 API 的返回值类型, 基本数据类型的返回值无需特殊定义,复杂类型的参数建议使用自定义type
/**
 * 函数返回结果
 * 可以是void, 基本数据类型,自定义type, 或者其他类型。
 * [可选实现]
 */
export type MyApiResult = {
  fieldA : number,
  fieldB : boolean,
  fieldC : string
}

// 定义 API 对外暴露的错误码,为了更好语法提示和校验效果,建议将错误码用type 定义成联合类型。定义后,使用未指定的错误码将会被警告提示。
// 建议定义的错误码遵循uni错误规范 [详见](https://uniapp.dcloud.net.cn/tutorial/err-spec.html#unierror)。
/**
 * 错误码
 * 根据uni错误码规范要求,建议错误码以90开头,以下是错误码示例:
 * - 9010001 错误信息1
 * - 9010002 错误信息2
 */
export type MyApiErrorCode = 9010001 | 9010002;


// 定义 API 的错误回调参数类型,这里定义成 interface 并继承 IUniError 是为了遵循统一的 Uni错误码规范。
// 这里开发者只需要指定 errCode 的类型,以便获得更好的语法提和校验效果。
/**
 * myApi 的错误回调参数
 */
export interface MyApiFail extends IUniError {
  errCode : MyApiErrorCode
};

// 定义对外暴露的 API 类型,这里是个异步函数
/* 异步函数定义 */
export type MyApi = (options : MyApiOptions) => void


// 定义对外暴露的 API 类型,这里是个同步函数
/* 同步函数定义 */
export type MyApiSync = (paramA : boolean) => MyApiResult


特别注意 interface.uts 是官方推荐的多端一致性的最佳实践,不做强制要求,可以根据自己的实际情况决定是否实现。比如某个插件只有一个平台,不写interface也可以。 interface.uts 文件中定义并 exportinterface 接口例如 MyApiFail 只能在插件内部的 uts 文件代码中使用,不能在 .uvue 文件中使用插件时导入使用。

至此,我们就完成了 interface 的定义,如果你遵循规范,定义了错误码的类型和错误码的 interfaceMyApiFail, 那么你还需要在 unierror.uts 文件中对 MyApiFail 这个接口做具体实现。

编写unierror.uts

为了获得更好语法提示和校验效果,我们在 interface.uts 文件中已经定义了错误的类型和错误的接口。但是错误码对应的具体错误信息,以及错误对象的具体实现,都还没有完成。 unierror.uts 文件就是专门用来实现这些的。

打开 unierror.uts 文件, 键入下面的源码。同样为了说明,源码的每个部分的作用都用注释来说明。

// 首先导入在 interface.uts 文件中定义的错误码类型,和错误的类型
import { MyApiErrorCode, MyApiFail } from "./interface.uts"

/**
 * 定义错误主题,错误主题是Uni错误码的一个标准字段。
 * 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。
 * [可选实现]
 */
export const UniErrorSubject = 'uts-api';


/**
 * 错误信息,定义和错误码对应的语义化的提示信息,为了更好的获取,建议定义成Map类型。
 * @UniError
 * [可选实现]
 */
export const UTSApiUniErrors : Map<MyApiErrorCode, string> = new Map([
  /**
   * 错误码及对应的错误信息
   */
  [9010001, 'custom error mseeage1'],
  [9010002, 'custom error mseeage2'],
]);


/**
 * 错误对象的具体使用实现,该实现会在 index.uts代码中创建使用。
 * 使用时只需要传入特定的错误码即可完成创建。
 */
export class MyApiFailImpl extends UniError implements MyApiFail {
  override errCode: MyApiErrorCode
  /**
   * 错误对象构造函数
   */
  constructor(errCode : MyApiErrorCode) {
    super();
    this.errSubject = UniErrorSubject;
    this.errCode = errCode;
    this.errMsg = UTSApiUniErrors.get(errCode) ?? "";
  }
}

至此我们完成了符合 uni 错误规范的错误码的定义和实现,后面我们就可以去实现插件的具体逻辑了。 Uni错误规范的更多信息详见

实现接口定义和业务逻辑

分别在插件的 app-androidapp-ios 等目录下打开 index.uts 文件,键入下面的插件源码:

harmonyOS


/**
 * 引用鸿蒙系统库,示例如下:
 * import deviceInfo from "@ohos.deviceInfo";
 * [可选实现,按需引入]
 */

/* 引入 interface.uts 文件中定义的变量 */
import { MyApiOptions, MyApiResult, MyApi, MyApiSync } from '../interface.uts';

/* 引入 unierror.uts 文件中定义的变量 */
import { MyApiFailImpl } from '../unierror';

export {
  MyApiOptions
}

/**
 * 引入三方库
 * 暂不支持,请留意后续更新
 */

/**
 * 异步方法
 *
 * uni-app项目中(vue/nvue)调用示例:
 * 1、引入方法声明 import { myApi } from "@/uni_modules/uts-api"
 * 2、方法调用
 * myApi({
 *   paramA: false,
 *   complete: (res) => {
 *      console.log(res)
 *   }
 * });
 *
 */
export const myApi : MyApi = function (options : MyApiOptions) {

  if (options.paramA == true) {
    // 返回数据
    const res : MyApiResult = {
      fieldA: 85,
      fieldB: true,
      fieldC: 'some message'
    };
    options.success?.(res);
    options.complete?.(res);

  } else {
    // 返回错误
    let failResult = new MyApiFailImpl(9010001);
    options.fail?.(failResult)
    options.complete?.(failResult)
  }

}

/**
 * 同步方法
 *
 * uni-app项目中(vue/nvue)调用示例:
 * 1、引入方法声明 import { myApiSync } from "@/uni_modules/uts-api"
 * 2、方法调用
 * myApiSync(true);
 *
 */
export const myApiSync : MyApiSync = function (paramA : boolean) : MyApiResult {
  // 返回数据,根据插件功能获取实际的返回值
  const res : MyApiResult = {
    fieldA: 85,
    fieldB: paramA,
    fieldC: 'some message'
  };
  return res;
}

使用插件

下面的示例代码为uni-app-x代码

上面的代码,我们完成了一个名为 “uts-api” 的UTS 插件,在 uvue 文件中使用该插件的代码示例如下:

// 导入要使用的插件
import { myApi, myApiSync, MyApiOptions } from "@/uni_modules/uts-api";

methods: {

	testMyApi() {
		// 调用异步方法示例
		let options = {
			paramA: false,
			complete: (res : any) => {
			console.log(res)
			}
		} as MyApiOptions;
		myApi(options);
	},

	testMyApiSync() {
		// 调用同步方法示例
		console.log(myApiSync(true))
	},
}

运行和编译uts插件,需要在HBuilderX的设置中配置Android和iOS的环境,见如下文档:

开发uts插件,调试、打断点是重要帮手,参考如下文档

获取电量插件示例

以获取电量为例,介绍uts插件开发步骤

首先在 uni_modules 目录下新建名为 uts-getbatteryinfo 的 uts 插件

在鸿蒙平台目录下,编辑index.uts,键入以下内容。

// index.uts

// 引用android api
import Context from "android.content.Context";
import BatteryManager from "android.os.BatteryManager";
import { UTSAndroid } from "io.dcloud.uts";

export function getBatteryCapacity(): string {
	// 获取android系统 application上下文
    const context = UTSAndroid.getAppContext();
    if (context != null) {
        const manager = context.getSystemService(
            Context.BATTERY_SERVICE
        ) as BatteryManager;
        const currentLevel: number = manager.getIntProperty(
            BatteryManager.BATTERY_PROPERTY_CAPACITY
        );
        return '' + currentLevel + '%';
    }
    return "0%";
}


至此,我们已经完成一个Android平台上获取电量的原生能力封装。

我们可以在vue页面中这样使用它:

import { getBatteryCapacity } from "@/uni_modules/uts-getbatteryinfo";

console.log(getBatteryCapacity())

有些场景下,我们期望 将获取电量的能力封装为 异步的接口,我们可以使用下面的代码

import Context from "android.content.Context";
import BatteryManager from "android.os.BatteryManager";
import { UTSAndroid } from "io.dcloud.uts";


type GetBatteryInfoOptions = {
    success?: (res: object) => void
    fail?: (res: object) => void
    complete?: (res: object) => void
}

export function getBatteryInfo(options: GetBatteryInfoOptions) {
    const context = UTSAndroid.getAppContext();
    if (context != null) {
        const manager = context.getSystemService(
            Context.BATTERY_SERVICE
        ) as BatteryManager;
        const level = manager.getIntProperty(
            BatteryManager.BATTERY_PROPERTY_CAPACITY
        );
        const res = {
            errCode: 0,
            errSubject: "uts-getbatteryinfo",
            errMsg: "getBatteryInfo:ok",
            level,
            isCharging: manager.isCharging()
        }
        options.success?.(res)
        options.complete?.(res)
    } else {
        const res = {
			errCode: 1001,
			errSubject: "uts-getbatteryinfo",
            errMsg: 'getBatteryInfo:fail getAppContext is null'
        }
        options.fail?.(res)
        options.complete?.(res)
    }
}

对应的使用代码需要调整为:

import {getBatteryInfo} from "@/uni_modules/uts-getbatteryinfo";

getBatteryInfo({
	success(res) {
		uni.showToast({
			title: "当前电量:" + res.level + '%',
			icon: 'none'
		});
	}
})

harmonyOS平台

在utssdk目录下创建harmonyOS平台目录app-harmony

在harmonyOS平台目录下,编辑index.uts,键入以下内容,即可完成harmonyOS平台获取电量能力

import batteryInfo from '@ohos.batteryInfo';
import { GetBatteryInfo, GetBatteryInfoOptions, GetBatteryInfoSuccess, GetBatteryInfoResult, GetBatteryInfoSync } from '../interface.uts';

export const getBatteryInfoSync : GetBatteryInfoSync = function () : GetBatteryInfoResult {
  return {
    level: batteryInfo.batterySOC,
    isCharging: batteryInfo.chargingStatus === batteryInfo.BatteryChargeState.ENABLE || batteryInfo.chargingStatus === batteryInfo.BatteryChargeState.FULL,
  };
}

export const getBatteryInfo : GetBatteryInfo = function (options : GetBatteryInfoOptions) {
  const batteryInfoResult : GetBatteryInfoSuccess = {
    errMsg: "getBatteryInfo:ok",
    level: batteryInfo.batterySOC,
    isCharging: batteryInfo.chargingStatus === batteryInfo.BatteryChargeState.ENABLE || batteryInfo.chargingStatus === batteryInfo.BatteryChargeState.FULL,
  }
  try {
    options.success && options.success(batteryInfoResult)
  } catch (e) {
    console.error(e)
  }
  try {
    options.complete && options.complete(batteryInfoResult)
  } catch (e) {
    console.error(e)
  }
}

以上就是整个的uni-appx开发鸿蒙插件示例,希望可以帮到大家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值