HarmonyOS 分布式新闻分享

系统 分布式 OpenHarmony
本篇Codelab中我们介绍了应用的主页面和详情页,在主页面可以通过顶部的新闻类型切换不同类别的新闻,同时下面整个新闻列表项也会跟随切换。

[[412557]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

1. 介绍

HarmonyOS支持应用以Ability为单位进行部署,Ability可以分为FA(Feature Ability)和PA(Particle Ability)两种类型,本篇Codelab将会使用到Page Ability以及Service Ability来进行开发,其中Page Ability是FA唯一支持的模板,用于提供与用户交互的能力,Service Ability是PA(Particle Ability)的一种,用于提供后台运行任务的能力。除此之外,您还将使用到HarmonyOS中的常用控件如:ListContainer,Image等,以及跨设备拉起FA的能力来共同实现一个基于分布式的HarmonyOS简易新闻客户端。

最终效果预览

我们最终会构建一个简易的HarmonyOS新闻客户端。应用包含两级页面,分别是主页面和详情页面,两个页面都展示了丰富的HarmonyOS组件,其中详情页的实现逻辑中还展示了如何通过调用相应接口,实现跨设备拉起FA。本篇Codelab我们将会一起完成这个客户端,其中包括:

1.顶部ListContainer以及新闻列表ListContainer

2.每条新闻的文本框以及图像

3.布局及页面跳转

4.设备发现以及跨设备拉起FA

HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区

2. 搭建HarmonyOS环境

安装DevEco Studio,详情请参考DevEco Studio下载。

设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:

如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。

如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。

说明:

如需要在手机中运行程序,则需要提前申请证书,如使用模拟器可忽略。

准备密钥和证书请求文件

申请调试证书

你可以通过如下设备完成Codelab:

开启开发者模式的HarmonyOS真机

DevEco Studio中的手机模拟器(模拟器暂不支持分布式调试)

3. 代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在参考中提供下载方式,接下来我们会用一小节来讲解整个工程的代码结构:

  • INewsDemoIDL.idl:存放在entry\src\main\idl\com\huawei\newsdemo目录下,接口中定义了tranShare方法用来实现不同设备之间的通信。
  • bean:NewsInfo封装了新闻信息,NewsType封装了新闻类型。
  • provider:DevicesListProvider,NewsListProvider,NewsTypeProvider,分别为设备列表,主页新闻列表以及新闻类型的provider,主要作用为高效传递和使用相关数据。
  • slice:NewsListAbilitySlice,NewsDetailAbilitySlice分别为进入应用的主页面和详情页面,同时里面也展现了我们大部分的逻辑实现。
  • utils:存放所有封装好的公共方法,如CommonUtils,DialogUtils等。
  • NewsAbility:动态权限的申请以及页面路由信息处理。
  • SharedService:供远端连接的Service Ability。
  • manager:该目录下的文件为INewsDemoIDL.idl在编译时自行生成,初始生成位置为entry\build\generated\source\idl\com\huawei\newsdemo。
  • resources:存放工程使用到的资源文件,其中resources\base\layout下存放xml布局文件;resources\base\media下存放图片资源;resources\rawfile下存放应用使用的新闻数据json文件。
  • config.json:配置文件
HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区

4. 添加主页顶部新闻类型

首先为我们的应用添加顶部新闻类型,用于切换不同类别的新闻,我们会使用到ListContainer控件,有关ListContainer的更多知识,可以参考HarmonyOS JAVA通用组件。

首先需要在布局文件中对控件进行声明,在resources\base\layout\news_list_layout.xml布局文件中有如下代码:

  1. <ListContainer  
  2.          
  3. ohos:id="$+id:selector_list"  
  4.          
  5. ohos:width="match_parent"  
  6.          
  7. ohos:height="40vp"  
  8.          
  9. ohos:orientation="horizontal"  
  10.          
  11. /> 

 此外我们还定义了selectorListContainer变量进行关联,在NewsListAbilitySlice.java的initView()方法中有如下代码:

  1. selectorListContainer = (ListContainer) findComponentById(ResourceTable.Id_selector_list); 

添加监听

在切换不同类别新闻的时候,下面展示的新闻列表项会跟随切换,所以我们需要为这个ListContainer设置一个监听,在NewsListAbilitySlice.java的initListener()方法中添加:

  1. selectorListContainer.setItemClickedListener(  
  2.     (listContainer, component, position, id) -> {  
  3.                 // 设置选中后的放大效果  
  4.         setCategorizationFocus(false);  
  5.         selectText = (Text) component.findComponentById(ResourceTable.Id_news_type_text);  
  6.         setCategorizationFocus(true);  
  7.         newsDataList.clear();  
  8.         for (NewsInfo mTotalNewsData : totalNewsDataList) {  
  9.             if (selectText.getText().equals(mTotalNewsData.getType()) || id == 0) {  
  10.                 newsDataList.add(mTotalNewsData);  
  11.             }  
  12.         }  
  13.         updateListView();  
  14.     }); 

声明NewsTypeProvider

为了方便我们的应用更加高效和便捷的使用数据,我们将应用中用到的新闻数据事先预置在resources/rawfile目录下的两个json文件中,此外我们还声明了一些Provider,便于数据的获取和传递,其中获取新闻类别的NewsTypeProvider如下:

  1. @Override  
  2. public Component getComponent(int position, Component component, ComponentContainer componentContainer) {  
  3.     ViewHolder viewHolder;  
  4.     Component temp = component;  
  5.     if (temp == null) {  
  6.         temp = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_news_type_layout, nullfalse);  
  7.         // 将所有子组件通过ViewHolder绑定到列表项实例  
  8.         viewHolder = new ViewHolder();  
  9.         viewHolder.title = (Text) temp.findComponentById(ResourceTable.Id_news_type_text);  
  10.         component.setTag(viewHolder);  
  11.     } else {  
  12.         viewHolder = (ViewHolder) temp.getTag();  
  13.     }  
  14.     viewHolder.title.setText(mNewsTypeList.get(position).getName());  
  15.     return temp;  

我们定义了initData方法来解析json文件中的新闻数据,并将这些数据传递给provider,在NewsListAbilitySlice.java的initData()添加如下代码:

  1. private void initData() {  
  2.     Gson gson = new Gson();  
  3.     List<NewsType> newsTypeList =  
  4.             gson.fromJson(  
  5.                     CommonUtils.getStringFromJsonPath(this, "entry/resources/rawfile/news_type_datas.json"),  
  6.                     new TypeToken<List<NewsType>>(){ }.getType());  
  7.     newsTypeProvider = new NewsTypeProvider(newsTypeList, this);  

添加切换效果

在切换不同类别新闻的时候,增加了一个放大效果,在setCategorizationFocus()中添加如下代码:

  1. private void setCategorizationFocus(boolean isFocus) {  
  2.     if (selectText == null) {  
  3.         return;  
  4.     }  
  5.     if (isFocus) {  
  6.         selectText.setTextColor(  
  7.                 new Color(CommonUtils.getColor(NewsListAbilitySlice.this, ResourceTable.Color_news_type_text_on)));  
  8.         selectText.setScaleX(FOCUS_TEXT_SIZE);  
  9.         selectText.setScaleY(FRCUS_TEXT_SIZE);  
  10.     } else {  
  11.         selectText.setTextColor(  
  12.                 new Color(CommonUtils.getColor(NewsListAbilitySlice.this, ResourceTable.Color_news_type_text_off)));  
  13.         selectText.setScaleX(UNFOCUS_TEXT_SIZE);  
  14.         selectText.setScaleY(UNFOCUS_TEXT_SIZE);  
  15.     } 

所以在进行类别切换的时候,将会得到如下效果:

HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区

5. 添加主页新闻列表项

新闻列表项布局

主页面的布局除了有上方的顶部栏,还由下方的新闻列表项构成,整个新闻列表项是一个ListContainer,同样我们先来看看在new_list_layout.xml中是如何定义的:

  1. <ListContainer  
  2.         ohos:id="$+id:news_container"  
  3.         ohos:width="match_parent"  
  4.         ohos:height="match_parent"/> 

整个新闻列表项由多个新闻item构成,每个item又由标题和图片构成,每个item在item_news_layout.xml布局中是这样定义的:

  1. <DirectionalLayout  
  2.     ohos:height="109.5vp"  
  3.     ohos:width="match_parent"  
  4.     ohos:orientation="horizontal"  
  5.     ohos:padding="10vp">  
  6.     <Text  
  7.         ohos:id="$+id:item_news_title"  
  8.         ohos:height="match_content"  
  9.         ohos:width="0vp"  
  10.         ohos:max_text_lines="3"  
  11.         ohos:multiple_lines="true"  
  12.         ohos:right_padding="20vp"  
  13.         ohos:text_size="18vp"  
  14.         ohos:weight="3"/>  
  15.     <Image  
  16.         ohos:id="$+id:item_news_image"  
  17.         ohos:height="match_parent"  
  18.         ohos:width="0vp"  
  19.         ohos:scale_mode="stretch"  
  20.         ohos:weight="2"/>  
  21. </DirectionalLayout> 

声明NewsListProvider

和顶部新闻类型一样,每个新闻item中的title和image也是利用provider传递的,在NewsListProvider.java中有如下代码:

  1. @Override  
  2. public Component getComponent(int position, Component component, ComponentContainer componentContainer) {  
  3.     ViewHolder viewHolder;  
  4.     Component temp = component;  
  5.     if (temp == null) {  
  6.         component = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_item_news_layout, nullfalse);  
  7.         // 将所有子组件通过ViewHolder绑定到列表项实例  
  8.         viewHolder = new ViewHolder();  
  9.         viewHolder.title = (Text) temp.findComponentById(ResourceTable.Id_item_news_title);  
  10.         viewHolder.image = (Image) temp.findComponentById(ResourceTable.Id_item_news_image);  
  11.         temp.setTag(viewHolder);  
  12.     } else {  
  13.         viewHolder = (ViewHolder) temp.getTag();  
  14.     }  
  15.     viewHolder.title.setText(newsInfoList.get(i).getTitle());  
  16.     viewHolder.image.setPixelMap(CommonUtils.getPixelMapFromPath(context, newsInfoList.get(i).getImgUrl()));  
  17.     return temp;  

同样,newsListProvider的数据也是在initData的时候进行赋值的,所以需要在NewsListAbilitySlice的initData()中添加:

  1. totalNewsDataList =  
  2.         gson.fromJson(  
  3.                 CommonUtils.getStringFromJsonPath(this, "entry/resources/rawfile/news_datas.json"),  
  4.                 new TypeToken<List<NewsInfo>>(){ }.getType());  
  5. newsDataList = new ArrayList<>();  
  6. newsDataList.addAll(totalNewsDataList);  
  7. newsListProvider = new NewsListProvider(newsDataList, this); 

到此我们完成了数据的加载和解析,接下来是为item添加点击事件。

添加监听

我们点击某个具体新闻item的时,应用会跳转到全局详情页面,这时要为新闻item添加一个监听,在NewsListAbilitySlice.java的initListener()中添加:

  1. newsListContainer.setItemClickedListener(  
  2.         (listContainer, component, position, id) -> {  
  3.             Intent intent = new Intent();  
  4.             Operation operation =  
  5.                     new Intent.OperationBuilder()  
  6.                             .withBundleName(getBundleName())  
  7.                             .withAbilityName(NewsAbility.class.getName())  
  8.                             .withAction("action.detail")  
  9.                             .build();  
  10.             intent.setOperation(operation);  
  11.             intent.setParam(NewsDetailAbilitySlice.INTENT_TITLE, newsDataList.get(position).getTitle());  
  12.             intent.setParam(NewsDetailAbilitySlice.INTENT_READ, newsDataList.get(position).getReads());  
  13.             intent.setParam(NewsDetailAbilitySlice.INTENT_LIKE, newsDataList.get(position).getLikes());  
  14.             intent.setParam(NewsDetailAbilitySlice.INTENT_CONTENT, newsDataList.get(position).getContent());  
  15.             intent.setParam(NewsDetailAbilitySlice.INTENT_IMAGE, newsDataList.get(position).getImgUrl());  
  16.             startAbility(intent);  
  17.         }); 

这里的startAbility()是我们页面跳转的关键方法,参数intent里面存放了要跳转的bundle name,ability name,详情页面的title,imgurl等重要参数。

6. 详情页页面布局

新闻详情页的布局相比于新闻主页稍微有些复杂,整体由DependentLayout布局嵌套DirectionalLayout布局、ScrollView和其他控件构成,我们把整体页面分为顶部,底部,和中部。并在resources\base\layout\new_detail_laylout.xml中实现详情页的布局。

顶部

顶部是由DirectionalLayout加上Text组件构成,分别对应了左侧的图标和NewsDemo以及右侧的reads和likes,实现效果及布局部分代码如下:

HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区
  1. <DirectionalLayout  
  2.         ohos:width="match_parent"  
  3.         ohos:height="match_content"  
  4.         ohos:alignment="vertical_center"  
  5.         ohos:orientation="horizontal">  
  6.     <Text  
  7.             ohos:id="$+id:title_icon"  
  8.             ohos:width="match_content"  
  9.             ohos:height="match_content"  
  10.             ohos:weight="1"  
  11.             ohos:text="NewsDemo"  
  12.             ohos:text_size="20fp"/>  
  13.     <Text  
  14.             ohos:id="$+id:read_num"  
  15.             ohos:width="match_content"  
  16.             ohos:height="match_content"  
  17.             ohos:text_size="10fp"  
  18.             ohos:right_margin="10vp"/>  
  19.     <Text  
  20.             ohos:id="$+id:like_num"  
  21.             ohos:width="match_content"  
  22.             ohos:height="match_content"  
  23.             ohos:text_size="10fp"/>  
  24. </DirectionalLayout> 

中部

页面的中间部分由新闻标题Text,缩略图Image,新闻内容Text构成,实现效果及布局部分代码如下:

HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区
  1. <Text  
  2.         ohos:id="$+id:title_text"  
  3.         ohos:width="match_parent"  
  4.         ohos:height="match_content"  
  5.         ohos:text_size="18fp"  
  6.         ohos:max_text_lines="4"  
  7.         ohos:multiple_lines="true"  
  8.         ohos:text_color="#000000"  
  9.         ohos:top_margin="10vp"/>  
  10. <Image  
  11.     ohos:id="$+id:image_content"  
  12.     ohos:width="match_parent"  
  13.     ohos:scale_mode="stretch"  
  14.     ohos:height="300vp"  
  15.     ohos:top_margin="10vp"/>  
  16. <Text  
  17.         ohos:id="$+id:title_content"  
  18.         ohos:width="match_parent"  
  19.         ohos:height="match_content"  
  20.         ohos:multiple_lines="true"  
  21.         ohos:text_color="#708090"  
  22.         ohos:text_size="16vp"  
  23.         ohos:text_alignment="center_horizontal"  
  24.         ohos:top_margin="5vp"/> 

底部

页面的底部由DirectionalLayout加上TextField和Image控件构成,对应输入评论和几个按钮,具体效果和部分布局代码如下:

HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区
  1. <DirectionalLayout  
  2.         ohos:id="$+id:bottom_layout"  
  3.         ohos:align_parent_bottom="true"  
  4.         ohos:width="match_parent"  
  5.         ohos:height="50vp"  
  6.         ohos:orientation="horizontal"  
  7.         ohos:background_element="#ffffff"  
  8.         ohos:alignment="vertical_center"  
  9.         ohos:left_padding="20vp"  
  10.         ohos:right_padding="20vp"  
  11.         >  
  12.     <TextField  
  13.             ohos:id="$+id:text_file"  
  14.             ohos:width="160vp"  
  15.             ohos:height="30vp"  
  16.             ohos:left_padding="5vp"  
  17.             ohos:right_padding="10vp"  
  18.             ohos:text_alignment="vertical_center"  
  19.             ohos:text_size="15vp"  
  20.             ohos:hint="Enter a comment."  
  21.             ohos:background_element="$graphic:corner_bg_comment"/>  
  22.     <Image  
  23.             ohos:id="$+id:button1"  
  24.             ohos:width="20vp"  
  25.             ohos:height="20vp"  
  26.             ohos:image_src="$media:message_icon"  
  27.             ohos:scale_mode="stretch"  
  28.             ohos:left_margin="20vp"/>  
  29.     <Image  
  30.             ohos:id="$+id:button2"  
  31.             ohos:width="20vp"  
  32.             ohos:height="20vp"  
  33.             ohos:image_src="$media:collect_icon"  
  34.             ohos:scale_mode="stretch"  
  35.             ohos:left_margin="20vp"/>  
  36.     <Image  
  37.             ohos:id="$+id:button3"  
  38.             ohos:width="20vp"  
  39.             ohos:height="20vp"  
  40.             ohos:image_src="$media:like_icon"  
  41.             ohos:scale_mode="stretch"  
  42.             ohos:left_margin="20vp"/>  
  43.     <Image  
  44.             ohos:id="$+id:button4"  
  45.             ohos:width="20vp"  
  46.             ohos:height="20vp"  
  47.             ohos:image_src="$media:share_icon"  
  48.             ohos:scale_mode="stretch"  
  49.             ohos:left_margin="20vp"/>  
  50. </DirectionalLayout> 

7. 详情页数据初始化

接受来自NewsListAbilitySlice页面的数据

我们在添加新闻列表项那一节中说明了新闻页面的title,imgurl等重要参数是如何存放的,现在我们一起看下在详情页是如何获取的。在NewsDetailAbilitySlice.java的onStart()中有如下代码:

  1. public void onStart(Intent intent) {  
  2.     super.onStart(intent);  
  3.     super.setUIContent(ResourceTable.Layout_news_detail_layout);  
  4.     reads = intent.getStringParam(INTENT_READ);  
  5.     likes = intent.getStringParam(INTENT_LIKE);  
  6.     title = intent.getStringParam(INTENT_TITLE);  
  7.     content = intent.getStringParam(INTENT_CONTENT);  
  8.     image = intent.getStringParam(INTENT_IMAGE);  

之前存放在intent中的参数,现在在onStart()中逐一进行取出。

布局和控件的初始化

除了需要声明xml来实现布局以外,还需要在NewsDetailAbilitySlice.java的onStart()中添加initView()方法进行初始化:

  1. private void initView() {  
  2.     parentLayout = (DependentLayout) findComponentById(ResourceTable.Id_parent_layout);  
  3.     commentFocus = (TextField) findComponentById(ResourceTable.Id_text_file);  
  4.     iconShared = (Image) findComponentById(ResourceTable.Id_button4);  
  5.     Text newsRead = (Text) findComponentById(ResourceTable.Id_read_num);  
  6.     Text newsLike = (Text) findComponentById(ResourceTable.Id_like_num);  
  7.     Text newsTitle = (Text) findComponentById(ResourceTable.Id_title_text);  
  8.     Text newsContent = (Text) findComponentById(ResourceTable.Id_title_content);  
  9.     Image newsImage = (Image) findComponentById(ResourceTable.Id_image_content);  
  10.     newsRead.setText("reads: " + reads);  
  11.     newsLike.setText("likes: " + likes);  
  12.     newsTitle.setText("Original title: " + title);  
  13.     newsContent.setText(content);  
  14.     newsImage.setPixelMap(CommonUtils.getPixelMapFromPath(this, image));  

添加监听

我们在点击页面底部右下角的分享按钮的时候,会进行设备发现操作,并将发现的设备列表进行展示,此处我们设置了两个监听,在NewsDetailAbilitySlice.java的onStart()中添加initListener():

  1. private void initListener() {  
  2.     parentLayout.setTouchEventListener(  
  3.             (component, touchEvent) -> {  
  4.                 if (commentFocus.hasFocus()) {  
  5.                     commentFocus.clearFocus();  
  6.                 }  
  7.                 return true;  
  8.             });  
  9.     iconShared.setClickedListener(  
  10.             v -> {  
  11.                 initDevices();  
  12.                 showDeviceList();  
  13.             });  

parentLayout的监听事件用来监听触控焦点是否在设备列表Dialog上,iconShared的监听事件用来监听分享按钮被是否被点击。

HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区

8. 设备发现

上一节我们了解到当分享按钮被点击的时候会触发监听,进行设备发现,那么触发监听后,是如何进行设备发现的?

在initListener()中有两个有关设备发现的方法:initDevices()和showDeviceList()。initDevices()方法调用接口实现设备发现,并将发现到的设备存储到List中,需要如下代码实现:

  1. private void initDevices() {  
  2.     if (devices.size() > 0) {  
  3.         devices.clear();  
  4.     }  
  5.     List<DeviceInfo> deviceInfos =  
  6.             DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE);  
  7.     devices.addAll(deviceInfos);  

发现到的设备,通过Dialog进行显示,您可以选择一个目标设备进行跨设备流转,需要在NewsDetailAbilitySlice.java的showDeviceList()中添加如下代码:

  1. private void showDeviceList() {  
  2.     // 设备列表dialog  
  3.     dialog = new CommonDialog(NewsDetailAbilitySlice.this);  
  4.     dialog.setAutoClosable(true);  
  5.     dialog.setTitleText("HarmonyOS devices");  
  6.     dialog.setSize(DIALOG_SIZE_WIDTH, DIALOG_SIZE_HEIGHT);  
  7.     ListContainer devicesListContainer = new ListContainer(getContext());  
  8.     DevicesListAdapter devicesListProvider = new DevicesListProvider(devices, this);  
  9.     devicesListContainer.setItemProvider(devicesListAdapter);  
  10.     devicesListContainer.setItemClickedListener(  
  11.             (listContainer, component, position, id) -> {  
  12.                 dialog.destroy()  
  13.                 // 跨设备拉起FA  
  14.                 startAbilityFA(devices.get(position).getDeviceId());  
  15.             });  
  16.     devicesListAdapter.notifyDataChanged();  
  17.     dialog.setContentCustomComponent(devicesListContainer);  
  18.     dialog.show();  
HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区

当我们选择某个设备的时候,被选择的设备会拉起指定的FA页面,被拉起的FA页面会和发起请求的那一端保持一致。

9. 跨设备协同

连接Service Ability

那么跨设备协同又是如何实现的?发现的设备列表也是通过一个ListContainer来展示的,设备列表也有对应的xml和变量声明,这里不再赘述。对于每一个设备item,我们添加了监听用来进行跨设备拉起FA,需要在NewsDetailAbilitySlice的showDeviceList()中添加startAlibityFA()方法,具体代码如下:

  1. private void startAbilityFA(StringdevicesId) {  
  2.     Intent intent = new Intent();  
  3.     Operation operation =  
  4.             new Intent.OperationBuilder()  
  5.                     .withDeviceId(devicesId)  
  6.                     .withBundleName(getBundleName())  
  7.                     .withAbilityName(SharedService.class.getName())  
  8.                     // 该FLAG用于分布式跨设备场景  
  9.                     .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE)  
  10.                     .build();  
  11.     intent.setOperation(operation);  
  12.     boolean connectFlag =  
  13.             // 连接远端 Service Ability  
  14.             connectAbility(  
  15.                     intent,  
  16.                     new IAbilityConnection() {  
  17.                         @Override  
  18.                         public void onAbilityConnectDone(  
  19.                                 ElementName elementName, IRemoteObject iRemoteObject, int i) {  
  20.                             INewsDemoIDL sharedManager = NewsDemoIDLStub.asInterface(iRemoteObject);  
  21.                             try {  
  22.                                 sharedManager.tranShare(title, reads, likes, content, image);  
  23.                             } catch (RemoteException e) {  
  24.                                 LogUtil.i(TAG, "connect successful,but have remote exception");  
  25.                             }  
  26.                         }  
  27.                         @Override  
  28.                         public void onAbilityDisconnectDone(ElementName elementName, int i) {  
  29.                             disconnectAbility(this);  
  30.                         }  
  31.                     });  
  32.     DialogUtil.toast(  
  33.             this, connectFlag ? "Sharing succeeded!" : "Sharing failed. Please try again later.", WAIT_TIME);  

方法中我们为intent设置了bundlename,abilityname,devicesId等参数,通过connectAbility方法实现与远端Service Ability进行连接,连接成功后,会在onAbilityConnectDone中调用tranShare方法将对端需要的数据传递过去。

远端Service Ability的定义

本端通过connectAbility连接远端的Service Ability,那么远端的Service Ability又是如何定义的?需要在SharedService.java中添加tranShare()方法,代码如下:

  1. public void tranShare(String title, String reads, String likes, String content, String image) {  
  2.     Intent intent = new Intent();  
  3.     Operation operation =  
  4.             new Intent.OperationBuilder()  
  5.                     .withBundleName(getBundleName())  
  6.                     .withAbilityName(NewsAbility.class.getName())  
  7.                     .withAction("action.detail")  
  8.                     .build();  
  9.     intent.setOperation(operation);  
  10.     intent.setParam(NewsDetailAbilitySlice.INTENT_TITLE, title);  
  11.     intent.setParam(NewsDetailAbilitySlice.INTENT_READ, reads);  
  12.     intent.setParam(NewsDetailAbilitySlice.INTENT_LIKE, likes);  
  13.     intent.setParam(NewsDetailAbilitySlice.INTENT_CONTENT, content);  
  14.     intent.setParam(NewsDetailAbilitySlice.INTENT_IMAGE, image);  
  15.     startAbility(intent); 

说明:

以上代码仅demo演示参考使用

这样便通过startAbility方法拉起了指定的FA,并将intent携带的参数一并传递过去。

—-结束

当前实现远程启动FA,需要至少两个设备处于同一个分布式网络中,可以通过操作如下配置实现:

所有设备接入同一网络,

所有设备登陆相同华为账号,

所有设备上开启"设置->更多连接->多设备协同 "

10. 回顾和总结

在本篇Codelab中我们介绍了应用的主页面和详情页,在主页面可以通过顶部的新闻类型切换不同类别的新闻,同时下面整个新闻列表项也会跟随切换。点击下方某个具体新闻item的时候,会进行跳转到新闻详情页面;在新闻详情页可以上下滑动查看新闻,并且点击下方分享按钮可以实现FA的跨设备协同,整体效果如下图1和图2:

HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区
HarmonyOS 分布式新闻分享-鸿蒙HarmonyOS技术社区

11. 恭喜你

目前你已经成功完成了Codelab并且学到了:

如何使用ListContainer等常用控件

如何进行布局编写及页面跳转

如何进行设备发现以及FA的跨设备协同

12. 参考

gitee源码

github源码

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-07-22 10:20:21

鸿蒙HarmonyOS应用

2020-09-29 19:20:05

鸿蒙

2020-11-06 12:12:35

HarmonyOS

2021-05-28 09:52:00

鸿蒙HarmonyOS应用

2021-12-13 11:07:10

鸿蒙HarmonyOS应用

2023-01-13 07:39:07

2021-10-21 10:03:09

鸿蒙HarmonyOS应用

2021-11-16 09:38:10

鸿蒙HarmonyOS应用

2022-07-15 16:26:58

Java分布式

2019-10-10 09:16:34

Zookeeper架构分布式

2021-12-02 10:11:44

鸿蒙HarmonyOS应用

2021-12-10 15:06:56

鸿蒙HarmonyOS应用

2021-08-16 09:55:41

鸿蒙HarmonyOS应用

2017-09-01 05:35:58

分布式计算存储

2023-05-29 14:07:00

Zuul网关系统

2019-06-19 15:40:06

分布式锁RedisJava

2021-12-14 14:47:18

鸿蒙HarmonyOS应用

2021-01-21 09:45:36

鸿蒙HarmonyOS分布式

2010-06-03 18:54:57

Hadoop

2013-03-01 09:55:28

负载均衡分布式存储集群
点赞
收藏

51CTO技术栈公众号