Epidemic Service Assistant 疫情服务助手卡片

开发 前端
前段时间国内的新冠疫情又出现了一些波动,公司也要求每天上报健康码和行程码,就想着能不能用服务卡片做一个,于是就开始行动了,想着大体可以分成2步走,需要先设计UI,然后对接相关的接口。

[[422884]]

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

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

https://harmonyos.51cto.com

介绍

前段时间国内的新冠疫情又出现了一些波动,公司也要求每天上报健康码和行程码,就想着能不能用服务卡片做一个,于是就开始行动了,想着大体可以分成2步走,需要先设计UI,然后对接相关的接口,不过对接接口要麻烦一些,需要有相关的开放接口,目前还没实现。

搭建环境

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

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

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

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

效果展示

项目结构

Epidemic Service Assistant 疫情服务助手卡片-鸿蒙HarmonyOS技术社区

实现步骤

1.编写界面

ability_main.xml 主界面

这个界面会显示获取到城市,以及地区的风险等级,然后就是安康码和行程卡的入口。

Epidemic Service Assistant 疫情服务助手卡片-鸿蒙HarmonyOS技术社区

itinerary_card_slice.xml行程卡界面

行程卡的显示界面,上半部分是通过短信验证码获取行程信息,下半部分是显示获取到的行程信息。

Epidemic Service Assistant 疫情服务助手卡片-鸿蒙HarmonyOS技术社区

health_code_slice安康码界面

安康码的显示界面,上半部部分显示当前所在城市,下半部分显示获取的安康码信息,然后是一个行程卡的入口。

Epidemic Service Assistant 疫情服务助手卡片-鸿蒙HarmonyOS技术社区

form_image_with_info_date_card_2_2.xml 2x2的卡片界面

Epidemic Service Assistant 疫情服务助手卡片-鸿蒙HarmonyOS技术社区

form_image_with_info_date_card_2_4.xml 2x4的卡片界面

Epidemic Service Assistant 疫情服务助手卡片-鸿蒙HarmonyOS技术社区

2.编写启动应用代码

MainAbility.java

  1. /** 
  2.  * Card Main Ability 
  3.  */ 
  4. public class MainAbility extends Ability { 
  5.     private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x0D1001, "=>MainAbility"); 
  6.     //卡片规格编号 
  7.     private static final int DEFAULT_DIMENSION_2X2 = 2; 
  8.     private static final int DEFAULT_DIMENSION_2X4 = 3; 
  9.     //ACTION路由 
  10.     private final String ACTION_HEALTH_CODE = "action.custom.healthcode"
  11.     private final String ACTION_ITINERARY_CARD = "action.custom.itinerarycard"
  12.     //权限 
  13.     private String[] requestPermissions = {SystemPermission.LOCATION}; 
  14.     //卡片ID 
  15.     private long formId; 
  16.     //卡片信息 
  17.     private ProviderFormInfo formInfo; 
  18.     //二维码 
  19.     private QRCodeUtil qrCodeUtil; 
  20.  
  21.     //所在城市文本组件 
  22.     private Text regionText; 
  23.  
  24.     @Override 
  25.     public void onStart(Intent intent) { 
  26.         HiLog.info(LABEL, "onStart "); 
  27.         super.onStart(intent); 
  28.         super.setMainRoute(MainAbilitySlice.class.getName()); 
  29.         //必要的 
  30.         super.setUIContent(ResourceTable.Layout_ability_main); 
  31.         //添加ACTION路由 
  32.         addActionRoute(ACTION_HEALTH_CODE, HealthCodeSlice.class.getName()); 
  33.         addActionRoute(ACTION_ITINERARY_CARD, ItineraryCardSlice.class.getName()); 
  34.  
  35.         //向用户请求权限 
  36.         PermissionsUtils.getInstance(this).requestPermissions(this, requestPermissions); 
  37.  
  38.         //获取位置 
  39.         regionText = (Text) findComponentById(ResourceTable.Id_text_main_region); 
  40.         new LocationHelper().getMyLocation(getContext(), currentRegion -> { 
  41.             getUITaskDispatcher().asyncDispatch(() -> { 
  42.                 regionText.setText(currentRegion); 
  43.             }); 
  44.         }); 
  45.  
  46.     } 
  47.  
  48.     @Override 
  49.     protected ProviderFormInfo onCreateForm(Intent intent) { 
  50.         HiLog.info(LABEL, "创建卡片"); 
  51.         if (intent == null) { 
  52.             return new ProviderFormInfo(); 
  53.         } 
  54.         if (qrCodeUtil == null) { 
  55.             qrCodeUtil = new QRCodeUtil(this); 
  56.         } 
  57.  
  58.         // 获取卡片id 
  59.         if (intent.hasParameter(AbilitySlice.PARAM_FORM_IDENTITY_KEY)) { 
  60.             formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, -1); 
  61.         } else { 
  62.             HiLog.info(LABEL, "未获取到卡片id...."); 
  63.             return new ProviderFormInfo(); 
  64.         } 
  65.         HiLog.info(LABEL, "获取卡片id:" + formId); 
  66.         // 获取卡片名称 
  67.         String formName = "疫情助手"
  68.         if (intent.hasParameter(AbilitySlice.PARAM_FORM_NAME_KEY)) { 
  69.             formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY); 
  70.         } 
  71.         HiLog.info(LABEL, "获取卡片名称:" + formName); 
  72.         // 获取卡片规格 
  73.         int dimension = DEFAULT_DIMENSION_2X4; 
  74.         if (intent.hasParameter(AbilitySlice.PARAM_FORM_DIMENSION_KEY)) { 
  75.             dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X4); 
  76.         } 
  77.         Map<String, Integer> viewIdMap = new HashMap<>(); 
  78.  
  79.         HiLog.info(LABEL, "获取卡片规格:" + dimension); 
  80.         //获取卡片布局ID 
  81.         int layoutId = getLayoutId(dimension, viewIdMap); 
  82.  
  83.         HiLog.info(LABEL, "通过布局文件id实例化formInfo"); 
  84.         formInfo = new ProviderFormInfo(layoutId, this); 
  85.         // 存储卡片信息 
  86.         HiLog.info(LABEL, "存储卡片信息"); 
  87.         Form form = new Form(formId, formName, dimension); 
  88.  
  89.  
  90.         HiLog.info(LABEL, "根据Form实例化ComponentProvider"); 
  91.         ComponentProvider componentProvider = getComponentProvider(form, viewIdMap, layoutId, this); 
  92.  
  93.         HiLog.info(LABEL, "设置formInfo的 ComponentProvider 对象"); 
  94.         formInfo.mergeActions(componentProvider); 
  95.  
  96.         try { 
  97.             HiLog.info(LABEL, "通过DatabaseUtils保存Form信息到DB:" + form.toString()); 
  98.             DatabaseUtils.getInstance(this).insertForm(form); 
  99.         } catch (Exception e) { 
  100.             HiLog.info(LABEL, "发生异常,通过DatabaseUtils删除DB中的Form信息"); 
  101.             DatabaseUtils.getInstance(this).deleteFormData(form.getFormId()); 
  102.         } 
  103.         return formInfo; 
  104.     } 
  105.  
  106.     /** 
  107.      * @param dimension 卡片规格 
  108.      * @param viewIdMap 健康码/行程码所在布局ID 
  109.      * @return 
  110.      */ 
  111.     public int getLayoutId(int dimension, Map<String, Integer> viewIdMap) { 
  112.         viewIdMap.clear(); 
  113.         HiLog.info(LABEL, "getLayoutId"); 
  114.         int layoutId = 0; 
  115.         if (dimension == DEFAULT_DIMENSION_2X2) { 
  116.             HiLog.info(LABEL, "获取2*2的布局文件"); 
  117.             layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_2; 
  118.  
  119.             // 
  120.             viewIdMap.put(ACTION_HEALTH_CODE, ResourceTable.Id_layout_ankang_2x2); 
  121.         } else if (dimension == DEFAULT_DIMENSION_2X4) { 
  122.             HiLog.info(LABEL, "获取2*4的布局文件"); 
  123.             layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_4; 
  124.             // 
  125.             viewIdMap.put(ACTION_HEALTH_CODE, ResourceTable.Id_layout_ankang_2x4); 
  126.             viewIdMap.put(ACTION_ITINERARY_CARD, ResourceTable.Id_layout_itinerary_2x4); 
  127.         } 
  128.         return layoutId; 
  129.     } 
  130.  
  131.     /** 
  132.      * 获取卡片信息提供者对象 
  133.      * 
  134.      * @param form 
  135.      * @param viewIdMap 
  136.      * @param layoutId 
  137.      * @param context 
  138.      * @return 
  139.      */ 
  140.     public ComponentProvider getComponentProvider(Form form, Map<String, Integer> viewIdMap, int layoutId, Context context) { 
  141.         HiLog.info(LABEL, "getComponentProvider"); 
  142.         ComponentProvider componentProvider = new ComponentProvider(layoutId, context); 
  143.  
  144.         for (Map.Entry entry : viewIdMap.entrySet()) { 
  145.             String actionKey = (String) entry.getKey(); 
  146.             int viewId = (int) entry.getValue(); 
  147.             HiLog.info(LABEL, "actionKey = " + actionKey + ", viewId = " + viewId); 
  148.  
  149.             //设置组件值 
  150.             setComponentProviderValue(componentProvider, form); 
  151.             //设置跳转事件 
  152.             componentProvider.setIntentAgent(viewId, getIntentAgent(actionKey)); 
  153.         } 
  154.  
  155.         return componentProvider; 
  156.     } 
  157.  
  158.     /** 
  159.      * 设置卡片信息 
  160.      * 
  161.      * @param componentProvider 
  162.      * @param form 
  163.      */ 
  164.     private void setComponentProviderValue(ComponentProvider componentProvider, Form form) { 
  165.         //HiLog.debug(LABEL, "setComponentProviderValue,PixelMap:"+QRCodeUtil.getCurrentPixelMap()); 
  166.         try { 
  167.             if (form.getDimension() == DEFAULT_DIMENSION_2X2) { 
  168.                 HiLog.info(LABEL, "setComponentProviderValue2x2"); 
  169.                 componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity()); 
  170.                 //设置QR 
  171.                 componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, QRCodeUtil.getCurrentPixelMap()); 
  172.  
  173.             } else { 
  174.                 HiLog.info(LABEL, "setComponentProviderValue2x4"); 
  175.                 componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity()); 
  176.                 //设置安康码 
  177.                 componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, QRCodeUtil.getCurrentPixelMap()); 
  178.  
  179.                 //设置行程卡信息 
  180.                 componentProvider.setImageContent(ResourceTable.Id_image_itinerary_right, ResourceTable.Graphic_icon_itinerary); 
  181.  
  182.             } 
  183.         } catch (Exception e) { 
  184.             HiLog.error(LABEL, "setComponentProviderValueError:" + e.getMessage()); 
  185.             e.printStackTrace(); 
  186.         } 
  187.  
  188.     } 
  189.  
  190.     /** 
  191.      * 获取IntentAgent,事件控制对象 
  192.      * 
  193.      * @param ACTION 
  194.      * @return 
  195.      */ 
  196.     private IntentAgent getIntentAgent(String ACTION) { 
  197.         HiLog.info(LABEL, "getIntentAgent"); 
  198.         // 设置点击的跳转页面 
  199.         Intent intent = new Intent(); 
  200.         Operation operation = new Intent.OperationBuilder() 
  201.                 .withDeviceId(""
  202.                 .withBundleName(getBundleName()) 
  203.                 .withAbilityName(MainAbility.class) 
  204.                 .withAction(ACTION
  205.                 .build(); 
  206.         // 携带参数 
  207.         intent.setParam("formId", 1); 
  208.         intent.setOperation(operation); 
  209.         List<Intent> intentList = new ArrayList<>(); 
  210.         intentList.add(intent); 
  211.         // 对于不同的响应事件,第一个参数requestCode需要不同,此处用电影id设为requestCode 
  212.         IntentAgentInfo paramsInfo = new IntentAgentInfo(200, 
  213.                 IntentAgentConstant.OperationType.START_ABILITY, 
  214.                 IntentAgentConstant.Flags.UPDATE_PRESENT_FLAG, intentList, null); 
  215.         IntentAgent intentAgent = IntentAgentHelper.getIntentAgent(this, paramsInfo); 
  216.         HiLog.info(LABEL, "getIntentAgent:FINISH"); 
  217.         return intentAgent; 
  218.     } 
  219.  
  220.     /** 
  221.      * 用户删除卡片时会自动调用 
  222.      * 
  223.      * @param formId 
  224.      */ 
  225.     @Override 
  226.     protected void onDeleteForm(long formId) { 
  227.         super.onDeleteForm(formId); 
  228.         // 删除数据库中的卡片信息 
  229.         HiLog.info(LABEL, "删除DB中的Form信息:" + formId); 
  230.         DatabaseUtils.getInstance(this).deleteFormData(formId); 
  231.     } 
  232.  
  233.     @Override 
  234.     public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) { 
  235.         PermissionsUtils.getInstance(this).onRequestPermissionsResult(requestCode, permissions, grantResults); 
  236.     } 
  237.  

MainAbilitySlice.java

  1. /** 
  2.  * MainAbilitySlice 
  3.  */ 
  4. public class MainAbilitySlice extends AbilitySlice { 
  5.     private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001003, "=>MainAbilitySlice"); 
  6.  
  7.     @Override 
  8.     public void onStart(Intent intent) { 
  9.         HiLog.info(LABEL, "onStart"); 
  10.         super.onStart(intent); 
  11.         super.setUIContent(ResourceTable.Layout_ability_main); 
  12.         // 
  13.         initComponent(); 
  14.  
  15.         //初始化更新卡片服务 
  16.         startServiceAbility(); 
  17.     } 
  18.  
  19.     private void initComponent() { 
  20.         HiLog.info(LABEL, "initComponent"); 
  21.         // 
  22.         Component componentAnkang = findComponentById(ResourceTable.Id_text_bottom_card_ankang); 
  23.         Component componentItinerary = findComponentById(ResourceTable.Id_text_bottom_card_itinerary); 
  24.  
  25.         //跳转到健康码和行程卡页面 
  26.         componentAnkang.setClickedListener(listener -> present(new HealthCodeSlice(),new Intent())); 
  27.         componentItinerary.setClickedListener(listener -> present(new ItineraryCardSlice(), new Intent())); 
  28.  
  29.     } 
  30.  
  31.     /** 
  32.      * 启动更新卡片服务Ability 
  33.      */ 
  34.     private void startServiceAbility() { 
  35.         // 启动TimerAbility 
  36.         Intent intentService = new Intent(); 
  37.         Operation operation = 
  38.                 new Intent.OperationBuilder() 
  39.                         .withDeviceId(""
  40.                         .withBundleName(getBundleName()) 
  41.                         .withAbilityName(TimerAbility.class.getName()) 
  42.                         .build(); 
  43.         intentService.setOperation(operation); 
  44.         startAbility(intentService); 
  45.         HiLog.info(LABEL, "启动TimerAbility "); 
  46.     } 
  47.  
  48.     @Override 
  49.     public void onActive() { 
  50.         super.onActive(); 
  51.     } 
  52.  
  53.     @Override 
  54.     public void onForeground(Intent intent) { 
  55.         super.onForeground(intent); 
  56.     } 
  57.  
  58.     @Override 
  59.     protected void onStop() { 
  60.     } 
  61.  

TimerAbility.java

主要实现卡片的数据定时更新,代码如下:

  1. /** 
  2.  * 用于定时更新卡片的服务 
  3.  * Time PA 
  4.  */ 
  5. public class TimerAbility extends Ability { 
  6.     private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001003, "=>TimerAbility"); 
  7.     //卡片规格编号 
  8.     public static final int DEFAULT_DIMENSION_2X2 = 2; 
  9.     //卡片规格编号 
  10.     public static final int DEFAULT_DIMENSION_2X4 = 3; 
  11.  
  12.     //更新卡片周期:毫秒 
  13.     private static final long SEND_PERIOD = 10000L; 
  14.     private static final int QR_COLOR = 0xFF009900; 
  15.     //DB 帮助类 
  16.     private DatabaseHelper helper = new DatabaseHelper(this); 
  17.     //ORM上下文 
  18.     private OrmContext connect
  19.  
  20.     //二维码工具类 
  21.     private QRCodeUtil qrCodeUtil; 
  22.  
  23.     //全局定时器 
  24.     private Timer timer = null
  25.  
  26.     @Override 
  27.     public void onStart(Intent intent) { 
  28.         super.onStart(intent); 
  29.  
  30.         HiLog.info(LABEL, "初始化数据库连接"); 
  31.         connect = helper.getOrmContext("FormDatabase""FormDatabase.db", FormDatabase.class); 
  32.  
  33.         // 
  34.         qrCodeUtil = new QRCodeUtil(this); 
  35.  
  36.         // 
  37.         HiLog.info(LABEL, "启动定时"); 
  38.         startTimer(); 
  39.  
  40.     } 
  41.  
  42.     /** 
  43.      * 启动定时器,定期刷新卡片数据, 
  44.      * 一个卡片对应一个定时器 
  45.      */ 
  46.     private void startTimer() { 
  47.         /*if (timer != null) { 
  48.             timer.cancel(); 
  49.         }*/ 
  50.         timer = new Timer(); 
  51.         timer.schedule(new TimerTask() { 
  52.             @Override 
  53.             public void run() { 
  54.                 updateForms(); 
  55.             } 
  56.         }, 0, SEND_PERIOD); 
  57.     } 
  58.  
  59.     /** 
  60.      * 更细卡片数据 
  61.      */ 
  62.     private void updateForms() { 
  63.         // 从数据库中获取卡片信息 
  64.         HiLog.info(LABEL, "从数据库中获取卡片"); 
  65.         OrmPredicates ormPredicates = new OrmPredicates(Form.class); 
  66.         List<Form> formList = connect.query(ormPredicates); 
  67.         int layoutId = 0; 
  68.         // 更新时分秒 
  69.         if (formList.size() <= 0) { 
  70.             return
  71.         } 
  72.         HiLog.info(LABEL, "遍历卡片列表,逐个更新"); 
  73.         for (Form form : formList) { 
  74.             //获取卡片刷新的数据提供对象 
  75.             ComponentProvider componentProvider = getComponentProvider(form, this); 
  76.             try { 
  77.                 Long updateFormId = form.getFormId(); 
  78.                 HiLog.info(LABEL, "卡片ID[" + updateFormId + "]"); 
  79.  
  80.                 //更新卡片数据到数据库 
  81.                 boolean isSucc = updateForm(updateFormId, componentProvider); 
  82.                 HiLog.info(LABEL, "更新卡片数据完成," + isSucc); 
  83.  
  84.             } catch (FormException e) { 
  85.                 // 删除不存在的卡片 
  86.                 DatabaseUtils.getInstance(this).deleteFormData(form.getFormId()); 
  87.                 HiLog.error(LABEL, "更新卡片异常,删除数据库中不存在的卡片"); 
  88.             } 
  89.         } 
  90.     } 
  91.  
  92.     /** 
  93.      * Obtains the ComponentProvider object 
  94.      * 
  95.      * @param form    form info 
  96.      * @param context context 
  97.      * @return component provider 
  98.      */ 
  99.     public ComponentProvider getComponentProvider(Form form, Context context) { 
  100.         HiLog.info(LABEL, "getComponentProvider:" + form); 
  101.         //获取卡片规格 
  102.         int layoutId = getLayoutId(form.getDimension()); 
  103.         HiLog.info(LABEL, "layoutId:" + layoutId); 
  104.         ComponentProvider componentProvider = new ComponentProvider(layoutId, context); 
  105.  
  106.  
  107.         HiLog.info(LABEL, "更新卡片上组件的值"); 
  108.         setComponentProviderValue(componentProvider, form); 
  109.  
  110.         return componentProvider; 
  111.     } 
  112.  
  113.     /** 
  114.      * 获取对应规格的布局文件 
  115.      * 
  116.      * @param dimension 
  117.      * @return 
  118.      */ 
  119.     public int getLayoutId(int dimension) { 
  120.         HiLog.info(LABEL, "getLayoutId"); 
  121.         int layoutId = 0; 
  122.         if (dimension == DEFAULT_DIMENSION_2X2) { 
  123.             HiLog.info(LABEL, "获取2*2的布局文件"); 
  124.             layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_2; 
  125.         } 
  126.         if (dimension == DEFAULT_DIMENSION_2X4) { 
  127.             HiLog.info(LABEL, "获取2*4的布局文件"); 
  128.             layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_4; 
  129.         } 
  130.         return layoutId; 
  131.     } 
  132.  
  133.     /** 
  134.      * Set the value of componentProvider 
  135.      * 根据规格来更新卡片信息 
  136.      * 
  137.      * @param componentProvider component provider 
  138.      */ 
  139.     private void setComponentProviderValue(ComponentProvider componentProvider, Form form) { 
  140.         HiLog.info(LABEL, "setComponentProviderValue"); 
  141.         PixelMap pixels; 
  142.  
  143.         if (form.getDimension() == DEFAULT_DIMENSION_2X2) { 
  144.             HiLog.info(LABEL, "setComponentProviderValue2x2"); 
  145.             componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity()); 
  146.             //设置QR 
  147.             pixels = qrCodeUtil.generateColorQRCode(new Date().getTime() + "", QR_COLOR); 
  148.             componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, pixels); 
  149.  
  150.         } else { 
  151.             HiLog.info(LABEL, "setComponentProviderValue2x4"); 
  152.             componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity()); 
  153.             //设置QR 
  154.             pixels = qrCodeUtil.generateColorQRCode(new Date().getTime() + "", QR_COLOR); 
  155.             componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, pixels); 
  156.  
  157.             //设置行程卡信息 
  158.             componentProvider.setImageContent(ResourceTable.Id_image_itinerary_right, ResourceTable.Graphic_icon_itinerary); 
  159.  
  160.         } 
  161.     } 
  162.  
  163.     @Override 
  164.     public void onBackground() { 
  165.         super.onBackground(); 
  166.         HiLog.info(LABEL, "TimerAbility::onBackground"); 
  167.     } 
  168.  
  169.     @Override 
  170.     public void onStop() { 
  171.         super.onStop(); 
  172.         timer.cancel(); 
  173.         HiLog.info(LABEL, "TimerAbility::onStop"); 
  174.     } 

HealthCodeSlice.java

  1. public class HealthCodeSlice extends AbilitySlice { 
  2.     static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001005, "=>HealthCodeSlice"); 
  3.     private static final String accessToken = ""
  4.     /** 
  5.      * 随机定义生成不同颜色的二维码. 
  6.      */ 
  7.     private static final int QR_COLOR = 0xFF009900; 
  8.     /** 
  9.      * 生成英文二维码的内容. 
  10.      */ 
  11.     private final String englishContent = "http://www.huawei.com"
  12.     private EventHandler handler; 
  13.     private QRCodeUtil qrCodeUtil; 
  14.  
  15.  
  16.     /** 
  17.      * 显示不同颜色二维码. 
  18.      */ 
  19.     private Image colorQRCode; 
  20.  
  21.     private Text regionText; 
  22.  
  23.     @Override 
  24.     public void onStart(Intent intent) { 
  25.         HiLog.info(LABEL, "onStart"); 
  26.         super.onStart(intent); 
  27.         super.setUIContent(ResourceTable.Layout_health_code_slice); 
  28.         //二维码 
  29.         colorQRCode = (Image) findComponentById(ResourceTable.Id_text_main_card_icon); 
  30.         //所在城市 
  31.         regionText = (Text) findComponentById(ResourceTable.Id_text_health_region); 
  32.  
  33.         //设置行程卡跳转 
  34.         Component component = findComponentById(ResourceTable.Id_text_bottom_card_itinerary); 
  35.  
  36.         //行程卡跳转 
  37.         Intent itineraryIntent = new Intent(); 
  38.         component.setClickedListener(listener -> present(new ItineraryCardSlice(), itineraryIntent)); 
  39.  
  40.         //生成安康码 
  41.         handler = new EventHandler(EventRunner.create("qr")); 
  42.         qrCodeUtil = new QRCodeUtil(this); 
  43.         generateColorQRCode(); 
  44.  
  45.  
  46.         //获取所在位置 
  47.         String currentRegion = LocationHelper.getProvinceAndCity(); 
  48.         HiLog.info(LABEL, "currentRegion: " + currentRegion); 
  49.         regionText.setText(currentRegion); 
  50.     } 
  51.  
  52.     /** 
  53.      * 生成不同颜色二维码. 
  54.      */ 
  55.     private void generateColorQRCode() { 
  56.         handler.postTask(() -> { 
  57.             PixelMap pixelMap = qrCodeUtil.generateColorQRCode( 
  58.                     englishContent, QR_COLOR); 
  59.             getMainTaskDispatcher().syncDispatch(() -> { 
  60.                 // 显示二维码图像 
  61.                 colorQRCode.setPixelMap(pixelMap); 
  62.             }); 
  63.         }); 
  64.     } 
  65.  
  66.     @Override 
  67.     public void onActive() { 
  68.         super.onActive(); 
  69.     } 
  70.  
  71.     @Override 
  72.     public void onForeground(Intent intent) { 
  73.         super.onForeground(intent); 
  74.     } 
  75.  
  76.     @Override 
  77.     protected void onStop() { 
  78.         HiLog.info(LABEL, "onStop"); 
  79.     } 
  80.  
  81.  
  82.     /** 
  83.      * 调用阿里提供API,未实现 
  84.      */ 
  85.     public void queryGovHealthcode() { 
  86.         AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do""app_id""your private_key""json""GBK""alipay_public_key""RSA2"); 
  87.         AlipayEbppIndustryGovHealthcodeQueryRequest request = new AlipayEbppIndustryGovHealthcodeQueryRequest(); 
  88.         request.setBizContent("{" + 
  89.                 "\"city_code\":\"88684\"," + 
  90.                 "\"biz_info\":\"{\\\"location\\\":\\\"浙江省杭州市\\\",\\\"bizTime\\\":\\\"2020-04-13 14:20:30\\\"}\"," + 
  91.                 "\"biz_type\":\"HEALTHCODE\"" + 
  92.                 "  }"); 
  93.         AlipayEbppIndustryGovHealthcodeQueryResponse response = null
  94.         try { 
  95.             response = alipayClient.execute(request, accessToken); 
  96.             if (response.isSuccess()) { 
  97.                 System.out.println("调用成功"); 
  98.             } else { 
  99.                 System.out.println("调用失败"); 
  100.             } 
  101.         } catch (AlipayApiException e) { 
  102.             e.printStackTrace(); 
  103.         } 
  104.  
  105.     } 
  106.  

 ItineraryCardSlice.java

  1. /** 
  2.  * 行程卡页面 
  3.  */ 
  4. public class ItineraryCardSlice extends AbilitySlice { 
  5.     static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001003, "=>ItineraryCardSlice"); 
  6.  
  7.     @Override 
  8.     public void onStart(Intent intent) { 
  9.         HiLog.info(LABEL, "onStart"); 
  10.         super.onStart(intent); 
  11.         super.setUIContent(ResourceTable.Layout_itinerary_card_slice); 
  12.  
  13.  
  14.         //获取传递过来的所在城市 
  15.         String currentRegion = intent.getStringParam("currentRegion"); 
  16.         HiLog.debug(LABEL, "currentRegion:" + currentRegion); 
  17.         if (currentRegion!=null) { 
  18.  
  19.         } 
  20.     } 
  21.  
  22.     @Override 
  23.     public void onActive() { 
  24.         super.onActive(); 
  25.     } 
  26.  
  27.     @Override 
  28.     public void onForeground(Intent intent) { 
  29.         super.onForeground(intent); 
  30.     } 
  31.  
  32.     @Override 
  33.     protected void onStop() { 
  34.         HiLog.info(LABEL, "onStop"); 
  35.     } 
  36.  

LocationHelper.java 获取位置工具类

  1. /** 
  2.  * 获取本机位置信息实现类 
  3.  * 
  4.  * @since 2021-03-15 
  5.  */ 
  6. public class LocationHelper { 
  7.     static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001205, "=>LocationHelper"); 
  8.     //当前位置 
  9.     private static String provinceAndCity; 
  10.     private static String city; 
  11.     //当前的经纬度 
  12.     private static String longlat; 
  13.     private LocCallBack locCallBack; 
  14.     private Context context; 
  15.  
  16.     public static String getProvinceAndCity() { 
  17.         return provinceAndCity; 
  18.     } 
  19.  
  20.     public static void setProvinceAndCity(String provinceAndCity) { 
  21.         LocationHelper.provinceAndCity = provinceAndCity; 
  22.     } 
  23.  
  24.     public static String getCity() { 
  25.         return city; 
  26.     } 
  27.  
  28.     public static void setCity(String city) { 
  29.         LocationHelper.city = city; 
  30.     } 
  31.  
  32.     public static String getLonglat() { 
  33.         return longlat; 
  34.     } 
  35.  
  36.     public static void setLonglat(String longlat) { 
  37.         LocationHelper.longlat = longlat; 
  38.     } 
  39.  
  40.     /** 
  41.      * 获取本机位置信息 
  42.      * 
  43.      * @param con      Context con 
  44.      * @param callBack LocCallBack callBack 
  45.      */ 
  46.     public void getMyLocation(Context con, LocCallBack callBack) { 
  47.         locCallBack = callBack; 
  48.         context = con; 
  49.         Locator locator = new Locator(context); 
  50.         if (locator.isLocationSwitchOn()) { 
  51.             RequestParam requestParam = new RequestParam(RequestParam.SCENE_NAVIGATION); 
  52.             MyLocatorCallback locatorCallback = new MyLocatorCallback(); 
  53.             locator.requestOnce(requestParam, locatorCallback); 
  54.  
  55.         } else { 
  56.             ToastDialog toastDialog = new ToastDialog(context); 
  57.             toastDialog.setAutoClosable(false); 
  58.             toastDialog.setContentText("请前往设置打开位置开关"); 
  59.             toastDialog.show(); 
  60.         } 
  61.     } 
  62.  
  63.  
  64.     /** 
  65.      * 调用高德地图逆地理编码api,获取城市编码 
  66.      * 
  67.      * @param location Location 
  68.      */ 
  69.     public void getRegionDetail(Location location) { 
  70.         HiLog.info(LABEL, "getRegionDetail"); 
  71.         String locations = location.getLongitude() + "," + location.getLatitude(); 
  72.         HiLog.info(LABEL, "getRegionDetail,locations:" + locations + ",longlat:" + longlat); 
  73.         try { 
  74.             //如果经纬度和上次的一致就不再地理编码 
  75.             if (!locations.isEmpty() && locations.equals(longlat)) { 
  76.                 HiLog.info(LABEL, "getRegionDetail repeat"); 
  77.  
  78.                 if (locCallBack != null) { 
  79.                     locCallBack.locCallBack(provinceAndCity); 
  80.                 } 
  81.             } else { 
  82.                 String url = String.format(Const.REGION_DETAIL_URL, locations, Const.MAP_KEY); 
  83.                 HttpUtils.getInstance(context).get(url, result -> { 
  84.                     HiLog.info(LABEL, "result:" + result); 
  85.                     if (result != null) { 
  86.                         RegionDetailResult regionDetailResult = GsonUtils.jsonToBean(result, RegionDetailResult.class); 
  87.                         HiLog.info(LABEL, "regionDetailResult"); 
  88.                         String province = regionDetailResult.getRegeocode().getAddressComponent().getProvince(); 
  89.                         String city = regionDetailResult.getRegeocode().getAddressComponent().getCity(); 
  90.  
  91.                         StringBuilder stringBuilder = new StringBuilder(province); 
  92.                         stringBuilder.append("-").append(city); 
  93.                         //保存获取的位置 
  94.                         setCity(city); 
  95.                         setProvinceAndCity(stringBuilder.toString()); 
  96.                         setLonglat(locations); 
  97.                         HiLog.info(LABEL, "regionLocation:" + stringBuilder); 
  98.                         // 
  99.                         if (locCallBack != null) { 
  100.                             locCallBack.locCallBack(provinceAndCity); 
  101.                         } 
  102.                     } else { 
  103.                         HiLog.info(LABEL, "get Location Error!"); 
  104.                     } 
  105.                 }); 
  106.             } 
  107.         } catch (Exception e) { 
  108.             HiLog.error(LABEL, "getRegionDetail error:" + e.getMessage()); 
  109.             e.printStackTrace(); 
  110.         } 
  111.     } 
  112.  
  113.     /** 
  114.      * 获取位置信息后的回调接口 
  115.      * 
  116.      * @since 2021-03-15 
  117.      */ 
  118.     public interface LocCallBack { 
  119.         /** 
  120.          * locCallBack 
  121.          * 
  122.          * @param currentRegion 当前位置 
  123.          */ 
  124.         void locCallBack(String currentRegion); 
  125.     } 
  126.  
  127.     /** 
  128.      * MyLocatorCallback 
  129.      * 
  130.      * @since 2021-03-12 
  131.      */ 
  132.     private class MyLocatorCallback implements LocatorCallback { 
  133.         @Override 
  134.         public void onLocationReport(Location location) { 
  135.             HiLog.info(LABEL, "onLocationReport:" + location); 
  136.             //经纬度转地理位置 
  137.             getRegionDetail(location); 
  138.         } 
  139.  
  140.         @Override 
  141.         public void onStatusChanged(int type) { 
  142.             HiLog.info(LABEL, "onStatusChanged:" + type); 
  143.         } 
  144.  
  145.         @Override 
  146.         public void onErrorReport(int type) { 
  147.             HiLog.info(LABEL, "onErrorReport:" + type); 
  148.         } 
  149.     } 

全局config.json配置文件

  1.   "app": { 
  2.     "bundleName""com.buty.esa"
  3.     "vendor""huawei"
  4.     "version": { 
  5.       "code": 1000000, 
  6.       "name""1.0" 
  7.     } 
  8.   }, 
  9.   "deviceConfig": { 
  10.     "default": { 
  11.       "keepAlive"true 
  12.     } 
  13.   }, 
  14.   "module": { 
  15.     "package""com.huawei.learnharmony"
  16.     "name""com.huawei.learnharmony.MyApplication"
  17.     "deviceType": [ 
  18.       "phone" 
  19.     ], 
  20.     "distro": { 
  21.       "deliveryWithInstall"true
  22.       "moduleName""entry"
  23.       "moduleType""entry"
  24.       "installationFree"false 
  25.     }, 
  26.     "abilities": [ 
  27.       { 
  28.         "skills": [ 
  29.           { 
  30.             "entities": [ 
  31.               "entity.system.home" 
  32.             ], 
  33.             "actions": [ 
  34.               "action.system.home"
  35.               "action.custom.healthcode"
  36.               "action.custom.itinerarycard" 
  37.             ] 
  38.           } 
  39.         ], 
  40.         "orientation""unspecified"
  41.         "name""com.huawei.learnharmony.MainAbility"
  42.         "icon""$media:icon"
  43.         "description""$string:mainability_description"
  44.         "label""$string:app_name"
  45.         "type""page"
  46.         "launchType""singleton"
  47.         "formsEnabled"true
  48.         "visible"true
  49.         "forms": [ 
  50.           { 
  51.             "landscapeLayouts": [ 
  52.               "$layout:form_image_with_info_date_card_2_2"
  53.               "$layout:form_image_with_info_date_card_2_4" 
  54.             ], 
  55.             "isDefault"true
  56.             "scheduledUpdateTime""10:30"
  57.             "defaultDimension""2*2"
  58.             "name""EpidemicCard"
  59.             "description""查看安康码、行程卡"
  60.             "colorMode""auto"
  61.             "type""Java"
  62.             "supportDimensions": [ 
  63.               "2*2"
  64.               "2*4" 
  65.             ], 
  66.             "portraitLayouts": [ 
  67.               "$layout:form_image_with_info_date_card_2_2"
  68.               "$layout:form_image_with_info_date_card_2_4" 
  69.             ], 
  70.             "updateEnabled"true
  71.             "updateDuration": 1, 
  72.             "formVisibleNotify"true 
  73.           } 
  74.         ], 
  75.         "metaData":{ 
  76.           "customizeData":[ 
  77.             { 
  78.               "name" :"hwc-theme"
  79.               "value":"androidhwext:style/Theme.Emui.Light.NoTitleBar"
  80.               "extra":"" 
  81.             } 
  82.           ] 
  83.         } 
  84.       }, 
  85.       { 
  86.         "name""com.huawei.learnharmony.TimerAbility"
  87.         "icon""$media:icon"
  88.         "description""$string:TimeAbility_description"
  89.         "type""service"
  90.         "visible"true 
  91.       } 
  92.     ], 
  93.     "reqPermissions": [ 
  94.       { 
  95.         "reason""获取您所在城市"
  96.         "name""ohos.permission.LOCATION"
  97.         "usedScene": { 
  98.           "ability": [ 
  99.             "com.huawei.learnharmony.MainAbility" 
  100.           ], 
  101.           "when""always" 
  102.         } 
  103.       }, 
  104.       { 
  105.         "name""ohos.permission.LOCATION_IN_BACKGROUND" 
  106.       }, 
  107.       { 
  108.         "name""ohos.permission.INTERNET" 
  109.       }, 
  110.       { 
  111.         "name""ohos.permission.GET_BUNDLE_INFO" 
  112.       }, 
  113.       { 
  114.         "name""ohos.permission.GET_NETWORK_INFO" 
  115.       }, 
  116.       { 
  117.         "name""ohos.permission.SET_NETWORK_INFO" 
  118.       } 
  119.     ] 
  120.   } 

问题总结

1.解决页面布局问题,模拟器看到的效果和真机显示不完整存在差异

//卡片布局中 ohos:remote=“true” 一定要加

2.解决一个卡片,不同功能区跳转到不同的Slice问题

  1. //设置跳转事件 
  2. componentProvider.setIntentAgent(viewId, getIntentAgent(actionKey)); 

3.解决获取位置问题

使用LocationHelper,HttpUtils,GsonUtils工具类,获取经纬度后还需要逆地理编码

  1. 使用LocationHelper,HttpUtils,GsonUtils工具类,获取经纬度后还需要逆地理编码 
  2. //获取位置 
  3. regionText = (Text) findComponentById(ResourceTable.Id_text_main_region); 
  4. new LocationHelper().getMyLocation(getContext(), currentRegion -> { 
  5.     getUITaskDispatcher().asyncDispatch(() -> { 
  6.         regionText.setText(currentRegion); 
  7.     }); 
  8. }); 

4.二维码生成的问题

使用到了QRCodeUtil工具类,

官方指导:

https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/HarmonyOS-QRCode

5.待解决安康码,行程卡相关接口调用问题,需要找到相关的开放接口

文章相关附件可以点击下面的原文链接前往下载

https://harmonyos.51cto.com/resource/1092

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

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

https://harmonyos.51cto.com

 

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

2014-07-17 14:59:39

2021-09-15 10:19:15

鸿蒙HarmonyOS应用

2021-07-22 08:45:47

鸿蒙HarmonyOS应用

2021-07-28 14:59:08

鸿蒙HarmonyOS应用

2023-08-07 12:53:05

开发服务

2023-08-11 14:00:42

鸿蒙元服务

2022-04-24 15:26:38

服务卡鸿蒙

2019-10-30 08:55:33

谷歌人工智能技术

2021-08-23 10:12:41

鸿蒙HarmonyOS应用

2023-06-20 15:45:15

服务卡片鸿蒙

2022-05-09 11:52:38

Java卡片服务卡片

2023-09-18 15:12:47

服务卡片ArkTS

2021-06-21 15:21:52

鸿蒙HarmonyOS应用开发

2021-08-18 10:06:33

鸿蒙HarmonyOS应用

2021-07-20 09:58:16

鸿蒙HarmonyOS应用

2012-03-04 20:09:29

Siri

2016-06-23 11:48:00

Android开发

2021-08-20 14:23:14

鸿蒙HarmonyOS应用

2023-08-04 17:24:43

2023-04-07 09:20:55

点赞
收藏

51CTO技术栈公众号