- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
使用Data模板的Ability(以下简称“Data”)有助于应用管理其自身和其他应用存储数据的访问,并提供与其他应用共享数据的方法。Data既可用于同设备不同应用的数据共享,也支持跨设备不同应用的数据共享。
数据的存放形式多样,可以是数据库,也可以是磁盘上的文件。Data对外提供对数据的增、删、改、查,以及打开文件等接口,这些接口的具体实现由开发者提供。
Data的提供方和使用方都通过URI(Uniform Resource Identifier)来标识一个具体的数据,例如数据库中的某个表或磁盘上的某个文件。HarmonyOS的URI仍基于URI通用标准,格式如下:
URI示例:
使用Data模板的Ability形式仍然是Ability,因此,开发者需要为应用添加一个或多个Ability的子类,来提供程序与其他应用之间的接口。Data为结构化数据和文件提供了不同API接口供用户使用,因此,开发者需要首先确定好使用何种类型的数据。本章节主要讲述了创建Data的基本步骤和需要使用的接口。
Data提供方可以自定义数据的增、删、改、查,以及文件打开等功能,并对外提供这些接口。
确定数据的存储方式,Data支持以下两种数据形式:
UserDataAbility用于接收其他应用发送的请求,提供外部程序访问的入口,从而实现应用间的数据访问。
实现UserDataAbility,需要在“Project”窗口当前工程的主目录(“entry > src > main > java > com.xxx.xxx”)选择“File > New > Ability > Empty Data Ability”,设置“Data Name”后完成UserDataAbility的创建。
Data提供了文件存储和数据库存储两组接口供用户使用。
文件存储
开发者需要在Data中重写FileDescriptor openFile(Uri uri, String mode)方法来操作文件:uri为客户端传入的请求目标路径;mode为开发者对文件的操作选项,可选方式包含“r”(读), “w”(写), “rw”(读写)等。
ohos.rpc.MessageParcel类提供了一个静态方法,用于获取MessageParcel实例。开发者可通过获取到的MessageParcel实例,使用dupFileDescriptor()函数复制待操作文件流的文件描述符,并将其返回,供远端应用访问文件。
示例:根据传入的uri打开对应的文件
private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0xD00201, "Data_Log");
@Override
public FileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
// 创建messageParcel
MessageParcel messageParcel = MessageParcel.obtain();
File file = new File(uri.getDecodedPathList().get(0)); //get(0)是获取URI完整字段中查询参数字段。
if (mode == null || !"rw".equals(mode)) {
file.setReadOnly();
}
FileInputStream fileIs = new FileInputStream(file);
FileDescriptor fd = null;
try {
fd = fileIs.getFD();
} catch (IOException e) {
HiLog.info(LABEL_LOG, "failed to getFD");
}
// 绑定文件描述符
return messageParcel.dupFileDescriptor(fd);
}
数据库存储
1、初始化数据库连接。
系统会在应用启动时调用onStart()方法创建Data实例。在此方法中,开发者应该创建数据库连接,并获取连接对象,以便后续和数据库进行操作。为了避免影响应用启动速度,开发者应当尽可能将非必要的耗时任务推迟到使用时执行,而不是在此方法中执行所有初始化。
示例:初始化的时候连接数据库
private static final String DATABASE_NAME = "UserDataAbility.db";
private static final String DATABASE_NAME_ALIAS = "UserDataAbility";
private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.LOG_APP, 0xD00201, "Data_Log");
private OrmContext ormContext = null;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
DatabaseHelper manager = new DatabaseHelper(this);
ormContext = manager.getOrmContext(DATABASE_NAME_ALIAS, DATABASE_NAME, BookStore.class);
}
2、编写数据库操作方法。
Ability定义了6个方法供用户处理对数据库表数据的增删改查。这6个方法在Ability中已默认实现,开发者可按需重写。
方法 | 描述 |
---|---|
ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) | 查询数据库 |
int insert(Uri uri, ValuesBucket value) | 向数据库中插入单条数据 |
int batchInsert(Uri uri, ValuesBucket[] values) | 向数据库中插入多条数据 |
int delete(Uri uri, DataAbilityPredicates predicates) | 删除一条或多条数据 |
int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) | 更新数据库 |
DataAbilityResult[] executeBatch(ArrayList operations) | 批量操作数据库 |
3、批量操作数据库
这些方法的使用说明如下:
public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {
if (ormContext == null) {
HiLog.error(LABEL_LOG, "failed to query, ormContext is null");
return null;
}
// 查询数据库
OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
ResultSet resultSet = ormContext.query(ormPredicates, columns);
if (resultSet == null) {
HiLog.info(LABEL_LOG, "resultSet is null");
}
// 返回结果
return resultSet;
}
public int insert(Uri uri, ValuesBucket value) {
// 参数校验
if (ormContext == null) {
HiLog.error(LABEL_LOG, "failed to insert, ormContext is null");
return -1;
}
// 构造插入数据
User user = new User();
user.setUserId(value.getInteger("userId"));
user.setFirstName(value.getString("firstName"));
user.setLastName(value.getString("lastName"));
user.setAge(value.getInteger("age"));
user.setBalance(value.getDouble("balance"));
// 插入数据库
boolean isSuccessful = ormContext.insert(user);
if (!isSuccessful) {
HiLog.error(LABEL_LOG, "failed to insert");
return -1;
}
isSuccessful = ormContext.flush();
if (!isSuccessful) {
HiLog.error(LABEL_LOG, "failed to insert flush");
return -1;
}
DataAbilityHelper.creator(this, uri).notifyChange(uri);
int id = Math.toIntExact(user.getRowId());
return id;
}
public int delete(Uri uri, DataAbilityPredicates predicates) {
if (ormContext == null) {
HiLog.error(LABEL_LOG, "failed to delete, ormContext is null");
return -1;
}
OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
int value = ormContext.delete(ormPredicates);
DataAbilityHelper.creator(this, uri).notifyChange(uri);
return value;
}
public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
if (ormContext == null) {
HiLog.error(LABEL_LOG, "failed to update, ormContext is null");
return -1;
}
OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates,User.class);
int index = ormContext.update(ormPredicates, value);
HiLog.info(LABEL_LOG, "UserDataAbility update value:" + index);
DataAbilityHelper.creator(this, uri).notifyChange(uri);
return index;
}
和Service类似,开发者必须在配置文件中注册Data。
配置文件中该字段在创建Data Ability时会自动创建,name与创建的Data Ability一致。
需要关注以下属性:
{
"name": ".UserDataAbility",
"type": "data",
"visible": true,
"uri": "dataability://com.example.myapplication5.DataAbilityTest",
"permissions": [
"com.example.myapplication5.DataAbility.DATA"
]
}
开发者可以通过DataAbilityHelper类来访问当前应用或其他应用提供的共享数据。DataAbilityHelper作为客户端,与提供方的Data进行通信。Data接收到请求后,执行相应的处理,并返回结果。DataAbilityHelper提供了一系列与Data Ability对应的方法。
下面介绍DataAbilityHelper具体的使用步骤。
如果待访问的Data声明了访问需要权限,则访问此Data需要在配置文件中声明需要此权限。声明请参考权限申请字段说明。
"reqPermissions": [
{
"name": "com.example.myapplication5.DataAbility.DATA"
},
// 访问文件还需要添加访问存储读写权限
{
"name": "ohos.permission.READ_USER_STORAGE"
},
{
"name": "ohos.permission.WRITE_USER_STORAGE"
}
]
DataAbilityHelper为开发者提供了creator()方法来创建DataAbilityHelper实例。该方法为静态方法,有多个重载。最常见的方法是通过传入一个context对象来创建DataAbilityHelper对象。
获取helper对象示例:
DataAbilityHelper helper = DataAbilityHelper.creator(this);
DataAbilityHelper为开发者提供了一系列的接口来访问不同类型的数据(文件、数据库等)。
// 读取文件描述符
FileDescriptor fd = helper.openFile(uri, "r");
FileInputStream fis = new FileInputStream(fd);
// 使用文件描述符封装成的文件流,进行文件操作
方法 | 描述 |
---|---|
ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) | 查询数据库 |
int insert(Uri uri, ValuesBucket value) | 向数据库中插入单条数据 |
int batchInsert(Uri uri, ValuesBucket[] values) | 向数据库中插入多条数据 |
int delete(Uri uri, DataAbilityPredicates predicates) | 删除一条或多条数据 |
int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) | 更新数据库 |
DataAbilityResult[] executeBatch(ArrayList operations) | 批量操作数据库 |
这些方法的使用说明如下:
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 构造查询条件
DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.between("userId", 101, 103);
// 进行查询
ResultSet resultSet = helper.query(uri, columns, predicates);
// 处理结果
resultSet.goToFirstRow();
do {
// 在此处理ResultSet中的记录;
} while(resultSet.goToNextRow());
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 构造插入数据
ValuesBucket valuesBucket = new ValuesBucket();
valuesBucket.putString("name", "Tom");
valuesBucket.putInteger("age", 12);
helper.insert(uri, valuesBucket);
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 构造插入数据
ValuesBucket[] values = new ValuesBucket[2];
values[0] = new ValuesBucket();
values[0].putString("name", "Tom");
values[0].putInteger("age", 12);
values[1] = new ValuesBucket();
values[1].putString("name", "Tom1");
values[1].putInteger("age", 16);
helper.batchInsert(uri, values);
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 构造删除条件
DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.between("userId", 101, 103);
helper.delete(uri, predicates);
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 构造更新条件
DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.equalTo("userId", 102);
// 构造更新数据
ValuesBucket valuesBucket = new ValuesBucket();
valuesBucket.putString("name", "Tom");
valuesBucket.putInteger("age", 12);
helper.update(uri, valuesBucket, predicates);
DataAbilityHelper helper = DataAbilityHelper.creator(abilityObj, insertUri);
// 构造批量操作
ValuesBucket value1 = initSingleValue();
DataAbilityOperation opt1 = DataAbilityOperation.newInsertBuilder(insertUri).withValuesBucket(value1).build();
ValuesBucket value2 = initSingleValue2();
DataAbilityOperation opt2 = DataAbilityOperation.newInsertBuilder(insertUri).withValuesBucket(value2).build();
ArrayList<DataAbilityOperation> operations = new ArrayList<DataAbilityOperation>();
operations.add(opt1);
operations.add(opt2);
DataAbilityResult[] result = helper.executeBatch(insertUri, operations);
针对Data Ability开发,有以下示例工程可供参考:
我应该如何处理导致一些问题的常量。? import static android.net.ConnectivityManager.TYPE_BLUETOOTH; import
前言 因为鸿蒙系统刚出不久,官方的第三方登录SDK还没出来,下面就介绍下在鸿蒙应用中实现QQ登录的方法(支持唤起QQ安卓客户端进行授权) 前期准备 登录QQ开放平台 >
简介 前段时间一直研究ArkUI中的声明式开发,开发了一些demo,但都是界面相关的,相对来说比较基础,也比较简单。所以研究一下其他的,现在成熟的APP都会有网络交互,所以记录一篇网络
前言 鸿蒙这次API7更新除了新增TS声明式开发之外,还有JS开发也增加了很多API,JS开发自定义组件越来越方便了。 本项目基于ArkUI中JS扩展的类Web开发范式,关于
前言 本项目就是基于ArkUI中的声明式编程开发,语言ETS(Extended Type Script),代码都在ets文件中编写,这个文件用于描述 UI 布局、样式、事件交互和页面逻辑。
鸿蒙(HarmonyOS)原生AI能力之文本识别 原生智能介绍 在之前开发中,很多场景我们是通过调用云端的智能能力进行开发。例如文本识别、人脸识别等。 原生即指将一些能力直接集成在
全局弹窗相对于自定义弹窗有以下优点: 封装更彻底,一行代码就能调用 跟组件耦合度低,只需要传入组件的UIContext对象,不需要跟自定义弹窗一样需要在组件内部实例化CustomDialo
我正在使用 JS 框架创建一个 HarmonyOS 可穿戴应用程序,我想使用振动器。 watch 肯定有一个振动器,因为当我在设置应用程序中使用滚动条时我能感觉到它。 所以我申请了 system_gr
1 简介 通讯录demo主要分为联系人界面、设置紧急联系人、服务卡片3个模块,分为Java和JS两个版本,本篇主要讲解用尽可能的用纯JS去实现,实在无法实现的地方采用JS与Java结合
简介 本项目界面搭建基于ArkUI中TS扩展的声明式开发范式,关于语法和概念直接看官网官方文档地址: 基于TS扩展的声明式开发范式1、基于TS扩展的声明式开发范式2
DevEco Studio 下载、安装教程 DevEco Studio 下载 下载地址 运行环境 操作系统:Windows 10 64位 内存:8GB及以上 硬盘:100GB及以上 分辨率:1580*
我正在使用 Java SDK 在 HarmonyOS 中创建一个自定义组件,我必须在其中双击执行一些任务。但我无法检测到双击事件。 在 Android 中,借助 手势检测器 类我们可以检测双击事件如下
看到在 51CTO HarmonyOS社区张老师发了关于设备方向的认证资料,我给大家准备了应用方向的认证资料。 因为认证刚开始发布,现阶段去考相对来说是挺简单的,但是还是得把大纲的东西全部弄会。 官网
我正在开发华为 HarmonyOS 应用程序,我正在尝试使用 RxJava 为后台任务实现一个基类。我的问题是我不知道如何在主线程上观察。 在常规 Android 上,我会使用 AndroidSche
我正在做一个 Flutter 项目。其中,我们要生成 Android、iOS 和 HarmonyOS(华为)的构建版本。但我不确定 Flutter 是否支持这个操作系统。我浏览了互联网上的一些东西,但
我正在使用 Java SDK 在 HarmonyOS 中创建一个自定义组件,我必须在组件实例延迟一段时间后执行一些任务。 在 Android 中,我们有 postDelayed(Runnable ac
我是一名优秀的程序员,十分优秀!