@react-native-ohos/react-native-bluetooth-printer
v0.0.2-beta.3
Published
> 文档模板:v0.4.1
Readme
文档模板:v0.4.1
本项目基于 [email protected] 开发。
请到三方库的 Releases 发布地址查看配套的版本信息:
| 三方库名称 | 三方库版本 | 发布信息 | 支持RN版本 | Autolink | 编译API版本 | 社区基线版本 | npm地址 | | ------------ |---------| ------------------------------ |----------------| ------------- |------------------------ |--------| ------------- | | @react-native-ohos/react-native-bluetooth-printer | ~ 0.0.2 | Gitcode Releases | 0.72/0.77/0.82 | 否 | API12+ | 0.0.1 | Npm Address |
简介
bluetooth-printer 是 React Native 的蓝牙打印库。 它提供简洁的 API,支持手机与蓝牙打印设备的快速连接与数据通信,能够高效、稳定地完成打印任务,帮助开发者降低蓝牙集成的复杂度。
下载安装
进入到工程目录并输入以下命令:
npm
npm install @react-native-ohos/react-native-bluetooth-printeryarn
yarn add @react-native-ohos/react-native-bluetooth-printerLink
| | 是否支持autolink | RN框架版本 | |---------|-----------------|----------------| | ~ 0.0.2 | No | 0.72/0.77/0.82 |
使用AutoLink的工程需要根据该文档配置,Autolink框架指导文档:https://gitcode.com/openharmony-sig/ohos_react_native/blob/master/docs/zh-cn/Autolinking.md
首先需要使用 DevEco Studio 打开项目里的 HarmonyOS 工程 harmony。
1. Overrides RN SDK
为了让工程依赖同一个版本的 RN SDK,需要在工程根目录的 oh-package.json5 添加 overrides 字段,指向工程需要使用的 RN SDK 版本。替换的版本既可以是一个具体的版本号,也可以是一个模糊版本,还可以是本地存在的 HAR 包或源码目录。
关于该字段的作用请阅读官方说明
{
"overrides": {
"@rnoh/react-native-openharmony": "^0.72.38" // ohpm 在线版本
// "@rnoh/react-native-openharmony" : "./react_native_openharmony.har" // 指向本地 har 包的路径
// "@rnoh/react-native-openharmony" : "./react_native_openharmony" // 指向源码路径
}
}2. 引入原生端代码
目前有两种方法:
- 通过 har 包引入;
- 直接链接源码。
方法一:通过 har 包引入(推荐)
[!TIP] har 包位于三方库安装路径的
harmony文件夹下。
打开 entry/oh-package.json5,添加以下依赖
"dependencies": {
"@rnoh/react-native-openharmony": "file:../react_native_openharmony",
"@react-native-ohos/react-native-bluetooth-printer": "file:../../node_modules/@react-native-ohos/react-native-bluetooth-printer/harmony/bluetooth_print.har"
}点击右上角的 sync 按钮
或者在终端执行:
cd entry
ohpm install方法二:直接链接源码
[!TIP] 如需使用直接链接源码,请参考直接链接源码说明
3. 配置 CMakeLists 和引入 BluetoothPrintPackage
打开 entry/src/main/cpp/CMakeLists.txt,添加:
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+ set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
# RNOH_BEGIN: manual_package_linking_1
+ add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-bluetooth-printer/src/main/cpp" ./bluetooth_print)
# RNOH_END: manual_package_linking_1
# RNOH_BEGIN: manual_package_linking_2
+ target_link_libraries(rnoh_app PUBLIC rnoh_bluetooth_print)
# RNOH_END: manual_package_linking_2打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "SamplePackage.h"
+ #include "BluetoothPrintPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<SamplePackage>(ctx),
+ std::make_shared<BluetoothPrintPackage>(ctx)
};
}4. 在 ArkTs 侧引入 BluetoothPrintPackage
打开 entry/src/main/ets/RNPackagesFactory.ets,添加:
import type {RNPackageContext, RNPackage} from '@rnoh/react-native-openharmony/ts';
+ import { BluetoothPrintPackage } from '@react-native-ohos/react-native-bluetooth-printer';
export function createRNPackages(ctx: RNPackageContext): RNOHPackage[] {
return [
+ new BluetoothPrintPackage(ctx),
];
}运行
点击右上角的 sync 按钮
或者在命令行终端执行:
cd entry
ohpm install然后编译、运行即可。
约束与限制
兼容性
本文档内容基于以下版本验证通过:
- RNOH: 0.72.96; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
- RNOH: 0.72.33; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
- RNOH: 0.77.18; SDK: HarmonyOS 6.0.0 Release SDK; IDE: DevEco Studio 6.0.0.858; ROM: 6.0.0.112;
- RNOH: 0.82.1; SDK: HarmonyOS 6.0.1 Release SDK; IDE: DevEco Studio 6.0.1 Release; ROM:6.0.0.120 SP7;
使用示例
下面的代码展示了这个库的基本使用场景:
[!WARNING] 使用时 import 的库名不变。
import React, { useMemo, useRef, useState } from 'react';
import {
Alert,
Button,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import BluetoothPrint, {
type BluetoothDevice,
type IDevices,
} from '@react-native-ohos/react-native-bluetooth-printer'
function App() {
const [isBluetoothOpen, setIsBluetoothOpen] = useState<boolean>(false);
const [isScanning, setIsScanning] = useState<boolean>(false);
const [devices, setDevices] = useState<BluetoothDevice[]>([]);
const [selectedDeviceId, setSelectedDeviceId] = useState<string>('');
const [connectedDevice, setConnectedDevice] = useState<IDevices | null>(null);
const [connecting, setConnecting] = useState<boolean>(false);
const [printing, setPrinting] = useState<boolean>(false);
const connectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const currentClientNumber = useMemo(() => connectedDevice?.socketId ?? -1, [connectedDevice]);
const syncBluetoothState = () => {
const open = BluetoothPrint.isOpenBluetooth();
setIsBluetoothOpen(Boolean(open));
if (!open) {
Alert.alert('提示', '蓝牙未打开,已尝试唤起系统蓝牙。请手动确认蓝牙已开启后再试。');
}
};
const requestPermission = () => {
BluetoothPrint.requestBluetoothPermission();
Alert.alert('提示', '权限弹窗已触发,请在系统中授权蓝牙权限。');
};
const startScan = () => {
setDevices([]);
setSelectedDeviceId('');
setIsScanning(true);
BluetoothPrint.startScanBluetoothDevices((list) => {
setDevices(list);
});
};
const stopScan = () => {
BluetoothPrint.stopScanBluetoothDevices();
setIsScanning(false);
};
const connectSelectedDevice = () => {
if (!selectedDeviceId) {
Alert.alert('提示', '请先选择一个设备');
return;
}
setConnecting(true);
if (isScanning) {
// Stop scanning before connecting to reduce BLE connection conflicts.
stopScan();
}
if (connectTimeoutRef.current) {
clearTimeout(connectTimeoutRef.current);
connectTimeoutRef.current = null;
}
connectTimeoutRef.current = setTimeout(() => {
setConnecting(false);
Alert.alert('连接超时', '未收到连接成功回调,请确认设备可配对、蓝牙权限已授权。');
connectTimeoutRef.current = null;
}, 200000);
try {
BluetoothPrint.connect(selectedDeviceId, (device) => {
if (connectTimeoutRef.current) {
clearTimeout(connectTimeoutRef.current);
connectTimeoutRef.current = null;
}
setConnectedDevice(device);
setConnecting(false);
Alert.alert('连接成功', `${device.deviceName} (${device.deviceId})`);
});
} catch (e) {
if (connectTimeoutRef.current) {
clearTimeout(connectTimeoutRef.current);
connectTimeoutRef.current = null;
}
setConnecting(false);
Alert.alert('连接失败', String(e));
}
};
const printText = async () => {
if (!selectedDeviceId || currentClientNumber === -1) {
Alert.alert('提示', '请先完成设备连接');
return;
}
try {
setPrinting(true);
await BluetoothPrint.printForFile(currentClientNumber, selectedDeviceId);
Alert.alert('提示', '已触发文本打印');
} catch (e) {
Alert.alert('错误', `文本打印失败: ${String(e)}`);
} finally {
setPrinting(false);
}
};
const printImage = async () => {
if (!selectedDeviceId || currentClientNumber === -1) {
Alert.alert('提示', '请先完成设备连接');
return;
}
try {
setPrinting(true);
await BluetoothPrint.printForImage(currentClientNumber, selectedDeviceId);
Alert.alert('提示', '已触发图片打印');
} catch (e) {
Alert.alert('错误', `图片打印失败: ${String(e)}`);
} finally {
setPrinting(false);
}
};
return (
<SafeAreaView style={styles.container}>
<ScrollView contentContainerStyle={styles.content}>
<Text style={styles.title}>RNBluetoothPrint Harmony Demo</Text>
<Text style={styles.status}>蓝牙状态:{isBluetoothOpen ? '已开启' : '未开启'}</Text>
<Text style={styles.status}>
当前连接:{connectedDevice ? `${connectedDevice.deviceName} (${connectedDevice.socketId})` : '未连接'}
</Text>
<Text style={styles.status}>扫描状态:{isScanning ? '扫描中' : '未扫描'}</Text>
<View style={styles.row}>
<Button title="检查蓝牙状态" onPress={syncBluetoothState} />
</View>
<View style={styles.row}>
<Button title="申请蓝牙权限" onPress={requestPermission} />
</View>
<View style={styles.row}>
<Button title={isScanning ? '停止扫描' : '开始扫描'} onPress={isScanning ? stopScan : startScan} />
</View>
<View style={styles.row}>
<Button
title={connecting ? '连接中...' : '连接选中设备'}
onPress={connectSelectedDevice}
disabled={connecting}
/>
</View>
<View style={styles.row}>
<Button title={printing ? '打印中...' : '打印文本'} onPress={printText} disabled={printing} />
</View>
<View style={styles.row}>
<Button title={printing ? '打印中...' : '打印图片'} onPress={printImage} disabled={printing} />
</View>
<Text style={styles.subtitle}>扫描到的设备(点击选择)</Text>
{devices.length === 0 ? (
<Text style={styles.empty}>暂无设备,请先开始扫描</Text>
) : (
devices.map((item) => {
const selected = selectedDeviceId === item.deviceId;
const isConnected = connectedDevice?.deviceId === item.deviceId;
return (
<TouchableOpacity
key={item.deviceId}
style={[styles.card, selected && styles.cardSelected]}
onPress={() => setSelectedDeviceId(item.deviceId)}
>
<Text style={styles.deviceName}>{item.deviceName || '未知设备'}</Text>
<Text style={styles.deviceId}>{item.deviceId}</Text>
<Text style={styles.deviceRssi}>RSSI: {item.rssi ?? '--'}</Text>
{isConnected ? <Text style={styles.connectedTag}>状态:已连接</Text> : null}
</TouchableOpacity>
);
})
)}
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f2f5f7',
},
content: {
padding: 16,
paddingBottom: 32,
},
title: {
fontSize: 20,
fontWeight: '700',
color: '#1a1a1a',
marginBottom: 8,
},
subtitle: {
marginTop: 16,
marginBottom: 8,
fontSize: 16,
fontWeight: '600',
color: '#1a1a1a',
},
status: {
fontSize: 14,
color: '#333333',
marginTop: 4,
},
row: {
marginTop: 10,
},
empty: {
marginTop: 8,
color: '#666666',
},
card: {
backgroundColor: '#ffffff',
borderRadius: 8,
padding: 12,
marginTop: 10,
borderWidth: 1,
borderColor: '#d9d9d9',
},
cardSelected: {
borderColor: '#2f80ed',
backgroundColor: '#edf4ff',
},
deviceName: {
fontSize: 15,
fontWeight: '600',
color: '#111111',
},
deviceId: {
fontSize: 12,
color: '#666666',
marginTop: 4,
},
deviceRssi: {
fontSize: 12,
color: '#666666',
marginTop: 4,
},
connectedTag: {
marginTop: 6,
color: '#0b8f3a',
fontSize: 12,
fontWeight: '600',
},
});
export const examples = [
{
title: 'react-native-bluetooth-printer',
render: function (): any {
return <App />;
},
},
];接口说明
API
[!TIP] "Platform"列表示该属性在原三方库上支持的平台。
[!TIP] "OpenHarmony Support"列为 yes 表示 OpenHarmony平台支持 该属性;no 则表示不支持;partially 表示部分支持。使用方法跨平台一致,效果对标 iOS 或 Android 的效果。
| 名称 | 类型 | 参数类型 | 返回值 | 必填 | 平台 | OpenHarmony平台支持 | 描述 | |-----------|:--------:|--------------------------------------------------|------|-----|------|-----------------|-----------------------| | connect |function | mac: string, cb: Callback | void | No | Android | Yes | 初始化蓝牙服务,连接蓝牙打印机 | | check |function | cb: Callback | void | No | Android | Yes | 检查蓝牙打印机连接可用性 | | print |function | imgurl: string, pixelWidth: number, cb: Callback | void | No | Android | Yes | 打印指定本地路径(imgurl)的图片 | | print_p |function | imgurl: string, pixelWidth: number | void | No | Android | Yes | 异步打印指定本地路径(imgurl)的图片 | | check_p |function | / | void | No | Android | Yes | 异步检查蓝牙打印机连接可用性 | | list_p |function | / | void | No | Android | Yes | 异步获取已配对的蓝牙设备列表 | | connect_p |function | mac: string | void | No | Android | Yes | 异步连接蓝牙打印机 |
遗留问题
无
其他
无
目录结构
/react-native-bluetooth-printer # 项目根目录
├── harmony # 鸿蒙适配代码
│ └─ bluetooth_print.har # har包
│ └─ bluetooth_print # 鸿蒙适配核心代码
│ └─ Index.ets # 鸿蒙适配代码入口
│ └─ src/main/ets
│ └─ BluetoothPrintPackage.ts # bluetooth-printer包封装
├── src # RN代码
│ └─ index.ts # 入口文件
├── README.md # 安装使用方法 贡献代码
使用过程中发现任何问题都可以提交 Issue,当然,也非常欢迎提交 PR 。
开源协议
本项目基于 MIT ,请自由地享受和参与开源。
