HarmonyOS NEXT鸿蒙开发:同应用跨设备数据同步-键值型数据库封装类

申请权限

HarmonyOS NEXT鸿蒙开发:同应用跨设备数据同步-申请权限

封装类

在 ets 目录下创建包 utils,在该包下创建 KVStoreUtils.ets 文件,内容如下:

import { distributedKVStore } from '@kit.ArkData';
import common from '@ohos.app.ability.common';
import { BusinessError } from '@kit.BasicServicesKit';
import { bundleManager } from '@kit.AbilityKit';

const TAG = 'KVStoreUtils------'

export default  class KVStoreUtils {

  private kvManager: distributedKVStore.KVManager | undefined = undefined;
  // 全局KV存储实例

  private kvStore: distributedKVStore.SingleKVStore | undefined = undefined;
  private context: Context | undefined
  private storeId: string = ""
  /**
   * bundleName 与 appid是一个意思,不同方法,不同叫法
   */
  private bundleName:string = ""

  public constructor(storeId: string) {
    this.storeId = storeId
  }
  /**
   * 初始化分布式KV存储
   * @param context 上下文
   * @param storeId 打开KV存储(storeId需唯一,建议按业务划分)
   */
  public async init(context: Context) {

    this.context = context

    try {
      // 1. 创建KV管理器配置
      let bi:bundleManager.BundleInfo
      try {
        bi = await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT)
        this.bundleName = bi.name
      }catch (err){
        console.error(TAG,`获取 BundleInfo 报错!code:${err.code},message:${err.message}`)
      }
      // try {
      //   bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT).then((data) => {
      //     console.info(TAG, 'testTag', 'getBundleInfoForSelf successfully. Data: %{public}s', JSON.stringify(data));
      //   }).catch((err: BusinessError) => {
      //     console.info(TAG,  'getBundleInfoForSelf() 失败! Cause: %{public}s', err.message);
      //   });
      // } catch (err) {
      //   let message = (err as BusinessError).message;
      //   console.info(TAG, 'getBundleInfoForSelf() 失败!  %{public}s', message);
      // }
      // this.bundleName = bi!.name
      const config: distributedKVStore.KVManagerConfig = {
        bundleName: this.bundleName,
        context: this.context!
      }

      // 2. 创建KV管理器
      this.kvManager = distributedKVStore.createKVManager(config);
      console.info(TAG, '成功创建 KVManager.');

      await this.initKVStore(this.storeId)

      // this.on()
    } catch (err) {
      console.error(TAG, `KV存储初始化失败:${JSON.stringify(err)}`);
    }
  }
  /**
   * 3. 配置KV存储参数(关键:开启自动同步)
   * @param storeId 打开KV存储(storeId需唯一,建议按业务划分)
   */
  private async initKVStore(storeId:string){
    const options: distributedKVStore.Options = {
      createIfMissing: true, // 存储不存在则创建
      encrypt: false, // 敏感数据建议开启加密(需配置加密密钥)
      backup: true, // 支持云备份(可选)
      autoSync: true, // 开启跨设备自动同步(核心)
      kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION, // 单版本(同步场景必选)
      securityLevel: distributedKVStore.SecurityLevel.S1 // 安全级别(S1为普通级)
    };

    // 4. 打开KV存储(storeId需唯一,建议按业务划分)
    this.kvStore = await this.kvManager!.getKVStore(storeId, options);
    console.log(TAG, '分布式KV存储初始化成功');
  }
  /**
   * 订阅分布式数据变化
   */
  private on() {
    try {
      //订阅
      this.kvStore!.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {
        console.info(`dataChange callback call data: ${data}`);
      });
    } catch (error) {
      console.error(TAG, `订阅报错! code:${error.code},message:${error.message}`);
    }
  }
  /**
   * 移除订阅分布式数据变化
   */
  public off(){

    try {
      //移除订阅数据变化
      this.kvStore!.off('dataChange');
    } catch (error) {
      console.error(TAG, `移除订阅报错! err=${JSON.stringify(error)}`, 'KvStoreViewModel');
    }
  }

  /**
   * 将数据写入分布式数据库
   * @param key
   * @param value
   * @returns 成功返回true,失败返回false
   */
  public async put(key: string, value: string): Promise<boolean> {
    if (this.kvStore) {
      try {
        await this.kvStore.put(key, value)
        return true;
      } catch (error) {
        console.error(TAG, `添加 key=${key} 报错, error=${JSON.stringify(error)}`);
      }
    }
    return false;
  }

  /**
   * 根据key获取value
   * @param key
   * @returns
   */
  public async get(key: string): Promise<string | number | boolean | Uint8Array | undefined> {
    if (!this.kvStore) {
      console.info(TAG,'this.kvStore 为 undefined')
      return undefined;
    }
    try {
      return await this.kvStore.get(key)
    } catch (error) {
      console.error(TAG,`获取 key=${key} 失败, error=${JSON.stringify(error)}`)
    }
    return undefined
  }

  /**
   * 根据key删除数据
   * @param key
   * @returns
   */
  public async delete(key: string): Promise<void> {
    if (!this.kvStore) {
      console.info(TAG,'this.kvStore 为 undefined')
      return;
    }

    try {
      await this.kvStore.delete(key)
    } catch (error) {
      console.error(TAG,`删除 key=${key} 失败, error=${JSON.stringify(error)}`)
    }
  }

  /**
   * 手动模式时,用于同步数据到其他设备
   */
  // sync(deviceIds: string[],delayMs: number = 60*1000){
  //   if (!this.kvStore) {
  //     console.info(TAG,'this.kvStore 为 undefined')
  //     return;
  //   }
  //   try {
  //     // 1000表示最大延迟时间为1000ms
  //     this.kvStore.sync(deviceIds, distributedKVStore.SyncMode.PUSH_ONLY, delayMs);
  //   } catch (error) {
  //     console.error(TAG,`同步数据报错:${error.code},message:${error.message}`);
  //   }
  //
  // }

  /**
   * 关闭数据库
   */
  public async close(){
    if (!this.kvManager) {
      console.info(TAG,'this.kvManager 为 undefined')
      return;
    }
    try {
      await this.kvManager.closeKVStore(this.bundleName, this.storeId)
    }catch(err) {
      console.error(TAG,`关闭 KVStore 失败!code is ${err.code},message is ${err.message}`);
    }
  }
}

使用

创建保存登录信息的 数据库:在 utils 目录下创建文件 LoginKVStoreUtils.ets,内容如下:

import KVStoreUtils from "../utils/KVStoreUtils"

const instance = new KVStoreUtils("login_info")

export default instance

初始化数据库

在首页 Index.ets 的 aboutToAppear() 方法中加上下面代码:

import LoginKVStoreUtils from "../utils/LoginKVStoreUtils"
await LoginKVStoreUtils.init(this.getUIContext().getHostContext()!)

增加2个按钮,一个添加数据,一个取出数据:

Button("保存")
  .onClick(async ()=>{
    this.getUIContext().getPromptAction().showToast({
      message: "测试toast", // 提示文本
      duration: 2000, // 显示时长(毫秒),默认1500ms,范围[1500, 3000]
      bottom: 100 // 距离屏幕底部的距离(像素)
    })
    await LoginKVStoreUtils.put("name","李雷")
  })

Button("读取")
  .onClick(async ()=>{
    const name = await LoginKVStoreUtils.get("name")
    console.log(TAG,"name:",name)
  })

原文出处:/show_1GW2R2EfkYs4.html