鸿蒙智能快递柜取件助手开发指南 原创
鸿蒙智能快递柜取件助手开发指南
一、系统架构设计
基于HarmonyOS的智能快递柜取件助手,利用短信识别和分布式能力实现以下功能:
短信识别:自动解析短信中的取件码和快递柜位置
跨设备同步:手机识别取件码,大屏展示取件信息
一键开柜:支持远程开柜操作
取件提醒:智能提醒未取快递
!https://example.com/harmony-parcel-helper-arch.png
二、核心代码实现
短信解析服务
// SmsParserService.ets
import sms from ‘@ohos.telephony.sms’;
import distributedData from ‘@ohos.distributedData’;
class SmsParserService {
private static instance: SmsParserService = null;
private dataManager: distributedData.DataManager;
private parcelListeners: ParcelListener[] = [];
private constructor() {
this.initDataManager();
this.initSmsListener();
public static getInstance(): SmsParserService {
if (!SmsParserService.instance) {
  SmsParserService.instance = new SmsParserService();
return SmsParserService.instance;
private initDataManager(): void {
this.dataManager = distributedData.createDataManager({
  bundleName: 'com.example.parcelhelper',
  area: distributedData.Area.GLOBAL,
  isEncrypted: true
});
this.dataManager.registerDataListener('parcel_sync', (data) => {
  this.handleSyncData(data);
});
private initSmsListener(): void {
try {
  sms.on('smsReceive', (data) => {
    this.parseSms(data.message);
  });
catch (err) {
  console.error('初始化短信监听失败:', JSON.stringify(err));
}
private parseSms(message: string): void {
// 常见快递柜短信格式正则匹配
const patterns = [
/取件码(\d{4,6})[\s,,]+请至(.+?)快递柜取件/i,
/验证码:(\d{4,6})[\s,,]+地址:(.+?)快递柜/i,
/【(.+?)】您的取件码是(\d{4,6})[\s,,]+请到(.+?)取件/i
];
let code = '';
let location = '';
let carrier = '';
for (const pattern of patterns) {
  const match = message.match(pattern);
  if (match) {
    if (match.length >= 3) {
      code = match[1];
      location = match[2];
if (match.length >= 4) {
      carrier = match[1];
break;
}
if (code && location) {
  const parcelInfo: ParcelInfo = {
    id: Date.now().toString(),
    code: code,
    location: location,
    carrier: carrier || '未知快递',
    receiveTime: Date.now(),
    status: '待取件',
    message: message
  };
  
  this.notifyParcelFound(parcelInfo);
  this.syncParcelInfo(parcelInfo);
}
private notifyParcelFound(info: ParcelInfo): void {
this.parcelListeners.forEach(listener => {
listener.onParcelFound(info);
});
private syncParcelInfo(info: ParcelInfo): void {
this.dataManager.syncData('parcel_sync', {
  type: 'parcel_info',
  info: info,
  timestamp: Date.now()
});
private handleSyncData(data: any): void {
if (!data || data.type !== 'parcel_info') return;
this.parcelListeners.forEach(listener => {
  listener.onParcelFound(data.info);
});
public addParcelListener(listener: ParcelListener): void {
if (!this.parcelListeners.includes(listener)) {
  this.parcelListeners.push(listener);
}
public removeParcelListener(listener: ParcelListener): void {
this.parcelListeners = this.parcelListeners.filter(l => l !== listener);
}
interface ParcelListener {
onParcelFound(info: ParcelInfo): void;
interface ParcelInfo {
id: string;
code: string;
location: string;
carrier: string;
receiveTime: number;
status: ‘待取件’ ‘已取件’
‘已过期’;
message: string;
export const smsService = SmsParserService.getInstance();
快递柜控制服务
// LockerControlService.ets
import distributedData from ‘@ohos.distributedData’;
import http from ‘@ohos.net.http’;
class LockerControlService {
private static instance: LockerControlService = null;
private dataManager: distributedData.DataManager;
private controlListeners: ControlListener[] = [];
private constructor() {
this.initDataManager();
public static getInstance(): LockerControlService {
if (!LockerControlService.instance) {
  LockerControlService.instance = new LockerControlService();
return LockerControlService.instance;
private initDataManager(): void {
this.dataManager = distributedData.createDataManager({
  bundleName: 'com.example.parcelhelper',
  area: distributedData.Area.GLOBAL,
  isEncrypted: true
});
this.dataManager.registerDataListener('locker_sync', (data) => {
  this.handleSyncData(data);
});
public async openLocker(lockerId: string, code: string): Promise<boolean> {
try {
  // 实际应用中应调用快递柜API
  const httpRequest = http.createHttp();
  const response = await httpRequest.request(
    'https://api.example.com/open-locker',
method: ‘POST’,
      header: { 'Content-Type': 'application/json' },
      extraData: JSON.stringify({ lockerId, code })
);
  if (response.responseCode === 200) {
    const result = JSON.parse(response.result);
    if (result.success) {
      this.syncLockerStatus(lockerId, 'opened');
      return true;
}
  return false;
catch (err) {
  console.error('开柜请求失败:', JSON.stringify(err));
  return false;
}
private syncLockerStatus(lockerId: string, status: string): void {
this.dataManager.syncData(‘locker_sync’, {
type: ‘locker_status’,
lockerId: lockerId,
status: status,
timestamp: Date.now()
});
private handleSyncData(data: any): void {
if (!data) return;
switch (data.type) {
  case 'locker_status':
    this.controlListeners.forEach(listener => {
      listener.onLockerStatusChange(data.lockerId, data.status);
    });
    break;
  
  case 'open_request':
    this.handleOpenRequest(data.fromDevice, data.lockerId, data.code);
    break;
}
private handleOpenRequest(fromDevice: string, lockerId: string, code: string): void {
// 显示确认对话框
const dialog = new AlertDialog({
title: ‘开柜请求’,
message: 设备 {fromDevice} 请求打开 {lockerId} 快递柜,
buttons: [
text: ‘允许’,
      action: async () => {
        const success = await this.openLocker(lockerId, code);
        prompt.showToast({ 
          message: success ? '开柜成功' : '开柜失败' 
        });
},
text: ‘拒绝’,
      action: () => {
        prompt.showToast({ message: '已拒绝请求' });
}
});
dialog.show();
public async requestOpenLocker(deviceId: string, lockerId: string, code: string): Promise<void> {
this.dataManager.syncData('locker_sync', {
  type: 'open_request',
  fromDevice: this.dataManager.getDeviceId(),
  lockerId: lockerId,
  code: code,
  timestamp: Date.now()
});
public addControlListener(listener: ControlListener): void {
if (!this.controlListeners.includes(listener)) {
  this.controlListeners.push(listener);
}
public removeControlListener(listener: ControlListener): void {
this.controlListeners = this.controlListeners.filter(l => l !== listener);
}
interface ControlListener {
onLockerStatusChange(lockerId: string, status: string): void;
export const lockerService = LockerControlService.getInstance();
主界面实现
// MainScreen.ets
import { smsService } from ‘./SmsParserService’;
import { lockerService } from ‘./LockerControlService’;
@Component
export struct MainScreen {
@State parcels: ParcelInfo[] = [];
@State selectedParcel: ParcelInfo | null = null;
@State connectedDevices: string[] = [];
build() {
Column() {
// 标题栏
Row() {
Text(‘智能快递柜取件助手’)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
    Button('协同')
      .width(80)
      .onClick(() => {
        this.showDeviceSelector();
      })
.padding(10)
  .width('100%')
  
  // 快递列表
  if (this.parcels.length === 0) {
    Column() {
      Image($r('app.media.ic_empty'))
        .width(120)
        .height(120)
        .margin({ bottom: 20 })
      
      Text('暂无待取快递')
        .fontSize(16)
.width(‘100%’)
    .height('60%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
else {
    List() {
      ForEach(this.parcels, (parcel) => {
        ListItem() {
          Column() {
            Row() {
              Text(parcel.carrier)
                .fontSize(18)
                .fontWeight(FontWeight.Bold)
                .layoutWeight(1)
              
              Text(this.formatTime(parcel.receiveTime))
                .fontSize(12)
                .fontColor('#666666')
.margin({ bottom: 8 })
            Row() {
              Text(取件码: ${parcel.code})
                .fontSize(16)
                .layoutWeight(1)
              
              Text(parcel.status === '待取件' ? '待取件' : '已取件')
                .fontSize(14)
                .fontColor(parcel.status === '待取件' ? '#FF9800' : '#4CAF50')
Text(parcel.location)
              .fontSize(14)
              .fontColor('#666666')
              .margin({ top: 8 })
.padding(15)
          .width('100%')
          .borderRadius(8)
          .backgroundColor(this.selectedParcel?.id === parcel.id ? '#E3F2FD' : Color.White)
.onClick(() => {
          this.selectedParcel = parcel;
        })
      })
.height(‘60%’)
    .margin({ bottom: 20 })
// 控制区域
  if (this.selectedParcel) {
    Column() {
      Button('一键开柜')
        .width('80%')
        .height(50)
        .margin({ bottom: 10 })
        .onClick(() => {
          this.openSelectedLocker();
        })
      
      Button('分享取件码')
        .width('80%')
        .height(50)
        .onClick(() => {
          this.shareParcelInfo();
        })
}
  // 设备连接状态
  if (this.connectedDevices.length > 0) {
    Column() {
      Text('已连接设备')
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 8 })
      
      ForEach(this.connectedDevices, (device) => {
        Text(device)
          .fontSize(14)
          .margin({ bottom: 4 })
      })
.padding(10)
    .width('90%')
    .backgroundColor('#F5F5F5')
    .borderRadius(8)
    .margin({ top: 20 })
}
.width('100%')
.height('100%')
.padding(20)
.onAppear(() => {
  smsService.addParcelListener({
    onParcelFound: (info) => {
      this.addParcel(info);
});
  lockerService.addControlListener({
    onLockerStatusChange: (lockerId, status) => {
      this.updateLockerStatus(lockerId, status);
});
})
.onDisappear(() => {
  smsService.removeParcelListener({
    onParcelFound: () => {}
  });
  
  lockerService.removeControlListener({
    onLockerStatusChange: () => {}
  });
})
private addParcel(info: ParcelInfo): void {
// 避免重复添加
if (!this.parcels.some(p => p.id === info.id || 
    (p.code = info.code && p.location = info.location))) {
  this.parcels = [info, ...this.parcels];
}
private updateLockerStatus(lockerId: string, status: string): void {
if (status === ‘opened’ && this.selectedParcel) {
this.parcels = this.parcels.map(p => {
if (p.id === this.selectedParcel?.id) {
return { …p, status: ‘已取件’ };
return p;
  });
  
  this.selectedParcel = null;
  prompt.showToast({ message: '取件成功' });
}
private openSelectedLocker(): void {
if (!this.selectedParcel) return;
lockerService.openLocker(
  this.selectedParcel.location,
  this.selectedParcel.code
).then(success => {
  prompt.showToast({ 
    message: success ? '开柜请求已发送' : '开柜请求失败' 
  });
});
private shareParcelInfo(): void {
if (!this.selectedParcel) return;
const devices = ['设备1', '设备2', '设备3']; // 实际应从设备管理服务获取
const dialog = new AlertDialog({
  title: '分享到设备',
  items: devices,
  onSelect: (index) => {
    this.sendToDevice(devices[index]);
});
dialog.show();
private sendToDevice(deviceId: string): void {
if (!this.selectedParcel) return;
lockerService.requestOpenLocker(
  deviceId,
  this.selectedParcel.location,
  this.selectedParcel.code
);
prompt.showToast({ message: 已分享到 ${deviceId} });
private showDeviceSelector(): void {
const devices = ['设备1', '设备2', '设备3']; // 实际应从设备管理服务获取
const dialog = new AlertDialog({
  title: '选择协同设备',
  items: devices,
  onSelect: (index) => {
    this.connectToDevice(devices[index]);
});
dialog.show();
private connectToDevice(deviceId: string): void {
if (!this.connectedDevices.includes(deviceId)) {
  this.connectedDevices.push(deviceId);
  prompt.showToast({ message: 已连接 ${deviceId} });
}
private formatTime(timestamp: number): string {
const date = new Date(timestamp);
return {date.getMonth()+1}/{date.getDate()} {date.getHours()}:{date.getMinutes().toString().padStart(2, ‘0’)};
}
三、项目配置与权限
权限配置
// module.json5
“module”: {
"requestPermissions": [
“name”: “ohos.permission.RECEIVE_SMS”,
    "reason": "读取短信获取取件码"
  },
“name”: “ohos.permission.INTERNET”,
    "reason": "连接快递柜服务"
  },
“name”: “ohos.permission.DISTRIBUTED_DATASYNC”,
    "reason": "同步取件信息"
  },
“name”: “ohos.permission.ACCESS_DISTRIBUTED_DEVICE_MANAGER”,
    "reason": "发现和连接其他设备"
],
"abilities": [
“name”: “MainAbility”,
    "type": "page",
    "visible": true
  },
“name”: “LockerAbility”,
    "type": "service",
    "backgroundModes": ["dataTransfer"]
]
}
四、总结与扩展
本智能快递柜取件助手实现了以下核心功能:
智能识别:自动解析短信中的取件信息
便捷取件:一键操作快速开柜
多设备协同:家庭成员共享取件信息
状态同步:实时更新取件状态
扩展方向:
快递追踪:整合物流信息追踪
代取服务:授权他人代取快递
批量取件:支持多件快递同时取出
历史记录:保存取件记录便于查询
社区服务:与物业系统对接提供增值服务
通过HarmonyOS的分布式能力和短信识别功能,我们构建了一个便捷、高效的快递取件解决方案,大大简化了快递取件流程。




















