HarmonyOS实战—Data Ability Intent概念以及各种常见操作

Data Ability

Data Ability基本概念

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

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

URI介绍

Data的提供方和使用方都通过URI(Uniform Resource Identifier)来标识一个具体的数据,例如数据库中的某个表或磁盘上的某个文件。HarmonyOS的URI仍基于URI通用标准,格式如下:

img

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

这里可以看到,由于本地设备的device id 为“”,所以在本地设备的URL中dateability后面有三个斜杠,这是值得注意的

创建Data

使用Data模板的Ability形式仍然是Ability,因此,开发者需要为应用添加一个或多个Ability的子类,来提供程序与其他应用之间的接口。Data为结构化数据和文件提供了不同API接口供用户使用,因此,开发者需要首先确定好使用何种类型的数据。本章节主要讲述了创建Data的基本步骤和需要使用的接口。

Data提供方可以自定义数据的增、删、改、查,以及文件打开等功能,并对外提供这些接口。

确定数据存储方式

确定数据的存储方式,Data支持以下两种数据形式:

  • 文件数据:如文本、图片、音乐等。
  • 结构化数据:如数据库等。
实现UserDataAbility

UserDataAbility用于接收其他应用发送的请求,提供外部程序访问的入口,从而实现应用间的数据访问。

要实现UserDataAbility,首先应当新建这么一个Data Ability

  1. 在这里插入图片描述

2.在这里插入图片描述

Data提供了文件存储和数据库存储两组接口供用户使用。

文件存储

开发者需要在Data中重写FileDescriptor openFile(Uri uri, String mode)方法来操作文件:uri为客户端传入的请求目标路径;mode为开发者对文件的操作选项,可选方式包含“r”(读), “w”(写), “rw”(读写)等。

示例

@Override
public FileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    for(String string : uri.getDecodedPathList()){
        HiLog.info(LABEL_LOG,"uri.getDecodedPathList().item : %{public}%",string);

    }
    File file = new File(uri.getDecodedPathList().get(0));
    //会不会和getDecodedQueryParams​()作用一致呢?
    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);
    }
    

    这里用到一个OrmContext类,这个类是对象关系映射(ORM)系统提供的一个接口,用于操作在OrmObject中定义的ORM数据库实体。应用程序可以使用此接口创建、检索、更新和删除数据库实体。

    参考文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/database-orm-guidelines-0000000000030063

    官方demo中的示例

    private RdbStore rdbStore;
    private StoreConfig config = StoreConfig.newDefaultConfig(Const.DB_NAME);
    private RdbOpenCallback rdbOpenCallback = new RdbOpenCallback() {
        @Override
        public void onCreate(RdbStore store) {
            store.executeSql(
                "create table if not exists " + Const.DB_TAB_NAME + " (userId integer primary key autoincrement, "
                + Const.DB_COLUMN_NAME + " text not null, " + Const.DB_COLUMN_AGE + " integer)");
            HiLog.info(LABEL_LOG, "%{public}s", "create a  new database");
        }
    
        @Override
        public void onUpgrade(RdbStore store, int oldVersion, int newVersion) {
            HiLog.info(LABEL_LOG, "%{public}s", "DataBase upgrade");
        }
    };
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        DatabaseHelper databaseHelper = new DatabaseHelper(this);
        rdbStore = databaseHelper.getRdbStore(config, 1, rdbOpenCallback, null);
    }
    

    这里用到一个RdbStore类,这个类是为关系型数据库提供了增删查改的方法,其中的openCallback参数(第三个)用于对数据库进行创建更新等等,最后一个参数resultSetHook貌似也是一个功能强大的参数,很可惜目前没搞懂,等到搞懂了我就回来更新这篇文章

    参考文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/database-relational-guidelines-0000000000030051

  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()

      该方法接收三个参数,分别是查询的目标路径,查询的列名,以及查询条件,查询条件由类DataAbilityPredicates构建。

    • insert()

      该方法接收两个参数,分别是插入的目标路径和插入的数据值。其中,插入的数据由ValuesBucket封装,服务端可以从该参数中解析出对应的属性,然后插入到数据库中。此方法返回一个int类型的值用于标识结果。

    • batchInsert()

      该方法为批量插入方法,接收一个ValuesBucket数组用于单次插入一组对象。它的作用是提高插入多条重复数据的效率。该方法系统已实现,开发者可以直接调用

    • delete()

      该方法用来执行删除操作。删除条件由类DataAbilityPredicates构建,服务端在接收到该参数之后可以从中解析出要删除的数据,然后到数据库中执行。

    • update()

      此方法用来执行更新操作。用户可以在ValuesBucket参数中指定要更新的数据,在DataAbilityPredicates中构建更新的条件等。

    • executeBatch()

      此方法用来批量执行操作。DataAbilityOperation中提供了设置操作类型、数据和操作条件的方法,用户可自行设置自己要执行的数据库操作。该方法系统已实现,开发者可以直接调用

    这一部分涉及过多未学习的内容,就先不放代码

注册UserDataAbility

和Service类似,开发者必须在配置文件中注册Data。

配置文件中该字段在创建Data Ability时会自动创建,name与创建的Data Ability一致,这个是所有的Ability都需要做的配置。

需要关注以下属性:

  • type: 类型设置为data

  • uri: 对外提供的访问路径,全局唯一

  • permissions: 访问该data ability时需要申请的访问权限

    自定义权限的相关内容:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/security-permissions-guidelines-0000000000029886

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

访问Data

开发者可以通过DataAbilityHelper类来访问当前应用或其他应用提供的共享数据。DataAbilityHelper作为客户端,与提供方的Data进行通信。Data接收到请求后,执行相应的处理,并返回结果。DataAbilityHelper提供了一系列与Data Ability对应的方法。

声明使用权限

如果待访问的Data声明了访问需要权限,则访问此Data需要在配置文件中声明需要此权限(和服务端的permissions一致),如果待访问的Data Ability是由本应用创建,则可以不声明该权限

"reqPermissions": [
    {
        "name": "com.example.myapplication5.DataAbility.DATA"
    },
    // 访问文件还需要添加访问存储读写权限
    {
        "name": "ohos.permission.READ_USER_STORAGE"
    },
    {
        "name": "ohos.permission.WRITE_USER_STORAGE"
    }
]
创建DataAbilityHelper

DataAbilityHelper为开发者提供了creator()方法来创建DataAbilityHelper实例。该方法为静态方法,有多个重载。最常见的方法是通过传入一个context对象来创建DataAbilityHelper对象。

DataAbilityHelper helper = DataAbilityHelper.creator(this);
访问Data Ability

DataAbilityHelper为开发者提供了一系列的接口来访问不同类型的数据(文件、数据库等)

  • 访问文件

    DataAbilityHelper为开发者提供了FileDescriptor openFile(Uri uri, String mode)方法来操作文件。此方法需要传入两个参数,其中uri用来确定目标资源路径,mode用来指定打开文件的方式,可选方式包含“r”(读), “w”(写), “rw”(读写),“wt”(覆盖写),“wa”(追加写),“rwt”(覆盖写且可读)。

    该方法返回一个目标文件的FD(文件描述符),把文件描述符封装成流,开发者就可以对文件流进行自定义处理。

    // 读取文件描述符
    FileDescriptor fd = helper.openFile(uri, "r");
    FileInputStream fis = new FileInputStream(fd);
    
    // 使用文件描述符封装成的文件流,进行文件操作
    
  • 访问数据库

    DataAbilityHelper为开发者提供了增、删、改、查以及批量处理等方法来操作数据库。

    方法描述
    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()

      查询方法,其中uri为目标资源路径,columns为想要查询的字段。开发者的查询条件可以通过DataAbilityPredicates来构建。

    • insert()

      新增方法,其中uri为目标资源路径,ValuesBucket为要新增的对象。

    • batchInsert()

      批量插入方法,和insert()类似。

    • delete()

      删除方法,其中删除条件可以通过DataAbilityPredicates来构建。

    • update()

      更新方法,更新数据由ValuesBucket传入,更新条件由DataAbilityPredicates来构建。

    • executeBatch()

      此方法用来执行批量操作。DataAbilityOperation中提供了设置操作类型、数据和操作条件的方法,开发者可自行设置自己要执行的数据库操作。

示例

每一个部分都留有自己写的示例,是非常好的加深记忆、巩固知识的方法

  1. 新建Java Harmony OS 项目

  2. 使用Dev Eco Studio的功能,新建Data Ability

    检查config.json

    {
      ...,
      "module": {
        ...,
        "abilities": [
          ...,
          {
            "permissions": [
              "com.example.harmonyos02dataability.DataAbilityShellProvider.PROVIDER"
            ],
            "name": "com.example.harmonyos02dataability.DataAbility",
            "icon": "$media:icon",
            "description": "$string:dataability_description",
            "type": "data",
            "uri": "dataability://com.example.harmonyos02dataability.DataAbility"
          }
        ]
      }
    }
    
    1. 给Data Ability添加数据库相关常量

      //constant
      private static final String DB_NAME = "pokemondataability.db";
      
      private static final String DB_TAB_NAME = "pokemon";
      
      private static final String DB_COLUMN_PERSON_ID = "id";
      
      private static final String DB_COLUMN_NAME = "name";
      
      private static final int DB_VERSION = 1;
      
    2. 创建关系型数据库(RDB),给Data Ability添加以下代码

      //database config
      private StoreConfig config = StoreConfig.newDefaultConfig(DB_NAME);
      
      private RdbStore rdbStore;
      
      private RdbOpenCallback rdbOpenCallback = new RdbOpenCallback() {
          @Override
          public void onCreate(RdbStore store) {
              store.executeSql("create table if not exists "
                               + DB_TAB_NAME + " ("
                               + DB_COLUMN_PERSON_ID + " integer primary key, "
                               + DB_COLUMN_NAME + " text not null)");
          }
      
          @Override
          public void onUpgrade(RdbStore store, int oldVersion, int newVersion) {
          }
      };
      
    3. 初始化连接

      @Override
      public void onStart(Intent intent) {
          super.onStart(intent);
          HiLog.info(LABEL_LOG, "DataAbility onStart");
          DatabaseHelper databaseHelper = new DatabaseHelper(this);
          rdbStore = databaseHelper.getRdbStore(config,DB_VERSION,rdbOpenCallback,null);
      }
      
    4. 重写数据库操作方法 query、insert、delete、update

      @Override
      public ResultSet query(Uri uri, String[] columns, DataAbilityPredicates predicates) {
          //确定表和条件
          RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, DB_TAB_NAME);
          //确定字段、表和条件
          ResultSet resultSet = rdbStore.query(rdbPredicates, columns);
          if (resultSet == null) {
              HiLog.info(LABEL_LOG, "resultSet is null");
          }
          return resultSet;
      }
      
      @Override
      public int insert(Uri uri, ValuesBucket value) {
          HiLog.info(LABEL_LOG, "DataAbility insert");
          String path = uri.getLastPath();
          //判断path,当对多个表格进行操作时可以分支进行多种操作 (path 为 dataability://device_id/com.domainname.dataability.persondata/person/10 的 person)
          //且实际编码过程中还需要对操作异常进行处理,可捕获rdbStore.insert操作的异常,例如catch (DataAbilityRemoteException | IllegalStateException exception);
          if (!DB_TAB_NAME.equals(path)) {
              HiLog.info(LABEL_LOG, "DataAbility insert path is not matched");
              return -1;
          }
          ValuesBucket values = new ValuesBucket();
          values.putInteger(DB_COLUMN_PERSON_ID, value.getInteger(DB_COLUMN_PERSON_ID));
          values.putString(DB_COLUMN_NAME, value.getString(DB_COLUMN_NAME));
          int index = (int) rdbStore.insert(DB_TAB_NAME, values);
          //当表格数据插入成功时,可执行DataAbilityHelper.creator(this, uri).notifyChange(uri),通知该表格数据的订阅者
          DataAbilityHelper.creator(this, uri).notifyChange(uri);
          return index;
      }
      
      @Override
      public int delete(Uri uri, DataAbilityPredicates predicates) {
          //确定表和条件
          RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, DB_TAB_NAME);
          int index = rdbStore.delete(rdbPredicates);
          HiLog.info(LABEL_LOG, "delete: " + index);
          DataAbilityHelper.creator(this, uri).notifyChange(uri);
          return index;
      }
      
      @Override
      public int update(Uri uri, ValuesBucket value, DataAbilityPredicates predicates) {
          //确定表和条件
          RdbPredicates rdbPredicates = DataAbilityUtils.createRdbPredicates(predicates, DB_TAB_NAME);
          //确定字段、值、表和条件
          int index = rdbStore.update(value, rdbPredicates);
          HiLog.info(LABEL_LOG, "update: " + index);
          DataAbilityHelper.creator(this, uri).notifyChange(uri);
          return index;
      }
      

    可以看到得是,除了query()外每一个方法中都有一个DataAbilityHelper.creator(this, uri).notifyChange(uri);的代码,这个代码用于通知该表格数据的订阅者该表格发生了改变

  3. 添加访问Data Ability的代码,我们在MainAbilitySlice中添加对应代码

    1. 在添加代码之前,我们需要对config.json添加一些权限

      {
        ...,
        "module": {
          ...,
          "abilities": [
            ...,
            {
              ...,
              "permissions": [
                "com.example.harmonyos02dataability.DataAbilityShellProvider.PROVIDER"
              ],
              "uri": "dataability://com.example.harmonyos02dataability.DataAbility"
            }
          ],
          "reqPermissions": [
            {
              "name": "com.example.harmonyos02dataability.DataAbilityShellProvider.PROVIDER"
            }
          ]
        }
      }
      
    2. 创建DataAbilityHelper

       private DataAbilityHelper databaseHelper ;
      
      @Override
      public void onStart(Intent intent) {
          super.onStart(intent);
          super.setUIContent(ResourceTable.Layout_ability_main);
          databaseHelper =DataAbilityHelper.creator(this);
      }
      
    3. 添加数据库相关的常量

      //不能直接复制config.json里面的内容,在笔记中有提到,scheme后 , path前有一个authority字段,
      // 也就是设备id字段,由于是本地应用访问本地数据库,所以只需要在path前多加一个斜杠即可
      private static final String BASE_URI = "dataability:///com.example.harmonyos02dataability.DataAbility";
      
      private static final String DATA_PATH = "/pokemon";
      
      private static final String DB_COLUMN_PERSON_ID = "id";
      
      private static final String DB_COLUMN_NAME = "name";
      
    4. 添加数据库访问的代码

      private void queryAll(){
          String[] columns = new String[] {DB_COLUMN_PERSON_ID, DB_COLUMN_NAME};
          DataAbilityPredicates predicates = new DataAbilityPredicates();
          try {
              //确定查询的URI,(拼接转换),字段,条件
              ResultSet resultSet = databaseHelper.query(Uri.parse(BASE_URI + DATA_PATH),
                                                         columns, predicates);
              if (resultSet == null || resultSet.getRowCount() == 0) {
                  HiLog.info(LABEL_LOG, "query: resultSet is null or no result found");
                  return;
              }
              resultSet.goToFirstRow();
              do {
                  int id = resultSet.getInt(resultSet.getColumnIndexForName(DB_COLUMN_PERSON_ID));
                  String name = resultSet.getString(resultSet.getColumnIndexForName(DB_COLUMN_NAME));
                  HiLog.info(LABEL_LOG, "query: Id :" + id + " Name :" + name);
              } while (resultSet.goToNextRow());
          } catch (DataAbilityRemoteException | IllegalStateException exception) {
              HiLog.error(LABEL_LOG, "query: dataRemote exception | illegalStateException");
          }
      }
      
      private void query() {
          //确定字段
          String[] columns = new String[] {DB_COLUMN_PERSON_ID, DB_COLUMN_NAME};
          //构造查询条件
          DataAbilityPredicates predicates = new DataAbilityPredicates();
          //确定条件为 name = Pikachu
          predicates.equalTo("name","Pikachu");
          try {
              //确定查询的URI,(拼接转换),字段,条件
              ResultSet resultSet = databaseHelper.query(Uri.parse(BASE_URI + DATA_PATH),
                                                         columns, predicates);
              if (resultSet == null || resultSet.getRowCount() == 0) {
                  HiLog.info(LABEL_LOG, "query: resultSet is null or no result found");
                  return;
              }
              resultSet.goToFirstRow();
              do {
                  int id = resultSet.getInt(resultSet.getColumnIndexForName(DB_COLUMN_PERSON_ID));
                  String name = resultSet.getString(resultSet.getColumnIndexForName(DB_COLUMN_NAME));
                  HiLog.info(LABEL_LOG, "query: Id :" + id + " Name :" + name);
              } while (resultSet.goToNextRow());
          } catch (DataAbilityRemoteException | IllegalStateException exception) {
              HiLog.error(LABEL_LOG, "query: dataRemote exception | illegalStateException");
          }
      }
      
      private void insert(int id, String name) {
          //确定字段和值
          ValuesBucket valuesBucket = new ValuesBucket();
          valuesBucket.putInteger(DB_COLUMN_PERSON_ID, id);
          valuesBucket.putString(DB_COLUMN_NAME, name);
          try {
              //确定URI、字段和值
              if (databaseHelper.insert(Uri.parse(BASE_URI + DATA_PATH), valuesBucket) != -1) {
                  HiLog.info(LABEL_LOG, "insert successful");
              }
          } catch (DataAbilityRemoteException | IllegalStateException exception) {
              //由于数据库Person表格的Key值为DB_COLUMN_PERSON_ID,若插入数据时id对应的数据已经存在,将插入失败,需要进行异常捕获处理。
              HiLog.error(LABEL_LOG, "insert: dataRemote exception|illegalStateException");
          }
      }
      
      private void update() {
          //条件 id = 1时
          DataAbilityPredicates predicates = new DataAbilityPredicates();
          predicates.equalTo(DB_COLUMN_PERSON_ID, 1);
          ValuesBucket valuesBucket = new ValuesBucket();
          //name = Bulbasaur
          valuesBucket.putString(DB_COLUMN_NAME, "Bulbasaur");
          try {
              //确定URI、条件、字段和值
              if (databaseHelper.update(Uri.parse(BASE_URI + DATA_PATH), valuesBucket, predicates) != -1) {
                  HiLog.info(LABEL_LOG, "update successful");
              }
          } catch (DataAbilityRemoteException | IllegalStateException exception) {
              HiLog.error(LABEL_LOG, "update: dataRemote exception | illegalStateException");
          }
      }
      
      private void delete() {
          //条件 id = 100
          DataAbilityPredicates predicates = new DataAbilityPredicates()
              .equalTo(DB_COLUMN_PERSON_ID, 100);
          try {
              //确定URI、条件
              if (databaseHelper.delete(Uri.parse(BASE_URI + DATA_PATH), predicates) != -1) {
                  HiLog.info(LABEL_LOG, "delete successful");
              }
          } catch (DataAbilityRemoteException | IllegalStateException exception) {
              HiLog.error(LABEL_LOG, "delete: dataRemote exception | illegalStateException");
          }
      }
      
    5. 添加客户端的监控

      IDataAbilityObserver dataAbilityObserver;
      
      private void pokemonDatabaseObserver() {
          dataAbilityObserver = new IDataAbilityObserver() {
              @Override
              public void onChange() {
                  // 订阅者接收目标数据表格产生变化的通知,通过查询获取最新的数据
                  queryAll();
              }
          };
          // 根据uri指定订阅的数据表
          databaseHelper.registerObserver(Uri.parse(BASE_URI + DATA_PATH), dataAbilityObserver);
      }
      
    6. 在onStart添加测试代码

      @Override
      public void onStart(Intent intent) {
          super.onStart(intent);
          super.setUIContent(ResourceTable.Layout_ability_main);
          databaseHelper =DataAbilityHelper.creator(this);
          pokemonDatabaseObserver();
          query();
          insert(100, "Voltorb");
          insert(1, "Ivysaur");
          insert(25, "Pikachu");
          update();
          delete();
      }
      
  4. 测试

在这里插入图片描述

在这里插入图片描述

测试成功!

Intent

基本概念

Intent是对象之间传递信息的载体。例如,当一个Ability需要启动另一个Ability时,或者一个AbilitySlice需要导航到另一个AbilitySlice时,可以通过Intent指定启动的目标同时携带相关数据。Intent的构成元素包括Operation与Parameters,具体描述参见下表

属性子属性描述
OperationAction表示动作,通常使用系统预置Action,应用也可以自定义Action。例如IntentConstants.ACTION_HOME表示返回桌面动作。
Entity表示类别,通常使用系统预置Entity,应用也可以自定义Entity。例如Intent.ENTITY_HOME表示在桌面显示图标。
Uri表示Uri描述。如果在Intent中指定了Uri,则Intent将匹配指定的Uri信息,包括scheme, schemeSpecificPart, authority和path信息。
Flags表示处理Intent的方式。例如Intent.FLAG_ABILITY_CONTINUATION标记在本地的一个Ability是否可以迁移到远端设备继续运行。
BundleName表示包描述。如果在Intent中同时指定了BundleName和AbilityName,则Intent可以直接匹配到指定的Ability。
AbilityName表示待启动的Ability名称。如果在Intent中同时指定了BundleName和AbilityName,则Intent可以直接匹配到指定的Ability。
DeviceId表示运行指定Ability的设备ID。
Parameters-Parameters是一种支持自定义的数据结构,开发者可以通过Parameters传递某些请求所需的额外信息。

当Intent用于发起请求时,根据指定元素的不同,分为两种类型:

  • 如果同时指定了BundleName与AbilityName,则根据Ability的全称(例如“com.demoapp.FooAbility”)来直接启动应用。
  • 如果未同时指定BundleName和AbilityName,则根据Operation中的其他属性来启动应用。

Intent设置属性时,必须先使用Operation来设置属性。如果需要新增或修改属性,必须在设置Operation后再执行操作。

根据Ability的全称启动应用

Service Ability 中讲过

通过构造包含BundleName与AbilityName的Operation对象,可以启动一个Ability、并导航到该Ability。示例代码如下:

Intent intent = new Intent();

// 通过Intent中的OperationBuilder类构造operation对象,指定设备标识(空串表示当前设备)、应用包名、Ability名称
Operation operation = new Intent.OperationBuilder()
        .withDeviceId("")
        .withBundleName("com.demoapp")
        .withAbilityName("com.demoapp.FooAbility")
        .build();

// 把operation设置到intent中
intent.setOperation(operation);
startAbility(intent);

作为处理请求的对象,会在相应的回调方法中接收请求方传递的Intent对象。以导航到另一个Ability为例,导航的目标Ability可以在其onStart()回调的参数中获得Intent对象。

根据Opreation的其他属性启动应用

Page Ability 中讲过

有些场景下,开发者需要在应用中使用其他应用提供的某种能力,而不感知提供该能力的具体是哪一个应用。例如开发者需要通过浏览器打开一个链接,而不关心用户最终选择哪一个浏览器应用,则可以通过Operation的其他属性(除BundleName与AbilityName之外的属性)描述需要的能力。如果设备上存在多个应用提供同种能力,系统则弹出候选列表,由用户选择由哪个应用处理请求。以下示例展示使用Intent跨Ability查询天气信息。

请求方

在Ability中构造Intent以及包含Action的Operation对象,并调用startAbilityForResult()方法发起请求。然后重写onAbilityResult()回调方法,对请求结果进行处理。

private void queryWeather() {
    Intent intent = new Intent();
    Operation operation = new Intent.OperationBuilder()
            .withAction(Intent.ACTION_QUERY_WEATHER)
            .build();
    intent.setOperation(operation);
    startAbilityForResult(intent, REQ_CODE_QUERY_WEATHER);
}

@Override
protected void onAbilityResult(int requestCode, int resultCode, Intent resultData) {
    switch (requestCode) {
        case REQ_CODE_QUERY_WEATHER:
            // Do something with result.
            ...
            return;
        default:
            ...
    }
}

处理方

  1. 作为处理请求的对象,首先需要在配置文件中声明对外提供的能力,以便系统据此找到自身并作为候选的请求处理者。

    {
        "module": {
            ...
            "abilities": [
                {
                    ...
                    "skills":[
                        {
                            "actions":[
                                "ability.intent.QUERY_WEATHER"
                            ]
                        }
                    ]
                    ...
                }
            ]
            ...
        }
        ...
    }
    
  2. 在Ability中配置路由以便支持以此action导航到对应的AbilitySlice。

    @Override
    protected void onStart(Intent intent) {
        ...
        addActionRoute(Intent.ACTION_QUERY_WEATHER, DemoSlice.class.getName());
        ...
    }
    
  3. 在Ability中处理请求,并调用setResult()方法暂存返回结果。

    @Override
    protected void onActive() {
        ...
        Intent resultIntent = new Intent();
        setResult(0, resultIntent);   //0为当前Ability销毁后返回的resultCode。
        ...
    }
    
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值