🌟 引言:打破应用壁垒的数据流通革命

在鸿蒙全场景生态中,应用不再是孤立的信息孤岛。跨应用数据共享作为分布式体验的核心支撑,让应用间能够安全、高效地协同工作。无论是通讯录应用向社交应用共享联系人,还是办公应用套件间的文档协作,DataShare和UDMF为开发者提供了一套完整的标准化解决方案,真正实现了"数据随人走、服务随身动"的智慧体验。

一、DataShare架构解析:生产者-消费者模式的现代化实现

DataShare采用经典的生产者-消费者架构,通过标准化接口和安全管控机制,实现应用间的数据安全流通。

1. 核心架构与数据流

// DataShare整体架构示意图
class DataShareArchitecture {
  // 数据提供方(生产者)
  dataProvider: DataShareExtensionAbility = {
    onCreate: (want: Want, callback: Function) => void,
    onQuery: (uri: string, predicates: DataSharePredicates, 
              columns: string[], callback: Function) => void,
    onInsert: (uri: string, value: ValuesBucket, callback: Function) => void,
    onUpdate: (uri: string, predicates: DataSharePredicates, 
               value: ValuesBucket, callback: Function) => void,
    onDelete: (uri: string, predicates: DataSharePredicates, callback: Function) => void
  }
  
  // 数据访问方(消费者)
  dataConsumer: DataShareHelper = {
    createDataShareHelper: (context: Context, uri: string) => Promise<DataShareHelper>,
    query: (predicates: DataSharePredicates, columns: string[]) => Promise<ResultSet>,
    insert: (value: ValuesBucket) => Promise<number>,
    update: (predicates: DataSharePredicates, value: ValuesBucket) => Promise<number>,
    delete: (predicates: DataSharePredicates) => Promise<number>
  }
  
  // 通信层:IPC安全通信
  communicationLayer: IPCBridge = {
    securityCheck: new SecurityValidator(),    // 安全校验
    dataSerialization: new DataSerializer(),   // 数据序列化
    permissionControl: new PermissionManager()  // 权限控制
  }
}

2. 两种共享模式对比

DataShare支持两种不同的数据共享模式,适应不同业务场景:

// 模式对比枚举
enum DataShareMode {
  // 拉起提供方模式:完整业务处理
  PROVIDER_ACTIVE = 'active',
  // 静默访问模式:高性能直接访问  
  SILENT_ACCESS = 'silent'
}

// 模式选择策略
class DataShareModeSelector {
  static selectMode(operationType: string, dataSensitivity: string): DataShareMode {
    if (dataSensitivity === 'high' || operationType === 'complex_business') {
      return DataShareMode.PROVIDER_ACTIVE
    } else {
      return DataShareMode.SILENT_ACCESS
    }
  }
}
二、DataShareExtensionAbility:数据提供方的完整实现

作为数据提供方,需要继承DataShareExtensionAbility并实现核心生命周期方法。

1. 基础数据提供方实现

import Extension from '@ohos.application.DataShareExtensionAbility'
import dataSharePredicates from '@ohos.data.dataSharePredicates'
import relationalStore from '@ohos.data.relationalStore'
import { BusinessError } from '@ohos.base'

@Entry
@Component
struct DataProviderExample {
  private rdbStore: relationalStore.RdbStore | null = null
  private readonly DB_CONFIG = {
    name: 'SharedData.db',
    securityLevel: relationalStore.SecurityLevel.S2
  }
  
  // 数据库初始化
  async aboutToAppear() {
    await this.initDatabase()
  }
  
  private async initDatabase(): Promise<void> {
    try {
      this.rdbStore = await relationalStore.getRdbStore(getContext(this), this.DB_CONFIG)
      
      // 创建共享数据表
      const createTableSql = `
        CREATE TABLE IF NOT EXISTS shared_contacts (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          name TEXT NOT NULL,
          phone TEXT,
          email TEXT,
          company TEXT,
          created_time INTEGER DEFAULT (strftime('%s', 'now')),
          updated_time INTEGER DEFAULT (strftime('%s', 'now'))
        )
      `
      await this.rdbStore.executeSql(createTableSql)
    } catch (error) {
      console.error('数据库初始化失败', error)
    }
  }
}

2. DataShareExtensionAbility完整实现

// 数据提供方Extension实现
export default class ContactDataShareExtension extends Extension {
  private rdbStore: relationalStore.RdbStore | null = null
  private readonly TABLE_NAME = 'shared_contacts'
  
  // Extension生命周期:创建时初始化
  onCreate(want: Want, callback: Function): void {
    console.info('ContactDataShareExtension onCreate')
    
    // 初始化数据库连接
    this.initRdbStore().then(() => {
      callback()
    }).catch((error: BusinessError) => {
      console.error('数据库初始化失败', error)
      callback(error)
    })
  }
  
  // 查询数据实现
  onQuery(uri: string, predicates: dataSharePredicates.DataSharePredicates, 
          columns: string[], callback: Function): void {
    console.info(`查询请求: ${uri}`)
    
    // 权限验证
    if (!this.validateQueryPermission()) {
      callback(new Error('权限验证失败'))
      return
    }
    
    this.rdbStore.query(this.TABLE_NAME, predicates, columns, (err: BusinessError, resultSet: relationalStore.ResultSet) => {
      if (err) {
        console.error(`查询失败: ${err.code} - ${err.message}`)
        callback(err)
      } else {
        console.info(`查询成功,返回${resultSet.rowCount}条数据`)
        callback(undefined, resultSet)
      }
    })
  }
  
  // 插入数据实现
  onInsert(uri: string, value: ValuesBucket, callback: Function): void {
    console.info('插入数据请求')
    
    // 数据验证
    if (!this.validateContactData(value)) {
      callback(new Error('数据验证失败'))
      return
    }
    
    // 添加时间戳
    value.created_time = Math.floor(Date.now() / 1000)
    value.updated_time = value.created_time
    
    this.rdbStore.insert(this.TABLE_NAME, value, (err: BusinessError, rowId: number) => {
      if (err) {
        console.error(`插入失败: ${err.code} - ${err.message}`)
        callback(err)
      } else {
        console.info(`数据插入成功,ID: ${rowId}`)
        callback(undefined, rowId)
        
        // 通知数据变化
        this.notifyChange(uri)
      }
    })
  }
  
  // 数据验证
  private validateContactData(value: ValuesBucket): boolean {
    return value && value.name && typeof value.name === 'string' && value.name.length > 0
  }
  
  // 权限验证
  private validateQueryPermission(): boolean {
    // 实际项目中应检查调用方权限
    return true
  }
}

3. 配置文件设置

// module.json5中的Extension配置
{
  "extensionAbilities": [
    {
      "name": "ContactDataShareExtension",
      "srcEntry": "./ets/contacts/ContactDataShareExtension.ets",
      "label": "$string:contacts_data_provider",
      "description": "$string:contacts_data_description",
      "type": "dataShare",
      "uri": "datashare://com.example.contacts.provider/contacts",
      "exported": true,
      "permissions": [
        {
          "name": "ohos.permission.READ_CONTACTS",
          "grantMode": "system_grant"
        }
      ],
      "metadata": [
        {
          "name": "ohos.extension.dataShare",
          "resource": "$profile:data_share_config"
        }
      ]
    }
  ]
}
三、DataShareHelper:数据消费方的安全访问

数据消费方通过DataShareHelper实例访问提供方数据,无需关心底层存储细节。

1. DataShareHelper初始化与基础操作

@Entry
@Component
struct DataConsumerExample {
  private dataShareHelper: dataShare.DataShareHelper | null = null
  private readonly CONTACTS_URI = 'datashare://com.example.contacts.provider/contacts'
  
  async aboutToAppear() {
    await this.initDataShareHelper()
  }
  
  // 初始化DataShareHelper
  async initDataShareHelper(): Promise<void> {
    try {
      this.dataShareHelper = await dataShare.createDataShareHelper(
        getContext(this), 
        this.CONTACTS_URI,
        { isProxy: true }  // 启用代理模式
      )
      console.info('DataShareHelper初始化成功')
      
      // 注册数据变化监听
      this.setupDataChangeListener()
    } catch (error) {
      console.error('DataShareHelper初始化失败', error)
    }
  }
  
  // 查询联系人数据
  async queryContacts(filter?: string): Promise<Contact[]> {
    if (!this.dataShareHelper) {
      throw new Error('DataShareHelper未初始化')
    }
    
    const predicates = new dataSharePredicates.DataSharePredicates()
    if (filter) {
      predicates.contains('name', filter)
    }
    predicates.orderByAsc('name')
    
    const columns = ['id', 'name', 'phone', 'email', 'company']
    
    try {
      const resultSet = await this.dataShareHelper.query(this.CONTACTS_URI, predicates, columns)
      return this.processResultSet(resultSet)
    } catch (error) {
      console.error('查询联系人失败', error)
      return []
    }
  }
  
  // 添加新联系人
  async addContact(contact: Contact): Promise<boolean> {
    if (!this.dataShareHelper) return false
    
    const values: ValuesBucket = {
      name: contact.name,
      phone: contact.phone,
      email: contact.email,
      company: contact.company
    }
    
    try {
      const rowId = await this.dataShareHelper.insert(this.CONTACTS_URI, values)
      console.info(`联系人添加成功,ID: ${rowId}`)
      return true
    } catch (error) {
      console.error('添加联系人失败', error)
      return false
    }
  }
}

2. 高级特性:批量操作与数据同步

@Component
struct AdvancedDataOperations {
  private dataShareHelper: dataShare.DataShareHelper | null = null
  
  // 批量插入操作
  async batchImportContacts(contacts: Contact[]): Promise<BatchResult> {
    const results: BatchResult = {
      success: 0,
      failed: 0,
      errors: []
    }
    
    for (let i = 0; i < contacts.length; i++) {
      try {
        await this.addContact(contacts[i])
        results.success++
      } catch (error) {
        results.failed++
        results.errors.push({
          index: i,
          error: error.message,
          contact: contacts[i]
        })
      }
    }
    
    return results
  }
  
  // 数据变化监听
  setupDataChangeListener(): void {
    this.dataShareHelper.on('dataChange', this.CONTACTS_URI, (changeInfo: DataChangeInfo) => {
      console.info('检测到数据变化,更新UI')
      this.refreshContactList()
    })
  }
  
  // 安全的数据访问控制
  async secureQuery(sensitiveField: string): Promise<any> {
    // 检查调用方权限
    const hasPermission = await this.validateAccessPermission(sensitiveField)
    if (!hasPermission) {
      throw new Error('权限不足,无法访问敏感数据')
    }
    
    // 记录审计日志
    await this.logDataAccess(sensitiveField)
    
    return await this.queryContacts()
  }
}
四、统一数据管理框架UDMF:标准化数据交换

UDMF为跨应用、跨设备数据交互定义了统一标准,解决了数据格式不一致的痛点。

1. UDMF核心概念与数据标准化

// UDMF标准化数据类型定义
enum UDMFDataType {
  PLAIN_TEXT = 'text/plain',
  RICH_TEXT = 'text/richtext',
  HTML = 'text/html',
  JSON = 'application/json',
  IMAGE = 'image/*',
  VIDEO = 'video/*',
  AUDIO = 'audio/*',
  CONTACT = 'application/vnd.ohos.contact',
  CALENDAR = 'application/vnd.ohos.calendar'
}

// 统一数据记录结构
interface UnifiedRecord {
  type: UDMFDataType
  details: RecordDetail
  properties?: Record<string, any>
  authorization?: AccessControl
}

// 跨应用数据分享
class UDMFDataShare {
  // 分享数据到UDMF
  async shareToUDMF(data: UnifiedRecord, options: ShareOptions): Promise<string> {
    const udmfClient = await this.getUDMFClient()
    const recordId = await udmfClient.insert(data, options)
    
    // 设置访问权限
    await this.setAccessPolicy(recordId, options.accessPolicy)
    
    return recordId
  }
  
  // 从UDMF读取数据
  async readFromUDMF(recordId: string, requester: string): Promise<UnifiedRecord> {
    // 验证访问权限
    await this.validateAccess(recordId, requester)
    
    return await this.udmfClient.query(recordId)
  }
}

2. 实战案例:跨应用文件分享

@Entry
@Component
struct FileSharingExample {
  private readonly UDMF_IMAGE_TYPE = 'image/*'
  
  // 分享图片到其他应用
  async shareImageToEditor(imageUri: string): Promise<void> {
    const imageRecord: UnifiedRecord = {
      type: this.UDMF_IMAGE_TYPE,
      details: {
        uri: imageUri,
        width: 1920,
        height: 1080,
        size: this.getFileSize(imageUri),
        format: 'image/jpeg'
      },
      properties: {
        creationTime: Date.now(),
        author: this.getCurrentUser(),
        sourceApp: this.getAppBundleName()
      }
    }
    
    const shareOptions: ShareOptions = {
      allowedApps: ['com.example.photoeditor'], // 指定可访问应用
      validityPeriod: 24 * 60 * 60 * 1000, // 24小时有效
      accessPolicy: {
        read: true,
        write: false,
        share: false
      }
    }
    
    try {
      const recordId = await this.udmf.shareToUDMF(imageRecord, shareOptions)
      await this.launchEditorApp(recordId)
    } catch (error) {
      console.error('图片分享失败', error)
    }
  }
  
  // 处理接收到的共享数据
  async handleSharedData(recordId: string): Promise<void> {
    const sharedRecord = await this.udmf.readFromUDMF(recordId, this.getAppBundleName())
    
    switch (sharedRecord.type) {
      case UDMFDataType.PLAIN_TEXT:
        await this.processTextData(sharedRecord)
        break
      case UDMFDataType.IMAGE:
        await this.processImageData(sharedRecord)
        break
      case UDMFDataType.CONTACT:
        await this.processContactData(sharedRecord)
        break
      default:
        console.warn('不支持的数据类型:', sharedRecord.type)
    }
    
    // 清理临时数据
    await this.udmf.delete(recordId)
  }
}
五、安全与权限管理:数据共享的守护者

安全是跨应用数据共享的生命线,鸿蒙提供了多层次的安全保护机制。

1. 权限声明与验证

// 权限配置管理
class PermissionManager {
  private readonly REQUIRED_PERMISSIONS = {
    READ_CONTACTS: 'ohos.permission.READ_CONTACTS',
    WRITE_CONTACTS: 'ohos.permission.WRITE_CONTACTS',
    ACCESS_UDMF: 'ohos.permission.ACCESS_UDMF_DATA'
  }
  
  // 检查并申请权限
  async checkAndRequestPermissions(permissions: string[]): Promise<boolean> {
    for (const permission of permissions) {
      const grantStatus = await abilityAccessCtrl.verifyAccessToken(
        getContext(this).tokenId, 
        permission
      )
      
      if (grantStatus !== 0) { // 0表示已授权
        const grantResult = await abilityAccessCtrl.requestPermissionsFromUser(
          getContext(this), 
          [permission]
        )
        
        if (grantResult.authResults[0] !== 0) {
          return false
        }
      }
    }
    return true
  }
  
  // 数据提供方权限验证
  validateCallerPermission(): boolean {
    const callerUid = this.getCallingUid()
    const callerPid = this.getCallingPid()
    
    // 验证调用方身份和权限
    return this.isTrustedCaller(callerUid, callerPid)
  }
}

2. 数据安全策略与加密

// 数据安全处理
class DataSecurityHandler {
  // 敏感数据加密
  async encryptSensitiveData(data: any): Promise<string> {
    const crypto = await crypto.createCrypto('AES256_GCM')
    const plainText = JSON.stringify(data)
    const cipherText = await crypto.encrypt({
      data: new Uint8Array(plainText.split('').map(c => c.charCodeAt(0))),
      key: this.getEncryptionKey()
    })
    return btoa(String.fromCharCode(...cipherText))
  }
  
  // 数据传输安全
  async secureDataTransfer(data: any, targetApp: string): Promise<TransferResult> {
    // 验证目标应用签名
    await this.verifyTargetApp(targetApp)
    
    // 加密传输数据
    const encryptedData = await this.encryptSensitiveData(data)
    
    // 安全通道传输
    return await this.transferViaSecureChannel(encryptedData, targetApp)
  }
}
六、性能优化与最佳实践

大规模数据共享场景下的性能优化策略。

1. 性能优化技巧

@Component
struct PerformanceOptimization {
  private dataShareHelper: dataShare.DataShareHelper | null = null
  
  // 批量操作优化
  async optimizedBatchOperations(operations: DataOperation[]): Promise<void> {
    // 使用事务包装批量操作
    await this.dataShareHelper.beginTransaction()
    
    try {
      for (const op of operations) {
        switch (op.type) {
          case 'insert':
            await this.dataShareHelper.insert(op.uri, op.data)
            break
          case 'update':
            await this.dataShareHelper.update(op.uri, op.predicates, op.data)
            break
          case 'delete':
            await this.dataShareHelper.delete(op.uri, op.predicates)
            break
        }
      }
      await this.dataShareHelper.commit()
    } catch (error) {
      await this.dataShareHelper.rollback()
      throw error
    }
  }
  
  // 查询优化:分页和字段选择
  async optimizedQuery(predicates: DataSharePredicates, page: number, pageSize: number): Promise<PagedResult> {
    const offset = (page - 1) * pageSize
    
    predicates.limit(pageSize)
      .offset(offset)
      .orderBy('created_time', 'DESC')
    
    // 只查询需要的字段
    const columns = ['id', 'name', 'phone'] // 避免SELECT *
    
    const resultSet = await this.dataShareHelper.query(this.CONTACTS_URI, predicates, columns)
    return this.processPagedResult(resultSet, page, pageSize)
  }
  
  // 缓存策略
  private queryCache = new Map<string, { data: any, timestamp: number }>()
  private readonly CACHE_TTL = 5 * 60 * 1000 // 5分钟缓存
  
  async queryWithCache(predicates: DataSharePredicates): Promise<any> {
    const cacheKey = this.generateCacheKey(predicates)
    const cached = this.queryCache.get(cacheKey)
    
    if (cached && (Date.now() - cached.timestamp) < this.CACHE_TTL) {
      return cached.data
    }
    
    const freshData = await this.dataShareHelper.query(this.CONTACTS_URI, predicates, ['*'])
    this.queryCache.set(cacheKey, { data: freshData, timestamp: Date.now() })
    
    return freshData
  }
}
七、实战案例:企业通讯录共享系统

以下是一个完整的企业通讯录共享系统实现。

1. 系统架构设计

// 企业通讯录数据模型
interface EnterpriseContact {
  id: number
  employeeId: string
  name: string
  department: string
  title: string
  workPhone: string
  workEmail: string
  mobile: string
  avatar?: string
  status: 'active' | 'inactive'
  securityLevel: 1 | 2 | 3 // 数据安全等级
}

// 数据提供方实现
export default class EnterpriseContactProvider extends Extension {
  private readonly TABLE_NAME = 'enterprise_contacts'
  
  onQuery(uri: string, predicates: DataSharePredicates, columns: string[], callback: Function): void {
    // 企业级权限验证
    if (!this.validateEnterprisePermission()) {
      callback(new Error('企业权限验证失败'))
      return
    }
    
    // 根据用户角色过滤数据
    const filteredPredicates = this.applySecurityFilter(predicates)
    
    this.rdbStore.query(this.TABLE_NAME, filteredPredicates, columns, (err, resultSet) => {
      if (err) {
        callback(err)
      } else {
        // 记录审计日志
        this.logAccessAudit()
        callback(undefined, resultSet)
      }
    })
  }
  
  // 安全数据过滤
  private applySecurityFilter(predicates: DataSharePredicates): DataSharePredicates {
    const userSecurityLevel = this.getUserSecurityLevel()
    
    // 只能查看同级或更低安全级别的数据
    predicates.lessThanOrEqualTo('securityLevel', userSecurityLevel)
    
    return predicates
  }
}

2. 多应用协同场景

@Entry
@Component
struct EnterpriseContactApp {
  private contactProvider: EnterpriseContactProvider | null = null
  
  // 通讯录与邮件应用集成
  async shareContactToEmail(contact: EnterpriseContact, emailApp: string): Promise<void> {
    const vCard = this.generateVCard(contact)
    
    const shareRecord: UnifiedRecord = {
      type: UDMFDataType.PLAIN_TEXT,
      details: {
        content: vCard,
        mimeType: 'text/vcard'
      },
      properties: {
        subject: `联系人: ${contact.name}`,
        category: 'contact'
      }
    }
    
    await this.udmf.shareToUDMF(shareRecord, {
      allowedApps: [emailApp],
      accessPolicy: { read: true, write: false, share: false }
    })
    
    await this.launchEmailAppWithContact()
  }
  
  // 组织架构同步
  async syncDepartmentStructure(departmentId: string): Promise<void> {
    const predicates = new dataSharePredicates.DataSharePredicates()
    predicates.equalTo('department', departmentId)
      .equalTo('status', 'active')
    
    const departmentContacts = await this.contactProvider.queryContacts(predicates)
    
    // 同步到组织架构应用
    await this.syncToOrgChartApp(departmentId, departmentContacts)
  }
}
💎 总结

跨应用数据共享是鸿蒙分布式生态的核心能力,通过DataShare和UDMF的有机结合,开发者可以构建出真正实现应用协同的智能体验。关键在于理解安全权限控制、掌握性能优化技巧、遵循标准化数据规范,从而在保障用户隐私的前提下,实现数据的自由流动和价值最大化。

进一步学习建议:在实际项目中,建议从简单的数据分享场景开始,逐步扩展到复杂的跨应用协同。官方文档中的DataShare开发指南提供了完整的API参考。

需要参加鸿蒙认证的请点击 鸿蒙认证链接

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐