HarmonyOS Data Ability的了解和使用

简介

使用Data模板的Ability(以下简称“Data”)有助于应用管理其自身和其他应用存储数据的访问,并提供与其他应用共享数据的方法。Data既可用于同设备不同应用的数据共享,也支持跨设备不同应用的数据共享。

数据的存放形式多样,可以是数据库,也可以是磁盘上的文件。Data对外提供对数据的增、删、改、查,以及打开文件等接口,这些接口的具体实现由开发者提供。

简单来说就是提供对外操作数据的接口,一类是对数据库操作的增删改查,另外一类是打开文件的接口进行访问文件;而这些接口是由我们开发者自己实现的。

URI

在HarmonyOS里面Data的提供和使用都通过URI来进行操作,提供方使用URI标识提供一个数据,而访问方通过URI来访问该标识访问数据;例如数据库中的某个表或磁盘上的某个文件,URI的格式如下:
在这里插入图片描述

  • scheme:协议方案名,固定为“dataability”,代表Data Ability所使用的协议类型。
  • authority:设备ID。如果为跨设备场景,则为目标设备的ID;如果为本地设备场景,则不需要填写。
  • path:资源的路径信息,代表特定资源的位置信息。
  • query:查询参数。
  • fragment:可以用于指示要访问的子资源。

再看一下官方提供的例子,这些URI要配置在config.json里面。

跨设备访问,则需要填写设备ID:

dataability://device_id/com.domainname.dataability.persondata/person/10

本地访问,则不需要填写设备ID:

dataability:///com.domainname.dataability.persondata/person/10

本地访问要注意:本地设备的“device_id”字段为空,因此在“dataability:”后面有三个“/”。

Data Ability的创建和使用

在了解到Data Ability是通过URI提供数据和访问之后就可以创建URI然后进行使用了。

创建前的准备

1.创建Data Ability的时候要认为的确定它的存储方式,Data Ability支持以下两种数据形式:

  • 文件数据:比如文本,图片,音乐等媒体数据
  • 结构化数据:如数据库

比如要访问数据库,那么在创建Data Ability的时候最好就指定数据形式是结构化数据,然后Data Ability作为数据库的数据提供者。

在操作数据库的时候需要在onStart里面初始化连接数据库,只要通过ormContext连接到数据库就行了,这里不做耗时操作:

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)批量操作数据库

这些方法的具体使用待会在代码中进行实现,query、insert、update、delete这四个方法需要我们开发自己实现,而batchInsert和executeBatch是HarmonyOS已经实现了直接进行使用就可以了。

3.注册Data Ability
既然是Ability那么就要在config.json里面注册,但是注册Data Ability的时候要注意以下几点:

  1. type:类型要设置为data
  2. uri:对外访问的路径,这个路径要求全局唯一
  3. permissions:访问该data ability时需要申请的权限

官方例子如下:

{
    "name": ".UserDataAbility",
     "type": "data",
     "visible": true,
     "uri": "dataability://com.example.myapplication5.DataAbilityTest",
     "permissions": [
        "com.example.myapplication5.DataAbility.DATA"
     ]
}

4.DataAbilityHelper访问Data Ability

开发者可以通过DataAbilityHelper类来访当前应用或者其他应用提供的共享数据。

DataAbilityHelper作为客户端,与提供方的Data进行通信。

Data接收到请求后,执行相应的处理并返回结果。

DataAbilityHepler提供了一系列与DataAbility相对应的方法,如下:

在这里插入图片描述

Data Ability的创建

在包名下直接右键New -> Ability ->Empty data Ability
在这里插入图片描述
创建完成之后会在config.json的abilities下面自动给我们配置了该data ability的相关信息,如下:
在这里插入图片描述
我们可以看到它这里由这么一行代码:

"permissions": [
    "com.example.myapplication.DataAbilityShellProvider.PROVIDER"
]

这个权限就是我们一会在访问该Data Ability的时候所需要使用到的权限,该权限可以自定义,那么它既然有权限,我们就需要在注册权限的地方给它加上:

"reqPermissions": [
   {
        "name": "com.example.myapplication.DataAbilityShellProvider.PROVIDER"
   }
]

前面我们提到在Data Ability提供了我们对数据库进行增删改查的几个方法,在创建完成Data Ability之后会自动给我们重写了那四个需要我们开发人员自己实现的方法,如下:
在这里插入图片描述
在对数据库进行操作的时候就需要开发人员在四个方法里面自己写逻辑了。

配置ORM数据库以及初始化

1.在build.gradle的ohos模块下添加以下代码,打开注解开关:

ohos {
    compileSdkVersion 5
    defaultConfig {
        compatibleSdkVersion 4
    }
    buildTypes {
        release {
            proguardOpt {
                proguardEnabled false
                rulesFiles 'proguard-rules.pro'
            }
        }
    }
    //配置orm数据库  
    compileOptions{
        annotationEnabled true
    }
}

2.导入依赖包

在HarmonyOS安装的时候,sdk里面就给我们提供了响应的依赖包,可以直接从里面把jar包复制到libs里面进行导入,也可以直接从本地磁盘进行导入,这里就还是使用本地磁盘进行导入,方便不知道怎么查找sdk的提供一下路径:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
    testImplementation 'junit:junit:4.13'
    ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.100'
    compile files(
            "E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\api\\ohos.jar",
            "E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\javapoet_java.jar",
            "E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_java.jar",
            "E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_processor_java.jar"
    )
    annotationProcessor files(
            "E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\javapoet_java.jar",
            "E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_java.jar",
            "E:\\Program Files\\Huawei\\sdk\\java\\2.1.1.21\\build-tools\\lib\\orm_annotations_processor_java.jar"
    )
}

其中E:\Program Files\Huawei\是你的安装路径,这里我是安装在了E盘下面的Program Files。

3.创建数据库类

创建数据库类继承至OrmDatabase,并配置数据库表StudentEntity.class

@Database(entities = {StudentEntity.class},version = 1)
public abstract class StudentStore extends OrmDatabase {
}

4.创建数据库表

创建StudentEntity数据库表继承至OrmObject,使用@Entity注解,写好相关字段并实现get和set方法

/**
 * tableName 表名为 student
 * indices = {@Index(value = {"studentId"},name = "studentId_index",unique = true)}
 * 使用studentId来给这个表构建一个索引,索引名称为studentId_index,然后这个索引不能重复为true
 * value  索引值
 * name  索引名称
 * unique 索引是否可以重复
 * */
@Entity(tableName = "student",indices = {@Index(value = {"studentId"},name = "studentId_index",unique = true)})
public class StudentEntity extends OrmObject {

    //主键自增
    @PrimaryKey(autoGenerate = true)
    private Integer studentId;
    private String studentName;
    private String studentSex;
    private Integer studentAge;

    public Integer getStudentId() {
        return studentId;
    }

    public void setStudentId(Integer studentId) {
        this.studentId = studentId;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getStudentSex() {
        return studentSex;
    }

    public void setStudentSex(String studentSex) {
        this.studentSex = studentSex;
    }

    public Integer getStudentAge() {
        return studentAge;
    }

    public void setStudentAge(Integer studentAge) {
        this.studentAge = studentAge;
    }
}

5.初始化数据库

数据库和数据表已经创建好了,那么要在Data Ability那面初始化该数据库并拿到这个数据库的资源句柄,以便在后面操作数据库。

先声明数据库的别名和数据库的文件名:

private String dbAlias = "DataAbilityDemoStore";//数据库别名
private String dbFileName = "DataAbilityDemoStore.db";//数据库文件名

获取DataBaseHelper实例对象:

helper = new DatabaseHelper(this);

通过DataBaseHelper去创建数据库:

ormContext = helper.getOrmContext(dbAlias,dbFileName, StudentStore.class);

数据库创建完成。

DataAbility对数据库进行增删改查

Data Ability和ORM数据库都创建完成了,那么接下来就是在Data Ability里面对ORM数据库进行增删改查操作的实现,就是在创建Data Ability的时候默认给我们重写的那四个方法。

insert插入

获取到Orm数据库的资源句柄之后就可以通过insert进行数据插入了,但是在插入之前还需要做几个准备。

首先要判断一下orm数据库是否为空,如果为空则说明数据库没有进行初始化则直接返回失败:

if (ormContext == null){//数据库为空  没有进行初始化
      return -1;//返回负一表示插入失败
}

然后还要判断一下传过来的uri的参数,这里只使用二级参数作为例子,判断第二个参数是否等于student,如果是,则插入到student表里面去,如果不是则返回失败;当然这里在项目也会中会有很多张表,你就需要根据传过来的参数不同而将数据插入到不同的表里面去如下:

if (uri.getDecodedPathList().get(1).equals("student")){
     //todo 插入数据到学生表
}
if (uri.getDecodedPathList().get(1).equals("teacher")){
     //todo 插入数据到老师表
}

最后根据ValuesBucket传过来的值将那些值添加到相关实体里面去,在使用insert进行插入:

StudentEntity studentEntity = new StudentEntity();
studentEntity.setStudentName(value.getString("studentName"));
studentEntity.setStudentSex(value.getString("studentSex"));
studentEntity.setStudentAge(value.getInteger("studentAge"));

boolean insert = ormContext.insert(studentEntity);
if (!insert){//如果插入返回的结果是false  则说明插入失败
     return -1;
}

boolean flush = ormContext.flush();
if (!flush){//如果刷新数据返回的结果是false 则说明刷新失败
     return -1;
}
//获取插入数据成功后数据所在的行id,并返回
int rowId = Math.toIntExact(studentEntity.getRowId());

既然插入的代码写好了,那么自然就是要访问Data Ability并传递数据过来了,不然哪来的数据进行插入?

这里使用DataAbilityHelper进行访问,并传递数据,首先要创建访问路径:

  1. 因为在插入的时候判断了第二个参数是否是student,那么需要在路径后面多加一级
  2. 因为是本地访问,那么就没有设备ID,但是有三个斜杠///
/**
* /// 三个斜杠表示本地访问Data Ability
* /student 第二个参数是student
*/
String studentUriStr = "dataability:///com.example.myapplication.DemoDataAbility/student";

Uri dataAbilityUri = Uri.parse(studentUriStr);

然后创建一个DataAbilityHelper实例:

DataAbilityHelper helper = DataAbilityHelper.creator(MainAbilitySlice.this);

然后通过helper.insert()进行访问插入数据:

  • Uri 参数一 :访问的Data Ability的uri路径
  • ValuesBucket 参数二:访问Data Ability携带过去的参数对象
helper.insert(dataAbilityUri,valuesBucket);

valuesBucket就是一个对象拼接参数和值,代码如下:

ValuesBucket valuesBucket = new ValuesBucket();
valuesBucket.putString("studentName","张三");
valuesBucket.putString("studentSex","男");
valuesBucket.putInteger("studentAge",20);

最后再Data Ability打印输出一下ORM数据库插入数据以及刷新数据返回的结果:

HiLog.info(LABEL_LOG,"DemoDataAbility insert insert:"+insert);
HiLog.info(LABEL_LOG,"DemoDataAbility insert flush:"+flush);

在这里插入图片描述
都为true,说明插入和刷新都成功了。

query查询

查询数据同样使用DataAbilityHelper去访问Data Ability进行查询,所以先要创建一下DataAbilityHelper实例对象:

DataAbilityHelper helper = DataAbilityHelper.creator(MainAbilitySlice.this);

既然要查询数据,那么就要有查询条件,Data Ability给提供了组装谓词的对象叫做DataAbilityPredicates,通过该对象去创建谓词查询条件,这里我们查询名称为张三的student:

DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.equalTo("studentName","张三");

然后通过DataAbilityHelper的query方法进行查询,并返回结果集:

  • Uri:参数一,要访问Data Ability的参数
  • String[]:参数二,要查询表里面的哪些字段
  • DataAbilityPredicates:参数三,查询的谓词条件
ResultSet resultSet = helper.query(dataAbilityUri,
				new String[]{"studentId","studentName","studentSex","studentAge"},
				predicates);

将查询到的结果输出到控制台,在输出之前要先判断一下结果集是否为空:


if (resultSet != null && resultSet.getRowCount() > 0){
      resultSet.goToFirstRow();
      do {
          int studentId = resultSet.getInt(resultSet.getColumnIndexForName("studentId"));
          String studentName = resultSet.getString(resultSet.getColumnIndexForName("studentName"));
          String studentSex = resultSet.getString(resultSet.getColumnIndexForName("studentSex"));
          int studentAge = resultSet.getInt(resultSet.getColumnIndexForName("studentAge"));
          System.out.println("studentInfo:"+studentId+"--"+studentName+"--"+studentSex+"--"+studentAge);
       }while (resultSet.goToNextRow());
}

查询条件写好了,那么当然就要在Data Ability里面进行查询操作并返回结果了,在查询之前同样要对数据库资源句柄进行非空判断,对uri的第二个参数进行判断,是否是我们要查询的表:

if (ormContext == null){
        return null;
}
if (!uri.getDecodedPathList().get(1).equals("student")){
        return null;
}

将Data Ability的谓词条件转变成Orm数据库查询的谓词条件,使用DataAbilityUtils进行转换:

  • DataAbilityPredicates:参数一 Data Ability谓词条件
  • entity:参数二要查询的表
OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(
		predicates, StudentEntity.class);

使用ORM数据库资源句柄进行查询,并返回结果集,输出在控制台:

ResultSet query = ormContext.query(ormPredicates, columns);
return query;

在这里插入图片描述
查询成功。

Data Ability批量插入和批量执行

1.批量插入

在项目开发中往数据库里面插入数据不可能每次都是一条一条的插入,数据多的时候操作就很繁琐,这时候Data Ability给我们提供了一个叫batchInsert的接口执行批量插入数据的操作。

前面使用insert插入数据的时候是要传入一个ValuesBucket参数对象,那么批量插入自然就是传入多个ValuesBucket参数对象,这里要传入的是一个集合,先构建一个参数集合,并且集合的大小为10:

ValuesBucket[] valuesBuckets = new ValuesBucket[10];

给集合添加数据,没一个数据都对应一个ValuesBucket参数对象:

for (int i = 0;i < 10; i++){
    valuesBuckets[i] = new ValuesBucket();
    valuesBuckets[i].putString("studentName","张三");
    valuesBuckets[i].putString("studentSex","男");
    valuesBuckets[i].putInteger("studentAge",20);
}

通过DataAbilityHelper的batchInsert方法进行插入,并返回插入的行数:

  • Uri:参数一 访问Data Ability的uri路径
  • ValuesBucket[]:参数对象集合
int rowCount = helper.batchInsert(dataAbilityUri, valuesBuckets);

查询后得到以下结果:
在这里插入图片描述
2.批量执行

批量执行可以执行插入,修改,删除等等操作,这里操作指的是DataAbilityOperation,先来看一下参数,了解参数才能更好的使用:

  1. Uri 访问Data Ability的uri路径
  2. ArrayList<> DataAbilityOperation 操作集合,意思就是我们要执行什么批量操作就要写多个DataAbilityOperation操作放到集合里面去,然后调用executeBatch方法进行执行
public DataAbilityResult[] executeBatch(Uri uri, ArrayList<DataAbilityOperation> operations) throws DataAbilityRemoteException, OperationExecuteException {
    throw new RuntimeException("Stub!");
}

可以看到DataAbilityOperation里面以下insert、update、delete的构建方法,说明我们使用批量执行的方法可以执行批量插入,批量修改,批量删除的操作:
在这里插入图片描述
这里还是以批量插入为例进行操作。

首先创建三个数据源:

ValuesBucket valuesBuckets = new ValuesBucket();
valuesBuckets.putString("studentName","张三");
valuesBuckets.putString("studentSex","男");
valuesBuckets.putInteger("studentAge",20);
                    
ValuesBucket valuesBuckets2 = new ValuesBucket();
valuesBuckets2.putString("studentName","王五");
valuesBuckets2.putString("studentSex","男");
valuesBuckets2.putInteger("studentAge",20);
                    
ValuesBucket valuesBuckets3 = new ValuesBucket();
valuesBuckets3.putString("studentName","麻子");
valuesBuckets3.putString("studentSex","男");
valuesBuckets3.putInteger("studentAge",20);

创建DataAbilityOperation操作集合:

ArrayList<DataAbilityOperation> dataAbilityOperationArrayList = new ArrayList<>();

创建DataAbilityOperation,指向要执行什么操作这里是插入,所以是insert,并将创建好的操作添加到操作集合里面去:

DataAbilityOperation operation = DataAbilityOperation.newInsertBuilder(dataAbilityUri)
										.withValuesBucket(valuesBuckets)
										.build();
dataAbilityOperationArrayList.add(operation);

最后使用DataAbilityHelper的executeBatch执行批量操作:

helper.executeBatch(dataAbilityUri, dataAbilityOperationArrayList);

查询结果输出到控制台:
在这里插入图片描述
批量操作成功。

delete删除数据

删除数据就比较简单了,只要构建好删除的谓词条件,使用谓词条件进行删除就行了。

那么首先构建要删除的谓词条件:

DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.equalTo("studentName","张三");

然后使用DataAbilityHelper的delete进行删除,返回的是删除的条数:

int delete = helper.delete(dataAbilityUri2, predicates);

最后再Data Ability里面重写的delete方法里面执行删除操作:

@Override
public int delete(Uri uri, DataAbilityPredicates predicates) {
        if (ormContext == null){
            return -1;
        }
        if (!uri.getDecodedPathList().get(1).equals("student")){
            return -1;
        }
        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates, StudentEntity.class);
        int delete = ormContext.delete(ormPredicates);
        return delete;
}

看一下控制台输出的结果:
在这里插入图片描述

update更新数据

更新数据也比较简单,只要构建好要更新数据的谓词条件,和构建好更新数据在通过update方法去更新就可以了。

构建谓词条件,修改名字为张三的这条数据:

DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.equalTo("studentName", "张三");

构建更新数据,将张三的数据改为以下值:

ValuesBucket valuesBucket = new ValuesBucket();
valuesBucket.putString("studentName", "张三改");
valuesBucket.putInteger("studentAge", 40);

使用update方法进行更新:

int update = helper.update(dataAbilityUri2, valuesBucket, predicates);

在Data Ability的update方法里面进行更新操作:

@Override
public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
        if (ormContext == null){
            return -1;
        }
        if (!uri.getDecodedPathList().get(1).equals("student")){
            return -1;
        }
        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates, StudentEntity.class);
        int update = ormContext.update(ormPredicates, value);
        return update;
}

控制台查看内容:
在这里插入图片描述
以上内容就是Data Ability对数据库的增删改查,总的来说还是很方便的,将所有数据库的操作都放到Data Ability里面去统一执行。

跨设备访问Data Ability

前面就说到Data Ability是支持跨设备访问的,要在uri里面添加对应的DevcieId,同时除了添加这一个设备ID以外,还要注意以下几个条件。

1.定义应用级的访问权限,简单来说就是你想要访问这个应用,你必须要拥有该应用的应用权限,如下:

"defPermissions": [
      {
        "name": "com.example.myapplication.DataAbilityShellProvider.PROVIDER",
        "grantMode": "system_grant"
      }
]

2.因为是要跨设备访问,那么获取设备信息的权限自然是要有的,就要加上分布式数据同步和设备信息获取的权限,如下:

"reqPermissions": [
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC"
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"
      },
      {
        "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
      },
      {
        "name": "ohos.permission.GET_BUNDLE_INFO"
      }
]

并在onStart方法里面初始化:

public class MainAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());
		//初始化权限
        requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"
                ,"ohos.permission.servicebus.ACCESS_SERVICE"
                ,"com.huawei.hwddmp.servicebus.BIND_SERVICE"},0);
    }
}

3.Data Ability的注册信息中一定要打开允许其他设备访问的权限
这个东西在创建Data Ability的时候不会自动创建,需要我们手动添加以下代码:

"visible": true,

visible:是否允许其他第三方应用访问本应用。

Data Ability的配置就变成以下代码:

{
  "visible": true,//允许其他第三方设备访问本应用
  "permissions": [
     "com.example.myapplication.DataAbilityShellProvider.PROVIDER"
  ],
  "name": "com.example.myapplication.DemoDataAbility",
  "icon": "$media:icon",
  "description": "$string:demodataability_description",
  "type": "data",
  "uri": "dataability://com.example.myapplication.DemoDataAbility"
}

以上就是一些跨设备访问需要注意的点,如果不配置好的话是无法进行跨设备访问Data Ability的。

代码

今天主要实现的是Data Ability对数据库的一些操作,文件的操作还没有实现,代码不多,主要三个文件:

  1. DemoDataAbility 在Data Ability里面使用ORM数据库,执行增删改查的操作
  2. OptionsDataAbilitySlice 本地访问Data Ability,使用DataAbilityHelper执行增删改查
  3. config.json 配置文件

DemoDataAbility.class代码如下:

package com.example.myapplication;

import com.example.myapplication.data.StudentEntity;
import com.example.myapplication.data.StudentStore;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.data.DatabaseHelper;
import ohos.data.dataability.DataAbilityUtils;
import ohos.data.orm.OrmContext;
import ohos.data.orm.OrmPredicates;
import ohos.data.resultset.ResultSet;
import ohos.data.rdb.ValuesBucket;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import ohos.utils.net.Uri;
import ohos.utils.PacMap;

import java.io.FileDescriptor;

public class DemoDataAbility extends Ability {
    private static final HiLogLabel LABEL_LOG = new HiLogLabel(3, 0xD001100, "DataAbilityDemo");

    private OrmContext ormContext;
    private DatabaseHelper helper;
    private String dbAlias = "DataAbilityDemoStore";//数据库别名
    private String dbFileName = "DataAbilityDemoStore.db";//数据库文件名

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        HiLog.info(LABEL_LOG, "DemoDataAbility onStart");
        helper = new DatabaseHelper(this);
        ormContext = helper.getOrmContext(dbAlias,dbFileName, StudentStore.class);
    }

    @Override
    public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {
        if (ormContext == null){
            return null;
        }
        if (!uri.getDecodedPathList().get(1).equals("student")){
            return null;
        }
        //将Data Ability的谓词转变成Orm的谓词
        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates, StudentEntity.class);
        ResultSet query = ormContext.query(ormPredicates, columns);
        return query;
    }

    @Override
    public int insert(Uri uri, ValuesBucket value) {
        HiLog.info(LABEL_LOG, "DemoDataAbility insert");
        if (ormContext == null){//数据库为空  没有进行初始化
            return -1;//返回负一表示插入失败
        }
        /**
         * uri.getDecodedPathList().get(1) 获取传过来的uri的第二个元素,如果它不等于student则说明传过来的有误,无法插入到student表里面去
         * dataability://com.example.myapplication.DemoDataAbility/student
         * com.example.myapplication.DemoDataAbility 第一个
         * student 第二个
         * */
        if (!uri.getDecodedPathList().get(1).equals("student")){
            return -1;
        }
        /**
         * ValuesBucket
         * 获取传过来的值  并将值设置到student表里面去
         * */
        StudentEntity studentEntity = new StudentEntity();
        studentEntity.setStudentName(value.getString("studentName"));
        studentEntity.setStudentSex(value.getString("studentSex"));
        studentEntity.setStudentAge(value.getInteger("studentAge"));

        boolean insert = ormContext.insert(studentEntity);
        if (!insert){//如果插入返回的结果是false  则说明插入失败
            return -1;
        }
        HiLog.info(LABEL_LOG,"DemoDataAbility insert insert:"+insert);

        boolean flush = ormContext.flush();
        if (!flush){//如果刷新数据返回的结果是false 则说明刷新失败
            return -1;
        }
        HiLog.info(LABEL_LOG,"DemoDataAbility insert flush:"+flush);

        int rowId = Math.toIntExact(studentEntity.getRowId());//获取插入数据成功后数据所在的行id,并返回
        return rowId;
    }

    @Override
    public int delete(Uri uri, DataAbilityPredicates predicates) {
        if (ormContext == null){
            return -1;
        }
        if (!uri.getDecodedPathList().get(1).equals("student")){
            return -1;
        }
        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates, StudentEntity.class);
        int delete = ormContext.delete(ormPredicates);
        return delete;
    }

    @Override
    public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
        if (ormContext == null){
            return -1;
        }
        if (!uri.getDecodedPathList().get(1).equals("student")){
            return -1;
        }
        OrmPredicates ormPredicates = DataAbilityUtils.createOrmPredicates(predicates, StudentEntity.class);
        int update = ormContext.update(ormPredicates, value);
        return update;
    }

    @Override
    public FileDescriptor openFile(Uri uri, String mode) {
        return null;
    }

    @Override
    public String[] getFileTypes(Uri uri, String mimeTypeFilter) {
        return new String[0];
    }

    @Override
    public PacMap call(String method, String arg, PacMap extras) {
        return null;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }
}

OptionsDataAbilitySlice.class代码如下:

package com.example.myapplication.slice;

import com.example.myapplication.ResourceTable;
import ohos.aafwk.ability.*;
import ohos.aafwk.content.Intent;
import ohos.data.dataability.DataAbilityPredicates;
import ohos.data.rdb.ValuesBucket;
import ohos.data.resultset.ResultSet;
import ohos.utils.net.Uri;

import java.util.ArrayList;

public class OptionsDataAbilitySlice extends AbilitySlice {
    private Uri dataAbilityUri;
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_options_data);
        String studentUriStr = "dataability:///com.example.myapplication.DemoDataAbility/student";
        dataAbilityUri = Uri.parse(studentUriStr);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
    /**
     * 本地访问Data Ability插入数据的方法
     * */
    private void insertData(){
        try {
            DataAbilityHelper helper = DataAbilityHelper.creator(OptionsDataAbilitySlice.this);
            ValuesBucket valuesBucket = new ValuesBucket();
            valuesBucket.putString("studentName","张三");
            valuesBucket.putString("studentSex","男");
            valuesBucket.putInteger("studentAge",20);
            //insert返回插入的行id
            int insert = helper.insert(dataAbilityUri, valuesBucket);
            System.out.println("insertRowId:"+insert);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
    }
    /**
     * 本地访问Data Ability查询数据的方法
     * */
    private void queryData(){
        try {
            DataAbilityHelper helper = DataAbilityHelper.creator(OptionsDataAbilitySlice.this);
            DataAbilityPredicates predicates = new DataAbilityPredicates();
            predicates.equalTo("studentName","张三");
            ResultSet resultSet = helper.query(dataAbilityUri,new String[]{"studentId","studentName","studentSex","studentAge"},predicates);

            if (resultSet != null && resultSet.getRowCount() > 0){
                resultSet.goToFirstRow();
                do {
                    int studentId = resultSet.getInt(resultSet.getColumnIndexForName("studentId"));
                    String studentName = resultSet.getString(resultSet.getColumnIndexForName("studentName"));
                    String studentSex = resultSet.getString(resultSet.getColumnIndexForName("studentSex"));
                    int studentAge = resultSet.getInt(resultSet.getColumnIndexForName("studentAge"));
                    System.out.println("studentInfo:"+studentId+"--"+studentName+"--"+studentSex+"--"+studentAge);
                }while (resultSet.goToNextRow());
            }
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
    }
    /**
     * 本地访问Data Ability批量插入数据的方法
     * */
    private void batchInsertData(){
        try {
            DataAbilityHelper helper = DataAbilityHelper.creator(OptionsDataAbilitySlice.this);
            ValuesBucket[] valuesBuckets = new ValuesBucket[10];
            for (int i = 0;i < 10; i++){
                valuesBuckets[i] = new ValuesBucket();
                valuesBuckets[i].putString("studentName","张三");
                valuesBuckets[i].putString("studentSex","男");
                valuesBuckets[i].putInteger("studentAge",20);
            }
            int rowCount = helper.batchInsert(dataAbilityUri, valuesBuckets);
            System.out.println("rowCount:"+rowCount);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
    }
    /**
     * 本地访问Data Ability批量执行的方法
     * */
    private void executeBatchData(){
        try {
            ValuesBucket valuesBuckets = new ValuesBucket();
            valuesBuckets.putString("studentName","张三");
            valuesBuckets.putString("studentSex","男");
            valuesBuckets.putInteger("studentAge",20);

            ValuesBucket valuesBuckets2 = new ValuesBucket();
            valuesBuckets2.putString("studentName","王五");
            valuesBuckets2.putString("studentSex","男");
            valuesBuckets2.putInteger("studentAge",20);

            ValuesBucket valuesBuckets3 = new ValuesBucket();
            valuesBuckets3.putString("studentName","麻子");
            valuesBuckets3.putString("studentSex","男");
            valuesBuckets3.putInteger("studentAge",20);


            DataAbilityHelper helper = DataAbilityHelper.creator(OptionsDataAbilitySlice.this);
            ArrayList<DataAbilityOperation> dataAbilityOperationArrayList = new ArrayList<>();

            DataAbilityOperation operation = DataAbilityOperation.newInsertBuilder(dataAbilityUri).withValuesBucket(valuesBuckets).build();
            DataAbilityOperation operation2 = DataAbilityOperation.newInsertBuilder(dataAbilityUri).withValuesBucket(valuesBuckets2).build();
            DataAbilityOperation operation3 = DataAbilityOperation.newInsertBuilder(dataAbilityUri).withValuesBucket(valuesBuckets3).build();


            dataAbilityOperationArrayList.add(operation);
            dataAbilityOperationArrayList.add(operation2);
            dataAbilityOperationArrayList.add(operation3);

            DataAbilityResult[] dataAbilityResults = helper.executeBatch(dataAbilityUri, dataAbilityOperationArrayList);
        }catch (Exception e){}
    }
    /**
     * 本地访问Data Ability删除数据的方法
     * */
    private void deleteData(){
        try {
            DataAbilityHelper helper = DataAbilityHelper.creator(OptionsDataAbilitySlice.this);
            DataAbilityPredicates predicates = new DataAbilityPredicates();
            predicates.equalTo("studentName","张三");
            int delete = helper.delete(dataAbilityUri, predicates);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
    }
    /**
     * 本地访问Data Ability更新数据的方法
     * */
    private void updateData(){
        try {
            DataAbilityHelper helper = DataAbilityHelper.creator(OptionsDataAbilitySlice.this);
            // 构造更新条件
            DataAbilityPredicates predicates = new DataAbilityPredicates();
            predicates.equalTo("studentName", "张三");

            // 构造更新数据
            ValuesBucket valuesBucket = new ValuesBucket();
            valuesBucket.putString("studentName", "张三改");
            valuesBucket.putInteger("studentAge", 40);
            int update = helper.update(dataAbilityUri, valuesBucket, predicates);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
    }
}

config.json代码如下:

{
  "app": {
    "bundleName": "com.example.myapplication",
    "vendor": "example",
    "version": {
      "code": 1000000,
      "name": "1.0.0"
    }
  },
  "deviceConfig": {},
  "module": {
    "package": "com.example.myapplication",
    "name": ".MyApplication",
    "mainAbility": "com.example.myapplication.MainAbility",
    "deviceType": [
      "phone"
    ],
    "distro": {
      "deliveryWithInstall": true,
      "moduleName": "entry",
      "moduleType": "entry",
      "installationFree": false
    },
    "abilities": [
      {
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "action.system.home"
            ]
          }
        ],
        "orientation": "unspecified",
        "name": "com.example.myapplication.MainAbility",
        "icon": "$media:icon",
        "description": "$string:mainability_description",
        "label": "$string:entry_MainAbility",
        "type": "page",
        "launchType": "standard"
      },
      {
        "visible": true,
        "permissions": [
          "com.example.myapplication.DataAbilityShellProvider.PROVIDER"
        ],
        "name": "com.example.myapplication.DemoDataAbility",
        "icon": "$media:icon",
        "description": "$string:demodataability_description",
        "type": "data",
        "uri": "dataability://com.example.myapplication.DemoDataAbility"
      },
      {
        "orientation": "unspecified",
        "name": "com.example.myapplication.OptionsDataAbility",
        "icon": "$media:icon",
        "description": "$string:optionsdataability_description",
        "label": "$string:entry_OptionsDataAbility",
        "type": "page",
        "launchType": "standard"
      }
    ],
    "defPermissions": [
      {
        "name": "com.example.myapplication.DataAbilityShellProvider.PROVIDER",
        "grantMode": "system_grant"
      }
    ],
    "reqPermissions": [
      {
        "name": "com.example.myapplication.DataAbilityShellProvider.PROVIDER"
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DATASYNC"
      },
      {
        "name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE"
      },
      {
        "name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
      },
      {
        "name": "ohos.permission.GET_BUNDLE_INFO"
      },{
        "name": "ohos.permission.READ_USER_STORAGE"
      }
    ]
  }
}

以上就是今天实现的内容了,其实Data Ability的本地访问和跨设备访问只要注意上面的配置就可以,代码实现没什么区别。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值