HarmonyOS學習路之開發(fā)篇——Data Ability

Data Ability基本概念

使用Data模板的Ability(以下簡稱“Data”)有助于應用管理其自身和其他應用存儲數(shù)據的訪問,并提供與其他應用共享數(shù)據的方法。Data既可用于同設備不同應用的數(shù)據共享,也支持跨設備不同應用的數(shù)據共享。

數(shù)據的存放形式多樣,可以是數(shù)據庫,也可以是磁盤上的文件。Data對外提供對數(shù)據的增、刪、改、查,以及打開文件等接口,這些接口的具體實現(xiàn)由開發(fā)者提供。

URI介紹

Data的提供方和使用方都通過URI(Uniform Resource Identifier)來標識一個具體的數(shù)據,例如數(shù)據庫中的某個表或磁盤上的某個文件。HarmonyOS的URI仍基于URI通用標準,格式如下:

  • scheme:協(xié)議方案名,固定為“dataability”,代表Data Ability所使用的協(xié)議類型
  • authority:設備ID。如果為跨設備場景,則為目標設備的ID;如果為本地設備場景,則不需要填寫。
  • path:資源的路徑信息,代表特定資源的位置信息。
  • query:查詢參數(shù)。 f
  • ragment:可以用于指示要訪問的子資源。

URI示例:

創(chuàng)建Data

使用Data模板的Ability形式仍然是Ability,因此,開發(fā)者需要為應用添加一個或多個Ability的子類,來提供程序與其他應用之間的接口。Data為結構化數(shù)據和文件提供了不同API接口供用戶使用,因此,開發(fā)者需要首先確定好使用何種類型的數(shù)據。本章節(jié)主要講述了創(chuàng)建Data的基本步驟和需要使用的接口。
Data提供方可以自定義數(shù)據的增、刪、改、查,以及文件打開等功能,并對外提供這些接口。

確定數(shù)據存儲方式

確定數(shù)據的存儲方式,Data支持以下兩種數(shù)據形式:

  • 文件數(shù)據:如文本、圖片、音樂等。
  • 結構化數(shù)據:如數(shù)據庫等。

實現(xiàn)UserDataAbility

UserDataAbility用于接收其他應用發(fā)送的請求,提供外部程序訪問的入口,從而實現(xiàn)應用間的數(shù)據訪問。

實現(xiàn)UserDataAbility,需要在“Project”窗口當前工程的主目錄(“entry > src > main > java > com.xxx.xxx”)選擇“File > New > Ability > Empty Data Ability”,設置“Data Name”后完成UserDataAbility的創(chuàng)建。

Data提供了文件存儲和數(shù)據庫存儲兩組接口供用戶使用。

文件存儲

開發(fā)者需要在Data中重寫FileDescriptor openFile(Uri uri, String mode)方法來操作文件:uri為客戶端傳入的請求目標路徑;mode為開發(fā)者對文件的操作選項,可選方式包含“r”(讀), “w”(寫), “rw”(讀寫)等。

ohos.rpc.MessageParcel類提供了一個靜態(tài)方法,用于獲取MessageParcel實例。開發(fā)者可通過獲取到的MessageParcel實例,使用dupFileDescriptor()函數(shù)復制待操作文件流的文件描述符,并將其返回,供遠端應用訪問文件。

示例:根據傳入的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 {
    // 創(chuàng)建messageParcel
    MessageParcel messageParcel = MessageParcel.obtain();
    File file = new File(uri.getDecodedPathList().get(0)); //get(0)是獲取URI完整字段中查詢參數(shù)字段。
    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);
}

數(shù)據庫存儲
1、初始化數(shù)據庫連接。
系統(tǒng)會在應用啟動時調用onStart()方法創(chuàng)建Data實例。在此方法中,開發(fā)者應該創(chuàng)建數(shù)據庫連接,并獲取連接對象,以便后續(xù)和數(shù)據庫進行操作。為了避免影響應用啟動速度,開發(fā)者應當盡可能將非必要的耗時任務推遲到使用時執(zhí)行,而不是在此方法中執(zhí)行所有初始化。

示例:初始化的時候連接數(shù)據庫

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、編寫數(shù)據庫操作方法。
Ability定義了6個方法供用戶處理對數(shù)據庫表數(shù)據的增刪改查。這6個方法在Ability中已默認實現(xiàn),開發(fā)者可按需重寫。

方法 描述
ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) 查詢數(shù)據庫
int insert(Uri uri, ValuesBucket value) 向數(shù)據庫中插入單條數(shù)據
int batchInsert(Uri uri, ValuesBucket[] values) 向數(shù)據庫中插入多條數(shù)據
int delete(Uri uri, DataAbilityPredicates predicates) 刪除一條或多條數(shù)據
int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) 更新數(shù)據庫
DataAbilityResult[] executeBatch(ArrayList<DataAbilityOperation> operations) 批量操作數(shù)據庫

3、批量操作數(shù)據庫
這些方法的使用說明如下:

  • query()
    該方法接收三個參數(shù),分別是查詢的目標路徑,查詢的列名,以及查詢條件,查詢條件由類DataAbilityPredicates構建。根據傳入的列名和查詢條件查詢用戶表的代碼示例如下:
public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {
    if (ormContext == null) {
        HiLog.error(LABEL_LOG, "failed to query, ormContext is null");
        return null;
    }

    // 查詢數(shù)據庫
    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;
}
  • insert()
    該方法接收兩個參數(shù),分別是插入的目標路徑和插入的數(shù)據值。其中,插入的數(shù)據由ValuesBucket封裝,服務端可以從該參數(shù)中解析出對應的屬性,然后插入到數(shù)據庫中。此方法返回一個int類型的值用于標識結果。接收到傳過來的用戶信息并把它保存到數(shù)據庫中的代碼示例如下:
public int insert(Uri uri, ValuesBucket value) {
    // 參數(shù)校驗
    if (ormContext == null) {
        HiLog.error(LABEL_LOG, "failed to insert, ormContext is null");
        return -1;
    }

    // 構造插入數(shù)據
    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"));

    // 插入數(shù)據庫
    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;
}
  • batchInsert()
    該方法為批量插入方法,接收一個ValuesBucket數(shù)組用于單次插入一組對象。它的作用是提高插入多條重復數(shù)據的效率。該方法系統(tǒng)已實現(xiàn),開發(fā)者可以直接調用。
  • delete()
    該方法用來執(zhí)行刪除操作。刪除條件由類DataAbilityPredicates構建,服務端在接收到該參數(shù)之后可以從中解析出要刪除的數(shù)據,然后到數(shù)據庫中執(zhí)行。根據傳入的條件刪除用戶表數(shù)據的代碼示例如下:
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;
}
  • update()
    此方法用來執(zhí)行更新操作。用戶可以在ValuesBucket參數(shù)中指定要更新的數(shù)據,在DataAbilityPredicates中構建更新的條件等。更新用戶表的數(shù)據的代碼示例如下:
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;
}
  • executeBatch()
    此方法用來批量執(zhí)行操作。DataAbilityOperation中提供了設置操作類型、數(shù)據和操作條件的方法,用戶可自行設置自己要執(zhí)行的數(shù)據庫操作。該方法系統(tǒng)已實現(xiàn),開發(fā)者可以直接調用。

說明
上述代碼示例中,初始化了數(shù)據庫類BookStore.class,并通過實體類User.class對該數(shù)據庫的表User進行增刪改查操作。
關于對象關系映射數(shù)據庫的具體邏輯,以及示例中BookStore.class與User.class的邏輯關系,可參考“對象關系映射數(shù)據庫開發(fā)指導”。

注冊UserDataAbility

和Service類似,開發(fā)者必須在配置文件中注冊Data。
配置文件中該字段在創(chuàng)建Data Ability時會自動創(chuàng)建,name與創(chuàng)建的Data Ability一致。
需要關注以下屬性:

  • type: 類型設置為data
  • uri: 對外提供的訪問路徑,全局唯一
  • permissions: 訪問該data ability時需要申請的訪問權限
    說明
    如果權限非系統(tǒng)權限,需要在配置文件中進行自定義。請參考權限開發(fā)指導中關于“自定義權限”的相關說明。
{
    "name": ".UserDataAbility",
     "type": "data",
     "visible": true,
     "uri": "dataability://com.example.myapplication5.DataAbilityTest",
     "permissions": [
        "com.example.myapplication5.DataAbility.DATA"
     ]
}

訪問Data

開發(fā)者可以通過DataAbilityHelper類來訪問當前應用或其他應用提供的共享數(shù)據。DataAbilityHelper作為客戶端,與提供方的Data進行通信。Data接收到請求后,執(zhí)行相應的處理,并返回結果。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"
    }
]

創(chuàng)建DataAbilityHelper

DataAbilityHelper為開發(fā)者提供了creator()方法來創(chuàng)建DataAbilityHelper實例。該方法為靜態(tài)方法,有多個重載。最常見的方法是通過傳入一個context對象來創(chuàng)建DataAbilityHelper對象。

獲取helper對象示例:

DataAbilityHelper helper = DataAbilityHelper.creator(this);

訪問Data Ability

DataAbilityHelper為開發(fā)者提供了一系列的接口來訪問不同類型的數(shù)據(文件、數(shù)據庫等)。

  • 訪問文件
    DataAbilityHelper為開發(fā)者提供了FileDescriptor openFile(Uri uri, String mode)方法來操作文件。此方法需要傳入兩個參數(shù),其中uri用來確定目標資源路徑,mode用來指定打開文件的方式,可選方式包含“r”(讀), “w”(寫), “rw”(讀寫),“wt”(覆蓋寫),“wa”(追加寫),“rwt”(覆蓋寫且可讀)。
    該方法返回一個目標文件的FD(文件描述符),把文件描述符封裝成流,開發(fā)者就可以對文件流進行自定義處理。
    訪問文件示例:
// 讀取文件描述符
FileDescriptor fd = helper.openFile(uri, "r");
FileInputStream fis = new FileInputStream(fd);
// 使用文件描述符封裝成的文件流,進行文件操作
  • 訪問數(shù)據庫
    DataAbilityHelper為開發(fā)者提供了增、刪、改、查以及批量處理等方法來操作數(shù)據庫。
    說明
    對數(shù)據庫的操作方法,詳見數(shù)據管理中各數(shù)據庫類型的開發(fā)指南。
方法 描述
ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) 查詢數(shù)據庫
int insert(Uri uri, ValuesBucket value) 向數(shù)據庫中插入單條數(shù)據
int batchInsert(Uri uri, ValuesBucket[] values) 向數(shù)據庫中插入多條數(shù)據
int delete(Uri uri, DataAbilityPredicates predicates) 刪除一條或多條數(shù)據
int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) 更新數(shù)據庫
DataAbilityResult[] executeBatch(ArrayList<DataAbilityOperation> operations) 批量操作數(shù)據庫

這些方法的使用說明如下:

  • query()
    查詢方法,其中uri為目標資源路徑,columns為想要查詢的字段。開發(fā)者的查詢條件可以通過DataAbilityPredicates來構建。查詢用戶表中id在101-103之間的用戶,并把結果打印出來,代碼示例如下:
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());
  • insert()
    新增方法,其中uri為目標資源路徑,ValuesBucket為要新增的對象。插入一條用戶信息的代碼示例如下:
DataAbilityHelper helper = DataAbilityHelper.creator(this);

// 構造插入數(shù)據
ValuesBucket valuesBucket = new ValuesBucket();
valuesBucket.putString("name", "Tom");
valuesBucket.putInteger("age", 12);
helper.insert(uri, valuesBucket);
  • batchInsert()
    批量插入方法,和insert()類似。批量插入用戶信息的代碼示例如下:
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 構造插入數(shù)據
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);
  • delete()
    刪除方法,其中刪除條件可以通過DataAbilityPredicates來構建。刪除用戶表中id在101-103之間的用戶,代碼示例如下:
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 構造刪除條件
DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.between("userId", 101, 103);
helper.delete(uri, predicates);
  • update()
    更新方法,更新數(shù)據由ValuesBucket傳入,更新條件由DataAbilityPredicates來構建。更新id為102的用戶,代碼示例如下:
DataAbilityHelper helper = DataAbilityHelper.creator(this);
// 構造更新條件
DataAbilityPredicates predicates = new DataAbilityPredicates();
predicates.equalTo("userId", 102);
// 構造更新數(shù)據
ValuesBucket valuesBucket = new ValuesBucket();
valuesBucket.putString("name", "Tom");
valuesBucket.putInteger("age", 12);
helper.update(uri, valuesBucket, predicates);
  • executeBatch()
    此方法用來執(zhí)行批量操作。DataAbilityOperation中提供了設置操作類型、數(shù)據和操作條件的方法,開發(fā)者可自行設置自己要執(zhí)行的數(shù)據庫操作。插入多條數(shù)據的代碼示例如下:
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開發(fā),有以下示例工程可供參考:

  • DataAbility
    本示例演示了如何使用Data Ability對數(shù)據庫進行增、刪、改、查,以及讀取文本文件。
    針對Data Ability開發(fā),有以下Codelabs可供參考:

  • 關系型數(shù)據庫
    基于Data Ability的關系型數(shù)據庫和數(shù)據管理能力,實現(xiàn)數(shù)據庫相關應用服務的快速開發(fā)。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容