0
点赞
收藏
分享

微信扫一扫

ideaSSM图书借阅管理系统VS开发mysql数据库web结构java编程计算机网页源码maven项目

场景介绍

跨应用访问数据时,可以通过DataShareExtensionAbility拉起数据提供方的应用以实现对数据的访问。

此种方式支持跨应用拉起数据提供方的DataShareExtension,数据提供方的开发者可以在回调中实现灵活的业务逻辑。用于跨应用复杂业务场景。

运作机制

数据共享可分为数据的提供方和访问方两部分。

  • 数据提供方: DataShareExtensionAbility ,可以选择性实现数据的增、删、改、查,以及文件打开等功能,并对外共享这些数据。

  • 数据访问方:由 createDataShareHelper() 方法所创建的工具类,利用工具类,便可以访问提供方提供的这些数据。

图1 数据共享运作机制

  • DataShareExtensionAbility模块为数据提供方,实现跨应用数据共享的相关业务。

  • DataShareHelper模块为数据访问方,提供各种访问数据的接口,包括增删改查等。

  • 数据访问方与提供方通过IPC进行通信,数据提供方可以通过数据库实现,也可以通过其他数据存储方式实现。

  • ResultSet模块通过共享内存实现,用于存储查询数据得到的结果集,并提供了遍历结果集的方法。

实现说明

数据提供方应用的开发(仅限系统应用)

DataShareExtensionAbility 提供以下API,根据需要重写对应回调方法。

  • onCreate:DataShare客户端连接DataShareExtensionAbility服务端时,服务端需要在此回调中实现初始化业务逻辑,该方法可以选择性重写。
  • insert:业务函数,客户端请求插入数据时回调此接口,服务端需要在此回调中实现插入数据功能,该方法可以选择性重写。
  • update:业务函数,客户端请求更新数据时回调此接口,服务端需要在此回调中实现更新数据功能,该方法可以选择性重写。
  • batchUpdate:业务函数,客户端请求批量更新数据时回调此接口,服务端需要在此回调中实现批量更新数据功能,该方法可以选择性重写。
  • delete:业务函数,客户端请求删除数据时回调此接口,服务端需要在此回调中实现删除数据功能,该方法可以选择性重写。
  • query:业务函数,客户端请求查询数据时回调此接口,服务端需要在此回调中实现查询数据功能,该方法可以选择性重写。
  • batchInsert:业务函数,客户端请求批量插入数据时回调此接口,服务端需要在此回调中实现批量插入数据的功能,该方法可以选择性重写。
  • normalizeUri:业务函数,客户端给定的URI转换为服务端使用的URI时回调此接口,该方法可以选择性重写。
  • denormalizeUri:业务函数,服务端使用的URI转换为客户端传入的初始URI时服务端回调此接口,该方法可以选择性重写。

开发者在实现一个数据共享服务时,需要在DevEco Studio工程中手动新建一个DataShareExtensionAbility,具体步骤如下。

  1. 在工程Module对应的ets目录下,右键选择“New > Directory”,新建一个目录并命名为DataShareExtAbility。

  2. 在DataShareAbility目录,右键选择“New > ArkTS File”,新建一个文件并命名为DataShareExtAbility.ets。

  3. 在DataShareExtAbility.ets文件中,导入
    @ohos.application.DataShareExtensionAbility模块,开发者可根据应用需求选择性重写其业务实现。例如数据提供方只提供插入、删除和查询服务,则可只重写这些接口,并导入对应的基础依赖模块;如果需要增加权限校验,可以在重写的回调方法中使用IPC提供的 getCallingPid 、 getCallingUid 、 getCallingTokenId 方法获取访问者信息来进行权限校验。

    import Extension from '@ohos.application.DataShareExtensionAbility';
    import { UpdateOperation } from '@ohos.application.DataShareExtensionAbility';
    import dataSharePredicates from '@ohos.data.dataSharePredicates';
    import relationalStore from '@ohos.data.relationalStore';
    import Want from '@ohos.app.ability.Want';
    import { BusinessError } from '@ohos.base'
    
  4. 数据提供方的业务实现由开发者自定义。例如可以通过数据库、读写文件或访问网络等各方式实现数据提供方的数据存储。

    const DB_NAME = 'DB00.db';
    const TBL_NAME = 'TBL00';
    const DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS "
      + TBL_NAME
      + ' (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, isStudent BOOLEAN, Binary BINARY)';
    
    let rdbStore: relationalStore.RdbStore;
    let result: string;
    
    export default class DataShareExtAbility extends Extension {
      // 重写onCreate接口
      onCreate(want: Want, callback: Function) {
        result = this.context.cacheDir + '/datashare.txt';
        // 业务实现使用RDB
        relationalStore.getRdbStore(this.context, {
          name: DB_NAME,
          securityLevel: relationalStore.SecurityLevel.S1
        }, (err, data) => {
          rdbStore = data;
          rdbStore.executeSql(DDL_TBL_CREATE, [], (err) => {
            console.info(`DataShareExtAbility onCreate, executeSql done err:${err}`);
          });
          if (callback) {
            callback();
          }
        });
      }
    
      // 重写query接口
      query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array<string>, callback: Function) {
        if (predicates === null || predicates === undefined) {
          console.info('invalid predicates');
        }
        try {
          rdbStore.query(TBL_NAME, predicates, columns, (err, resultSet) => {
            if (resultSet !== undefined) {
              console.info(`resultSet.rowCount:${resultSet.rowCount}`);
            }
            if (callback !== undefined) {
              callback(err, resultSet);
            }
          });
        } catch (err) {
          let code = (err as BusinessError).code;
          let message = (err as BusinessError).message
          console.error(`Failed to query. Code:${code},message:${message}`);
        }
      }
      // 重写batchUpdate接口
      batchUpdate(operations, callback) {
         let recordOps : Record<string, Array<UpdateOperation>> = operations;
         let results : Record<string, Array<number>> = {};
            for (const [key, values] of Object.entries(recordOps)) {
                let result : number[] = [];
                for (const value of values) {
                    await rdbStore.update(TBL_NAME, value.values, value.predicates).then(async (rows) => {
                        console.info('Update row count is ' + rows);
                        result.push(rows);
                    }).catch((err) => {
                        console.info("Update failed, err is " + JSON.stringify(err));
                        result.push(-1);
                    })
                }
                results[key] = result;
            }
            callback(null, results);
        }
      // 可根据应用需求,选择性重写各个接口
    };
    
  5. 在module.json5中定义DataShareExtensionAbility。

    表1 module.json5对应属性字段

    属性名称备注说明必填
    nameAbility名称,对应Ability派生的ExtensionAbility类名。
    typeAbility类型,DataShare对应的Ability类型为“dataShare”,表示基于datashare模板开发的。
    uri通信使用的URI,是客户端链接服务端的唯一标识。
    exported对其他应用是否可见,设置为true时,才能与其他应用进行通信传输数据。
    readPermission访问数据时需要的权限,不配置默认不进行读权限校验。
    writePermission修改数据时需要的权限,不配置默认不进行写权限校验。
    metadata增加静默访问所需的额外配置项,包含name和resource字段。
    name类型固定为"ohos.extension.dataShare",是配置的唯一标识。
    resource类型固定为"$profile:data_share_config",表示配置文件的名称为data_share_config.json。
    若Ability启动模式为"singleton",则metadata必填,Ability启动模式可见abilities对象的内部结构-launchType;其他情况下无需填写。

    module.json5配置样例:

    "extensionAbilities": [
      {
        "srcEntry": "./ets/DataShareExtAbility/DataShareExtAbility.ets",
        "name": "DataShareExtAbility",
        "icon": "$media:icon",
        "description": "$string:description_datashareextability",
        "type": "dataShare",
        "uri": "datashare://com.samples.datasharetest.DataShare",
        "exported": true,
        "metadata": [{"name": "ohos.extension.dataShare", "resource": "$profile:data_share_config"}]
      }
    ]
    

    表2 data_share_config.json对应属性字段

    属性名称备注说明必填
    tableConfig配置标签。
    uri指定配置生效的范围,uri支持以下三种格式,优先级为**表配置>库配置>\ **,如果同时配置,高优先级会覆盖低优先级 。
    1. “*” : 所有的数据库和表。
    2. “datashare:///{bundleName}/{moduleName}/{storeName}” : 指定数据库。
    3. “datashare:///{bundleName}/{moduleName}/{storeName}/{tableName}” : 指定表。
    crossUserMode标识数据是否为多用户共享,配置为1则多用户数据共享,配置为2则多用户数据隔离。
    isSilentProxyEnable标识该ExtensionAbility是否关闭静默访问。
    false:代表关闭静默访问。
    true:代表打开静默访问。
    不填写默认为true,即默认开启静默访问。
    如果该应用下存在多个ExtensionAbility,其中一个配置了该属性为false,代表应用关闭静默访问。
    如果数据提供方调用过enableSilentProxy和disableSilentProxy接口,则按照接口的设置结果来开启或关闭静默访问。否则会读取该配置来开启或关闭静默访问。

    data_share_config.json配置样例

    {
        "tableConfig":[
            {
                "uri":"*",
                "crossUserMode":1
            },
            {
                "uri":"datashare:///com.acts.datasharetest/entry/DB00",
                "crossUserMode":1
            },
            {
                "uri":"datashare:///com.acts.datasharetest/entry/DB00/TBL00",
                "crossUserMode":2
            }
        ],
        "isSilentProxyEnable":true
    }
    

数据访问方应用的开发

  1. 导入基础依赖包。

    import UIAbility from '@ohos.app.ability.UIAbility';
    import dataShare from '@ohos.data.dataShare';
    import dataSharePredicates from '@ohos.data.dataSharePredicates';
    import { ValuesBucket } from '@ohos.data.ValuesBucket'
    import window from '@ohos.window';
    
  2. 定义与数据提供方通信的URI字符串。

    // 作为参数传递的URI,与module.json5中定义的URI的区别是多了一个"/",是因为作为参数传递的URI中,在第二个与第三个"/"中间,存在一个DeviceID的参数
    let dseUri = ('datashare:///com.samples.datasharetest.DataShare');
    
  3. 创建工具接口类对象。

    let dsHelper: dataShare.DataShareHelper | undefined = undefined;
    let abilityContext: Context;
    
    export default class EntryAbility extends UIAbility {
      onWindowStageCreate(windowStage: window.WindowStage) {
        abilityContext = this.context;
        dataShare.createDataShareHelper(abilityContext, dseUri, (err, data) => {
          dsHelper = data;
        });
      }
    }
    
  4. 获取到接口类对象后,便可利用其提供的接口访问提供方提供的服务,如进行数据的增删改查等。

    // 构建一条数据
    let key1 = 'name';
    let key2 = 'age';
    let key3 = 'isStudent';
    let key4 = 'Binary';
    let valueName1 = 'ZhangSan';
    let valueName2 = 'LiSi';
    let valueAge1 = 21;
    let valueAge2 = 18;
    let valueIsStudent1 = false;
    let valueIsStudent2 = true;
    let valueBinary = new Uint8Array([1, 2, 3]);
    let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary };
    let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary };
    let predicates = new dataSharePredicates.DataSharePredicates();
    let valArray = ['*'];
    
    let record: Record<string, Array<dataShare.UpdateOperation>> = {};
    let operations1: Array<dataShare.UpdateOperation> = [];
    let operations2: Array<dataShare.UpdateOperation> = [];
    let operation1: dataShare.UpdateOperation = {
      values: valuesBucket,
      predicates: predicates
    }
    operations1.push(operation1);
    let operation2: dataShare.UpdateOperation = {
      values: updateBucket,
      predicates: predicates
    }
    operations2.push(operation2);
    record["uri1"] = operations1;
    record["uri2"] = operations2;
    
    if (dsHelper != undefined) {
      // 插入一条数据
      (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => {
        console.info(`dsHelper insert result:${data}`);
      });
      // 更新数据
      (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => {
        console.info(`dsHelper update result:${data}`);
      });
      // 查询数据
      (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => {
        console.info(`dsHelper query result:${data}`);
      });
      // 删除指定的数据
      (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => {
        console.info(`dsHelper delete result:${data}`);
      });
      // 批量更新数据
      (dsHelper as dataShare.DataShareHelper).batchUpdate(record).then((data: Record<string, Array<number>>) => {
        // 遍历data获取每条数据的更新结果, value为更新成功的数据记录数,若小于0,说明该次更新失败
        for (const [key, values] of Object.entries(data)) {
            console.info(`Update uri:${key}`);
            for (const value of values) {
                console.info(`Update result:${value}`);
            }
        }
      })// 关闭DataShareHelper实例
      (dsHelper as dataShare.DataShareHelper).close();
    }
    

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

举报

相关推荐

0 条评论