当前位置:   article > 正文

HarmonyOS实战—Page Ability简介及各种操作:页面跳转、跨设备迁移

HarmonyOS实战—Page Ability简介及各种操作:页面跳转、跨设备迁移

Harmony OS 2 Page Ability

Page Ability

一个Page可以由一个或多个AbilitySlice构成,AbilitySlice是指应用的单个页面及其控制逻辑的总和。

当一个Page由多个AbilitySlice共同构成时,这些AbilitySlice页面提供的业务能力应具有高度相关性。

Page Ability基本概念

AbilitySlice路由配置

虽然一个Page可以包含多个AbilitySlice,但是Page进入前台时界面默认只展示一个AbilitySlice。默认展示的AbilitySlice是通过setMainRoute()方法来指定的。如果需要更改默认展示的AbilitySlice,可以通过addActionRoute()方法为此AbilitySlice配置一条路由规则。此时,当其他Page实例期望导航到此AbilitySlice时,可以在Intent中指定Action,详见下文的不同Page间导航

示例

src/main/java/com/example/harmonyos01java/slice/MainAbilitySlice.java

public class MainAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());

        addActionRoute("action.second", SecondAbilitySlice.class.getName());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

src/main/config.json

addActionRoute()方法中使用的动作命名,需要在应用配置文件(config.json)中注册

{
    "module": {
        "abilities": [
            {
                "skills":[
                    {
                        "actions":[
                            "action.system.home",
                            "action.second"
                        ]
                    }
                ],
                "name": "com.example.harmonyos01java.MainAbility",
                "page": "page"
                ...
            }
        ]
        ...
    }
    ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Page Ability生命周期

系统管理或用户操作等行为均会引起Page实例在其生命周期的不同状态之间进行转换。Ability类提供的回调机制能够让Page及时感知外界变化,从而正确地应对状态变化(比如释放资源),这有助于提升应用的性能和稳健性。

这一部分我不进行太多的描述

Page生命周期回调

这里我们借用一下官方文档的一张图

img

非常直观的表现了Page的若干个状态

  • INITIAL
    • onStart前
    • onStop后
  • INACTIVE
    • onStart后
    • onInactice后(Page失去焦点执行:即 返回键、或者 另一个Ability到前台 时)
    • onForeground后 (Page处于BACKGROUND状态重新回到前台时)
  • ACTIVE
    • onActive后(Page来到前台 时)
  • BACKGROUND
    • onBackground后 (Page不再对用户可见 时)
AbilitySlice生命周期

AbilitySlice作为Page的组成单元,其生命周期是依托于其所属Page生命周期的,AbilitySlice生命周期回调与Page的相应回调类似,因此不再赘述。

AbilitySlice和Page具有相同的生命周期状态和同名的回调,当Page生命周期发生变化时,它的AbilitySlice也会发生相同的生命周期变化。此外,AbilitySlice还具有独立于Page的生命周期变化,这发生在同一Page中的AbilitySlice之间导航时,此时Page的生命周期状态不会改变。

Page与AbilitySlice生命周期关联

Page和AbilitySlice的生命周期很多时候都是一致的,值得注意的是他们都需要编写他们的onStart方法

  • Page:开发者必须重写onStart回调,并在此配置默认展示的AbilitySlice
  • AbilitySlice:开发者必须重写AbilitySlice的onStart()回调,并在此方法中通过setUIContent()方法设置页面

当AbilitySlice处于前台且具有焦点时,其生命周期状态随着所属Page的生命周期状态的变化而变化。当一个Page拥有多个AbilitySlice时,例如:MyAbility下有FooAbilitySlice和BarAbilitySlice,当前FooAbilitySlice处于前台并获得焦点,并即将导航到BarAbilitySlice,在此期间的生命周期状态变化顺序为:

  1. FooAbilitySlice(原前台AbilitySlice)从ACTIVE状态变为INACTIVE状态。
  2. BarAbilitySlice(原非前台AbilitySlice)则从INITIAL状态首先变为INACTIVE状态,然后变为ACTIVE状态(假定此前BarAbilitySlice未曾启动)。
  3. FooAbilitySlice(原前台AbilitySlice)从INACTIVE状态变为BACKGROUND状态。

对应两个slice的生命周期方法回调顺序为:

FooAbilitySlice.onInactive() --> BarAbilitySlice.onStart() --> BarAbilitySlice.onActive() --> FooAbilitySlice.onBackground()

在整个流程中,MyAbility始终处于ACTIVE状态。但是,当Page被系统销毁时,其所有已实例化的AbilitySlice将联动销毁,而不仅是处于前台的AbilitySlice。

AbilitySlice间导航

同一Page内导航

当发起导航的AbilitySlice和导航目标的AbilitySlice处于同一个Page时,您可以通过present()方法实现导航。

这个也是我们上一个博客中有用到的

 @Override
public void onStart(Intent intent) {
    super.onStart(intent);
    super.setUIContent(ResourceTable.Layout_ability_main);

    Button button = (Button) findComponentById(ResourceTable.Id_button);

    // 点击按钮跳转至第二个页面
    button.setClickedListener(listener -> present(new SecondAbilitySlice(), new Intent()));

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如果开发者希望在用户从导航目标AbilitySlice返回时,能够获得其返回结果,则应当使用presentForResult()实现导航。用户从导航目标AbilitySlice返回时,系统将回调onResult()来接收和处理返回结果,开发者需要重写该方法。返回结果由导航目标AbilitySlice在其生命周期内通过**setResult()**进行设置。

@Override
protected void onStart(Intent intent) {

    ...
    Button button = ...;
    button.setClickedListener(listener -> presentForResult(new TargetSlice(), new Intent(), 0));
    ...

}

@Override
protected void onResult(int requestCode, Intent resultIntent) {
    if (requestCode == 0) {
        // Process resultIntent here.
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在我的理解下requestCode是用来辨别不同的接受请求的AbilitySlice的,

值得注意的是,系统为每个Page维护了一个AbilitySlice实例的栈,每个进入前台的AbilitySlice实例均会入栈。当开发者在调用present()或presentForResult()时指定的AbilitySlice实例已经在栈中存在时,则栈中位于此实例之上的AbilitySlice均会出栈并终止其生命周期。

不同Page内导航

AbilitySlice作为Page的内部单元,以Action的形式对外暴露,因此可以通过配置Intent的Action导航到目标AbilitySlice。Page间的导航可以使用**startAbility()startAbilityForResult()**方法,获得返回结果的回调为onAbilityResult()。在Ability中调用setResult()可以设置返回结果。

这里我们尝试着制作一个demo

  1. 新建一个新java项目(第二个)

  2. src/main/java/xxx.xxx/slice下新建一个SecondAbilitySlice类,使其继承于AbilitySlice类

  3. src/main/java/xxx.xxx下新建一个SecondAbility类,使其继承于Ability类

  4. src/main/resources/base/layout新建一个ability_second.xml的Layout Resource File

  5. src/main/resources/base/graphic新建一个background_button.xml的Graphic Resourse File

  6. 修改src/main/resources/base/element/string.jsonsrc/main/resources/base/en.element/string.json

    {
      "string": [
        {
          "name": "entry_MainAbility",
          "value": "entry_MainAbility"
        },
        {
          "name": "mainability_description",
          "value": "Java_Empty Ability"
        },
        {
          "name": "entry_SecondAbility",
          "value": "entry_SecondAbility"
        },
        {
          "name": "secondability_description",
          "value": "Java_Empty Ability"
        },
        {
          "name": "string_tip_to_jump",
          "value": "Press the button to jump"
        },
        {
          "name": "string_tip_jump_success",
          "value": "Jump success"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    修改src/main/resources/base/zh.element/string.json

    {
      "string": [
        {
          "name": "entry_MainAbility",
          "value": "entry_MainAbility"
        },
        {
          "name": "mainability_description",
          "value": "Java_Empty Ability"
        },
        {
          "name": "entry_SecondAbility",
          "value": "entry_SecondAbility"
        },
        {
          "name": "secondability_description",
          "value": "Java_Empty Ability"
        },
        {
          "name": "string_tip_to_jump",
          "value": "按下按钮以跳转"
        },
        {
          "name": "string_tip_jump_success",
          "value": "跳转成功"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  7. 我们需要在config.json中添加HAP包的配置信息

    {
      "app": {
        ...
      },
      "deviceConfig": {},
      "module": {
        ...
        "abilities": [
          {
            "skills": [
              {
                "entities": [
                  "entity.system.home"
                ],
                "actions": [
                  "action.system.home"
                ]
              }
            ],
            "orientation": "unspecified",
            "name": "com.example.harmonyos02pagenavigator.MainAbility",
            "icon": "$media:icon",
            "description": "$string:mainability_description",
            "label": "$string:entry_MainAbility",
            "type": "page",
            "launchType": "standard"
          },
          {
            "skills": [
              {
                "entities": [
                  "entity.system.home"
                ],
                "actions": [
                  "action.system.home",
                  "action.second"
                ]
              }
            ],
            "orientation": "unspecified",
            "name": "com.example.harmonyos02pagenavigator.SecondAbility",
            "icon": "$media:icon",
            "description": "$string:secondability_description",
            "label": "$string:entry_SecondAbility",
            "type": "page",
            "launchType": "standard"
          }
        ]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  8. 添加完毕后我们开始编写前面新建的几个空类

    SecondAbilitySlice

    package com.example.harmonyos02pagenavigator.slice;
    
    import com.example.harmonyos02pagenavigator.ResourceTable;
    import ohos.aafwk.ability.AbilitySlice;
    import ohos.aafwk.content.Intent;
    
    public class SecondAbilitySlice extends AbilitySlice {
        @Override
        public void onStart(Intent intent) {
            super.onStart(intent);
            super.setUIContent(ResourceTable.Layout_ability_second);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    SecondAbility

    package com.example.harmonyos02pagenavigator;
    
    import com.example.harmonyos02pagenavigator.slice.MainAbilitySlice;
    import com.example.harmonyos02pagenavigator.slice.SecondAbilitySlice;
    import ohos.aafwk.ability.Ability;
    import ohos.aafwk.content.Intent;
    
    public class SecondAbility extends Ability {
        @Override
        protected void onStart(Intent intent) {
            super.onStart(intent);
            super.setMainRoute(SecondAbilitySlice.class.getName());
    
            addActionRoute("action。second",SecondAbilitySlice.class.getName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  9. 开始编写前面新建的几个新xml

    ability_second.xml

    <?xml version="1.0" encoding="utf-8"?>
    <DependentLayout
        xmlns:ohos="http://schemas.huawei.com/res/ohos"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:orientation="vertical">
        <Text
            ohos:id="$+id:string_jump_success"
            ohos:width="match_content"
            ohos:height="match_content"
            ohos:text="$string:string_tip_jump_success"
            ohos:text_color="#000000"
            ohos:text_size="32fp"
            ohos:center_in_parent="true"/>
    </DependentLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    background_button.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape
        xmlns:ohos="http://schemas.huawei.com/res/ohos"
        ohos:shape="rectangle">
        <corners
            ohos:radius="100"/>
        <solid
            ohos:color="#007DFF"/>
    </shape>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  10. 修改已经存在的layout ability_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <DirectionalLayout
        xmlns:ohos="http://schemas.huawei.com/res/ohos"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="vertical">
    
        <Button
            ohos:id="$+id:button_jump"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:text_color="#FFFFFF"
            ohos:text="$string:string_tip_to_jump"
            ohos:padding="8vp"
            ohos:left_padding="50vp"
            ohos:right_padding="50vp"
            ohos:background_element="$graphic:background_button"
            ohos:layout_alignment="horizontal_center"
            ohos:text_size="25vp"
            />
    
    </DirectionalLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  11. 修改已经存在的类

    src/main/java/xxx.xxx/slice/MainAbilitySlice

    package com.example.harmonyos02pagenavigator.slice;
    
    import com.example.harmonyos02pagenavigator.ResourceTable;
    import ohos.aafwk.ability.AbilitySlice;
    import ohos.aafwk.content.Intent;
    import ohos.aafwk.content.Operation;
    import ohos.agp.components.Button;
    
    public class MainAbilitySlice extends AbilitySlice {
        @Override
        public void onStart(Intent intent) {
            super.onStart(intent);
            super.setUIContent(ResourceTable.Layout_ability_main);
    
            Button button = (Button) findComponentById(ResourceTable.Id_button_jump);
    
            Intent secondIntent = new Intent();
            Operation operation = new Intent.OperationBuilder().withAction("action.second").build();
            secondIntent.setOperation(operation);
            button.setClickedListener(listener -> startAbility(secondIntent));
        }
    
        @Override
        public void onActive() {
            super.onActive();
        }
    
        @Override
        public void onForeground(Intent intent) {
            super.onForeground(intent);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
  12. 运行测试

在这里插入图片描述

在这里插入图片描述

跨设备迁移

跨设备迁移(下文简称“迁移”)支持将Page在同一用户的不同设备间迁移,以便支持用户无缝切换的诉求。以Page从设备A迁移到设备B为例,迁移动作主要步骤如下:

  1. 设备A上的Page请求迁移。
  2. HarmonyOS处理迁移任务,并回调设备A上Page的保存数据方法,用于保存迁移必须的数据。
  3. HarmonyOS在设备B上启动同一个Page,并回调其恢复数据方法。

在这里插入图片描述

看上去十分复杂的东西,官方文档却不是很长,官方应该是觉得这个部分不会特别难,所以我决定做一个demo来熟悉这个技术

  1. 新建Java Phone Application项目

  2. 修改string.json

    src/main/resources/base/element/string.jsonsrc/main/resources/base/zh.element/string.json

    {
      "string": [
        {
          "name": "entry_MainAbility",
          "value": "跨设备迁移"
        },
        {
          "name": "mainability_description",
          "value": "Java_Empty Ability"
        },
        {
          "name": "mainability_tip",
          "value": "输入内容以跨设备迁移"
        },
        {
          "name": "mainability_button",
          "value": "跨设备迁移"
        },
        {
          "name": "mainability_success",
          "value": "跨设备成功"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    src/main/resources/base/element/en.string.json

    {
      "string": [
        {
          "name": "entry_MainAbility",
          "value": "Cross-equipment migration"
        },
        {
          "name": "mainability_description",
          "value": "Java_Empty Ability"
        },
        {
          "name": "mainability_tip",
          "value": "Enter content migrate across equipment"
        },
        {
          "name": "mainability_button",
          "value": "cross-equipment migration"
        },
        {
          "name": "mainability_success",
          "value": "success"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
  3. 修改config.json

    • 添加跨设备迁移权限

      {
        ...
        "module": {
          ...
          "reqPermissions": [
            {
              "name": "ohos.permission.DISTRIBUTED_DATASYNC"
            }
          ]
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
  4. 修改ability_background.xml (ui修改)

    <DirectionalLayout
        xmlns:ohos="http://schemas.huawei.com/res/ohos"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ohos:alignment="center"
        ohos:orientation="vertical">
        <TextField
            ohos:id="$+id:message_textfield"
            ohos:height="match_content"
            ohos:width="300vp"
            ohos:hint="$string:mainability_tip"
            ohos:left_margin="24vp"
            ohos:padding="5vp"
            ohos:background_element="$graphic:background_text_field"
            ohos:text_alignment="center"
            ohos:right_margin="24vp"
            ohos:text_size="16vp"/>
    
        <Button
            ohos:id="$+id:button_jump"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:text_color="#FFF"
            ohos:text="$string:mainability_button"
            ohos:top_margin="30vp"
            ohos:padding="8vp"
            ohos:left_padding="50vp"
            ohos:right_padding="50vp"
            ohos:background_element="$graphic:background_button"
            ohos:layout_alignment="horizontal_center"
            ohos:text_size="15vp"
            />
    
    </DirectionalLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  5. 新建两个Graphic Resource File

    background_text_field.xml

    <shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
           ohos:shape="rectangle">
        <corners
            ohos:radius="200"/>
        <solid
            ohos:color="#0d000000"/>
        <stroke
            ohos:color="#33000000"
            ohos:width="0.4vp"/>
    </shape>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    background_button.xml

    <?xml version="1.0" encoding="utf-8"?>
    <shape
        xmlns:ohos="http://schemas.huawei.com/res/ohos"
        ohos:shape="rectangle">
        <corners
            ohos:radius="100"/>
        <solid
            ohos:color="#007DFF"/>
    </shape>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  6. 使MainAbility实现IAbilityContinuation

    几乎没有什么实现

    package com.example.harmonyos02cemigration;
    
    import com.example.harmonyos02cemigration.slice.MainAbilitySlice;
    import ohos.aafwk.ability.Ability;
    import ohos.aafwk.ability.IAbilityConnection;
    import ohos.aafwk.ability.IAbilityContinuation;
    import ohos.aafwk.content.Intent;
    import ohos.aafwk.content.IntentParams;
    import ohos.bundle.IBundleManager;
    import ohos.security.SystemPermission;
    
    public class MainAbility extends Ability implements IAbilityContinuation {
        @Override
        public void onStart(Intent intent) {
            super.onStart(intent);
            super.setMainRoute(MainAbilitySlice.class.getName());
            requestPermissions();
        }
    
        /**
         *
         */
        private void requestPermissions() {
            if (verifySelfPermission(SystemPermission.DISTRIBUTED_DATASYNC) != IBundleManager.PERMISSION_GRANTED) {
                requestPermissionsFromUser(new String[] {SystemPermission.DISTRIBUTED_DATASYNC}, 0);
            }
        }
    
        /**
         * Page请求迁移后,系统首先回调此方法,开发者可以在此回调中决策当前是否可以执行迁移,
         * 比如,弹框让用户确认是否开始迁移。
         * @return 
         */
        @Override
        public boolean onStartContinuation() {
            //return false;
            return true;
        }
    
        /**
         * 如果onStartContinuation()返回true,则系统回调此方法,
         * 开发者在此回调中保存必须传递到另外设备上以便恢复Page状态的数据。
         * @param intentParams 用于保存数据的一个结构类似于map的数据结构
         * @return
         */
        @Override
        public boolean onSaveData(IntentParams intentParams) {
            //return false;
            return true;
        }
    
        /**
         * 源侧设备上Page完成保存数据后,系统在目标侧设备上回调此方法,
         * 开发者在此回调中接受用于恢复Page状态的数据。注意,在目标侧设备上的Page会重新启动其生命周期,
         * 无论其启动模式如何配置。且系统回调此方法的时机在onStart()之前。
         * @param intentParams 用于恢复数据的一个结构类似于map的数据结构
         * @return
         */
        @Override
        public boolean onRestoreData(IntentParams intentParams) {
            //return false;
            return true;
        }
    
        /**
         * 目标侧设备上恢复数据一旦完成,系统就会在源侧设备上回调Page的此方法,
         * 以便通知应用迁移流程已结束。开发者可以在此检查迁移结果是否成功,
         * 并在此处理迁移结束的动作,例如,应用可以在迁移完成后终止自身生命周期。
         * @param i
         */
        @Override
        public void onCompleteContinuation(int i) {
            terminateAbility();
        }
    
        /**
         * 如果开发者使用continueAbilityReversibly()而不是continueAbility(),
         * 则此后可以在源侧设备上使用reverseContinueAbility()进行回迁。这种场景下,
         * 相当于同一个Page(的两个实例)同时在两个设备上运行,迁移完成后,如果目标侧设备上Page因任何原因终止,
         * 则源侧Page通过此回调接收终止通知。
         */
        @Override
        public void onRemoteTerminated() {
            terminateAbility();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
  7. 使MainAbilitySlice实现IAbilityContinuation

    由于顺序是

    1. a方 b方安装好app

    2. a方打开app

    3. a方app申请跨设备迁跃 答应

    4. a方输入数据

    5. a方触发开始跨设备迁跃

      1. onStartContinuation 开始迁跃
      2. onSaveData 保存数据 将输入的数据保存于传入的参数IntentParams(map)中
    6. b方自动打开app

    7. b方开始跨设备迁跃

      1. onRestoreData 恢复数据 通过传入的参数IntentParams(map)来恢复
      2. onStart 开始b方app的Ability的初始化
    8. a方继续跨设备迁跃

      • onCompleteContinuation 结束迁跃

    在本项目中,我们设计a方开始跨设备迁跃完毕后直接关闭项目(本项目在Ability中实现了,而非在AbilitySlice中实现),结束其生命周期,所以我们将内容重新显示位于b方app的Ability运行onStart时实现,用到b方 onRestoreData 获取到的参数,放入输入框中,在开始跨设备时保存数据

    package com.example.harmonyos02cemigration.slice;
    
    import com.example.harmonyos02cemigration.ResourceTable;
    import ohos.aafwk.ability.AbilitySlice;
    import ohos.aafwk.ability.IAbilityContinuation;
    import ohos.aafwk.content.Intent;
    import ohos.aafwk.content.IntentParams;
    import ohos.agp.components.Component;
    import ohos.agp.components.TextField;
    import ohos.agp.window.dialog.ToastDialog;
    import ohos.hiviewdfx.HiLog;
    
    public class MainAbilitySlice extends AbilitySlice implements IAbilityContinuation {
        private static final String INPUT_CONTENT = "input content";
        private TextField textField ;
    
        private String message;
        private boolean isContinued;
        @Override
        public void onStart(Intent intent) {
            super.onStart(intent);
            super.setUIContent(ResourceTable.Layout_ability_main);
            findComponentById(ResourceTable.Id_button_jump).setClickedListener(this::ceMigrate);
            textField = (TextField) findComponentById(ResourceTable.Id_message_textfield);
            if (isContinued && message != null) {
                textField.setText(message);
            }
        }
    
        private void ceMigrate(Component component){
            String messageSend = textField.getText();
            if (messageSend.isEmpty()) {
                new ToastDialog(this).setText("输入信息不为空").show();
                return;
            }
    
            try {
                continueAbility();
            } catch (IllegalStateException illegalStateException) {
                new ToastDialog(this).setText("发送失败").show();
                return;
            }
        }
    
        @Override
        public void onActive() {
            super.onActive();
        }
    
        @Override
        public void onForeground(Intent intent) {
            super.onForeground(intent);
        }
    
        @Override
        public boolean onStartContinuation() {
            return true;
        }
    
        @Override
        public boolean onSaveData(IntentParams intentParams) {
            intentParams.setParam(INPUT_CONTENT,textField.getText());
            return true;
        }
    
        @Override
        public boolean onRestoreData(IntentParams intentParams) {
            if (intentParams.getParam(INPUT_CONTENT) instanceof String) {
                message = (String) intentParams.getParam(INPUT_CONTENT);
                isContinued = true;
            }
            return true;
        }
    
        @Override
        public void onCompleteContinuation(int i) {
    
        }
    
        @Override
        public void onRemoteTerminated() {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
  8. 运行测试

    1. 两部手机都安装好这个app,打开a方的该app,询问是否允许使用多设备协同时点击始终允许

    在这里插入图片描述

    1. 输入一些数据在TextField中并点击跨设备迁移

    在这里插入图片描述

    1. b方手机成功打开,并且显示出a方的数据在这里插入图片描述

    2. 很快a方手机自动终止该app生命周期

    在这里插入图片描述
    【本文正在参与“有奖征文 | HarmonyOS征文大赛”活动】

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/252684
推荐阅读
相关标签
  

闽ICP备14008679号