uniapp开发鸿蒙:原生能力调用实战

引入:跨平台开发的核心能力

在之前的文章中,我们已经掌握了uniapp在鸿蒙平台下的基础开发技能。今天,我们将深入探讨uniapp调用鸿蒙原生能力的完整方案,这是实现复杂业务功能、提升应用体验的关键环节。

uniapp通过uni-app框架提供了丰富的API,同时支持通过原生插件扩展能力。在鸿蒙平台下,我们还可以直接调用鸿蒙的ArkTS原生能力,实现更底层的功能调用。本文将系统讲解这三种方式的实现方案。

一、uni-app内置API调用

1.1 设备信息获取

获取设备信息

// 获取设备信息
uni.getSystemInfo({
  success: (res) => {
    console.log('设备品牌:', res.brand)
    console.log('设备型号:', res.model)
    console.log('系统版本:', res.system)
    console.log('屏幕尺寸:', res.screenWidth, res.screenHeight)
    console.log('DPI:', res.pixelRatio)
  }
})

// 获取设备基础信息
const systemInfo = uni.getSystemInfoSync()
console.log('设备信息:', systemInfo)

获取网络状态

// 监听网络状态变化
uni.onNetworkStatusChange((res) => {
  console.log('网络类型:', res.networkType)
  console.log('是否联网:', res.isConnected)
})

// 获取当前网络状态
uni.getNetworkType({
  success: (res) => {
    console.log('当前网络:', res.networkType)
  }
})

1.2 地理位置服务

获取当前位置

// 获取当前位置
uni.getLocation({
  type: 'gcj02', // 坐标系类型
  success: (res) => {
    console.log('经度:', res.longitude)
    console.log('纬度:', res.latitude)
    console.log('速度:', res.speed)
    console.log('精度:', res.accuracy)
  },
  fail: (err) => {
    console.error('获取位置失败:', err)
  }
})

// 持续定位
const locationId = uni.startLocationUpdate({
  type: 'gcj02',
  success: () => {
    console.log('开始持续定位')
  }
})

// 停止定位
uni.stopLocationUpdate({
  success: () => {
    console.log('停止持续定位')
  }
})

1.3 设备传感器

加速度计

// 监听加速度计
uni.onAccelerometerChange((res) => {
  console.log('X轴加速度:', res.x)
  console.log('Y轴加速度:', res.y)
  console.log('Z轴加速度:', res.z)
})

// 开始监听
uni.startAccelerometer({
  interval: 'normal'
})

// 停止监听
uni.stopAccelerometer()

陀螺仪

// 监听陀螺仪
uni.onGyroscopeChange((res) => {
  console.log('X轴角速度:', res.x)
  console.log('Y轴角速度:', res.y)
  console.log('Z轴角速度:', res.z)
})

// 开始监听
uni.startGyroscope({
  interval: 'normal'
})

// 停止监听
uni.stopGyroscope()

1.4 文件系统操作

文件读写

// 读取文件
uni.getFileSystemManager().readFile({
  filePath: 'file:///path/to/file.txt',
  encoding: 'utf8',
  success: (res) => {
    console.log('文件内容:', res.data)
  }
})

// 写入文件
uni.getFileSystemManager().writeFile({
  filePath: 'file:///path/to/file.txt',
  data: 'Hello World',
  encoding: 'utf8',
  success: () => {
    console.log('写入成功')
  }
})

// 获取文件信息
uni.getFileSystemManager().getFileInfo({
  filePath: 'file:///path/to/file.txt',
  success: (res) => {
    console.log('文件大小:', res.size)
  }
})

二、鸿蒙原生API调用

2.1 权限申请

权限列表

// 检查权限
uni.authorize({
  scope: 'scope.userLocation',
  success: () => {
    console.log('位置权限已授权')
  },
  fail: () => {
    console.log('位置权限未授权')
  }
})

// 常用权限scope
const PERMISSIONS = {
  LOCATION: 'scope.userLocation', // 位置信息
  CAMERA: 'scope.camera', // 相机
  RECORD: 'scope.record', // 录音
  USER_INFO: 'scope.userInfo', // 用户信息
  ADDRESS: 'scope.address', // 通讯地址
  INVOICE: 'scope.invoice', // 发票抬头
  WERUN: 'scope.werun', // 微信运动
  WRITE_PHOTOS: 'scope.writePhotosAlbum' // 保存到相册
}

2.2 系统能力调用

拨打电话

uni.makePhoneCall({
  phoneNumber: '10086',
  success: () => {
    console.log('拨号成功')
  }
})

发送短信

uni.sendSms({
  phoneNumber: '10086',
  content: 'Hello',
  success: () => {
    console.log('发送成功')
  }
})

打开系统设置

uni.openSetting({
  success: (res) => {
    console.log('设置页面打开成功')
  }
})

获取剪贴板内容

uni.getClipboardData({
  success: (res) => {
    console.log('剪贴板内容:', res.data)
  }
})

// 设置剪贴板内容
uni.setClipboardData({
  data: 'Hello World',
  success: () => {
    console.log('复制成功')
  }
})

2.3 设备振动

短振动

uni.vibrateShort({
  success: () => {
    console.log('振动成功')
  }
})

// 长振动
uni.vibrateLong({
  success: () => {
    console.log('长振动成功')
  }
})

2.4 屏幕亮度

获取屏幕亮度

uni.getScreenBrightness({
  success: (res) => {
    console.log('屏幕亮度:', res.value)
  }
})

// 设置屏幕亮度
uni.setScreenBrightness({
  value: 0.8,
  success: () => {
    console.log('设置亮度成功')
  }
})

// 保持屏幕常亮
uni.setKeepScreenOn({
  keepScreenOn: true,
  success: () => {
    console.log('屏幕常亮开启')
  }
})

三、原生插件开发

3.1 插件项目结构

创建插件项目

# 创建原生插件项目
npx @dcloudio/uni-plugin create my-plugin

项目结构

my-plugin/
├── android/          # Android原生代码
├── ios/              # iOS原生代码
├── harmony/           # 鸿蒙原生代码
├── package.json
├── plugin.json       # 插件配置文件
└── src/
    └── index.js      # JS接口文件

3.2 鸿蒙原生代码实现

harmony/ets/MyPlugin.ets

import plugin from '@ohos.hap.plugin'

@Entry
@Component
struct MyPlugin {
  @State message: string = 'Hello World'

  build() {
    Column() {
      Text(this.message)
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
    }
    .width('100%')
    .height('100%')
  }
}

// 原生方法实现
export class MyPluginImpl {
  static getDeviceInfo(): string {
    const deviceInfo = deviceInfo.getDeviceInfoSync()
    return JSON.stringify({
      brand: deviceInfo.brand,
      model: deviceInfo.model,
      system: deviceInfo.system
    })
  }

  static showToast(message: string): void {
    prompt.showToast({
      message: message,
      duration: 2000
    })
  }
}

// 注册插件
plugin.registerPlugin('my-plugin', MyPluginImpl)

3.3 JS接口封装

src/index.js

// JS接口文件
export default {
  // 获取设备信息
  getDeviceInfo() {
    return new Promise((resolve, reject) => {
      // 调用鸿蒙原生方法
      const result = uni.requireNativePlugin('my-plugin').getDeviceInfo()
      if (result) {
        resolve(JSON.parse(result))
      } else {
        reject(new Error('获取设备信息失败'))
      }
    })
  },

  // 显示原生Toast
  showToast(message) {
    uni.requireNativePlugin('my-plugin').showToast(message)
  }
}

3.4 插件配置

plugin.json

{
  "name": "my-plugin",
  "id": "my-plugin",
  "version": "1.0.0",
  "description": "自定义原生插件",
  "main": "src/index.js",
  "platforms": ["android", "ios", "harmony"],
  "dependencies": {}
}

3.5 在uniapp中使用插件

安装插件

# 在uniapp项目中安装插件
npm install ./my-plugin

在页面中使用

import myPlugin from 'my-plugin'

// 获取设备信息
myPlugin.getDeviceInfo().then(info => {
  console.log('设备信息:', info)
})

// 显示Toast
myPlugin.showToast('Hello from native plugin')

四、ArkTS原生能力调用

4.1 条件编译调用原生API

在uniapp中调用ArkTS

// #ifdef HARMONYOS
// 鸿蒙平台下调用ArkTS原生API
const { getSystemInfo } = require('@system.app')
getSystemInfo({
  success: (res) => {
    console.log('系统信息:', res)
  }
})
// #endif

// #ifndef HARMONYOS
// 其他平台使用uni-app API
uni.getSystemInfo({
  success: (res) => {
    console.log('系统信息:', res)
  }
})
// #endif

4.2 常用ArkTS API

应用信息

// #ifdef HARMONYOS
const app = require('@system.app')

// 获取应用信息
app.getInfo({
  success: (res) => {
    console.log('应用名称:', res.name)
    console.log('版本号:', res.versionName)
  }
})

// 退出应用
app.terminate()
// #endif

路由跳转

// #ifdef HARMONYOS
const router = require('@system.router')

// 跳转到页面
router.push({
  uri: 'pages/index/index'
})

// 返回上一页
router.back()

// 替换当前页
router.replace({
  uri: 'pages/detail/detail'
})
// #endif

存储系统

// #ifdef HARMONYOS
const storage = require('@system.storage')

// 存储数据
storage.set({
  key: 'token',
  value: 'your_token',
  success: () => {
    console.log('存储成功')
  }
})

// 读取数据
storage.get({
  key: 'token',
  success: (res) => {
    console.log('读取成功:', res.value)
  }
})

// 删除数据
storage.delete({
  key: 'token',
  success: () => {
    console.log('删除成功')
  }
})
// #endif

五、跨平台适配方案

5.1 平台判断

判断当前平台

// 判断平台
const platform = uni.getSystemInfoSync().platform

// 条件编译
// #ifdef HARMONYOS
console.log('当前平台: 鸿蒙')
// #endif

// #ifdef APP-PLUS
console.log('当前平台: App')
// #endif

// #ifdef H5
console.log('当前平台: H5')
// #endif

// #ifdef MP-WEIXIN
console.log('当前平台: 微信小程序')
// #endif

5.2 统一API封装

封装跨平台API

// utils/native.js
export const native = {
  // 获取设备信息
  getDeviceInfo() {
    // #ifdef HARMONYOS
    return new Promise((resolve) => {
      const { getSystemInfo } = require('@system.app')
      getSystemInfo({
        success: resolve
      })
    })
    // #endif
    
    // #ifndef HARMONYOS
    return new Promise((resolve) => {
      uni.getSystemInfo({
        success: resolve
      })
    })
    // #endif
  },

  // 显示Toast
  showToast(message) {
    // #ifdef HARMONYOS
    const { showToast } = require('@system.prompt')
    showToast({
      message: message,
      duration: 2000
    })
    // #endif
    
    // #ifndef HARMONYOS
    uni.showToast({
      title: message,
      icon: 'none'
    })
    // #endif
  },

  // 拨打电话
  makePhoneCall(phoneNumber) {
    // #ifdef HARMONYOS
    const { makeCall } = require('@system.telephone')
    makeCall({
      number: phoneNumber
    })
    // #endif
    
    // #ifndef HARMONYOS
    uni.makePhoneCall({
      phoneNumber: phoneNumber
    })
    // #endif
  }
}

5.3 在页面中使用

import { native } from '@/utils/native'

// 获取设备信息
native.getDeviceInfo().then(info => {
  console.log('设备信息:', info)
})

// 显示Toast
native.showToast('Hello')

// 拨打电话
native.makePhoneCall('10086')

六、实战案例:拍照上传功能

6.1 拍照功能实现

import { native } from '@/utils/native'

export const takePhoto = () => {
  return new Promise((resolve, reject) => {
    // #ifdef HARMONYOS
    const { takePhoto } = require('@system.camera')
    takePhoto({
      success: (res) => {
        resolve(res.uri)
      },
      fail: reject
    })
    // #endif
    
    // #ifndef HARMONYOS
    uni.chooseImage({
      count: 1,
      sourceType: ['camera'],
      success: (res) => {
        resolve(res.tempFilePaths[0])
      },
      fail: reject
    })
    // #endif
  })
}

6.2 图片上传功能

import { uploadFile } from '@/utils/upload'

export const uploadPhoto = async () => {
  try {
    // 拍照
    const imagePath = await takePhoto()
    
    // 上传到服务器
    const result = await uploadFile(imagePath)
    
    // 显示上传成功
    native.showToast('上传成功')
    
    return result
  } catch (error) {
    console.error('拍照上传失败:', error)
    native.showToast('上传失败')
    throw error
  }
}

6.3 在页面中使用

<template>
  <view>
    <button @click="handleTakePhoto">拍照上传</button>
    <image v-if="imageUrl" :src="imageUrl" mode="aspectFill" />
  </view>
</template>

<script setup>
import { ref } from 'vue'
import { uploadPhoto } from '@/utils/photo'

const imageUrl = ref('')

const handleTakePhoto = async () => {
  try {
    const result = await uploadPhoto()
    imageUrl.value = result.url
  } catch (error) {
    console.error('拍照上传失败:', error)
  }
}
</script>

七、鸿蒙平台特有配置

7.1 权限配置

manifest.json

{
  "app-plus": {
    "harmony": {
      "requestPermissions": [
        {
          "name": "ohos.permission.CAMERA"
        },
        {
          "name": "ohos.permission.READ_MEDIA"
        },
        {
          "name": "ohos.permission.WRITE_MEDIA"
        },
        {
          "name": "ohos.permission.INTERNET"
        },
        {
          "name": "ohos.permission.LOCATION"
        }
      ]
    }
  }
}

7.2 应用配置

{
  "app-plus": {
    "harmony": {
      "appId": "com.example.myapp",
      "appName": "我的应用",
      "versionName": "1.0.0",
      "versionCode": 100,
      "minPlatformVersion": 9,
      "compileSdkVersion": 9,
      "targetSdkVersion": 9
    }
  }
}

八、常见问题与解决方案

8.1 权限申请失败

问题:在鸿蒙平台下,部分权限需要动态申请。

解决方案

// 动态申请权限
uni.authorize({
  scope: 'scope.camera',
  success: () => {
    console.log('相机权限已授权')
  },
  fail: () => {
    uni.showModal({
      title: '提示',
      content: '需要相机权限才能使用拍照功能',
      success: (res) => {
        if (res.confirm) {
          uni.openSetting()
        }
      }
    })
  }
})

8.2 原生插件调用失败

问题:原生插件未正确注册或配置。

解决方案

  1. 检查plugin.json配置是否正确
  2. 确认原生代码已正确编译
  3. 检查权限配置是否完整

8.3 跨平台兼容性问题

问题:不同平台API行为不一致。

解决方案

  1. 使用条件编译区分不同平台
  2. 封装统一的API接口
  3. 在开发阶段充分测试各平台

总结

通过本篇文章的学习,我们掌握了uniapp在鸿蒙平台下调用原生能力的完整方案:

  1. uni-app内置API:设备信息、地理位置、传感器等基础能力
  2. 鸿蒙原生API:权限申请、系统能力、设备振动等系统级功能
  3. 原生插件开发:自定义插件的开发、配置和使用
  4. ArkTS原生调用:条件编译调用鸿蒙原生API
  5. 跨平台适配:统一API封装和平台判断
  6. 实战案例:拍照上传功能的完整实现

关键要点

  • 优先使用uni-app内置API,保证跨平台兼容性
  • 原生插件适用于复杂业务场景和性能优化
  • 条件编译是实现跨平台适配的有效手段
  • 权限申请是鸿蒙平台下的必要步骤

下一篇文章,我们将深入讲解性能优化与调试,包括启动速度优化、渲染性能优化、内存管理等核心内容,帮助您构建更高效的应用。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐