Epidemic Service Assistant 疫情服务助手卡片 原创 精华
@toc
Epidemic Service Assistant 疫情服务助手卡片
介绍
前段时间国内的新冠疫情又出现了一些波动,公司也要求每天上报健康码和行程码,就想着能不能用服务卡片做一个,于是就开始行动了,想着大体可以分成2步走,需要先设计UI,然后对接相关的接口,不过对接接口要麻烦一些,需要有相关的开放接口,目前还没实现。
搭建环境
安装DevEco Studio,详情请参考DevEco Studio下载。
设置DevEco Studio开发环境,DevEco Studio开发环境需要依赖于网络环境,需要连接上网络才能确保工具的正常使用,可以根据如下两种情况来配置开发环境:
如果可以直接访问Internet,只需进行下载HarmonyOS SDK操作。
如果网络不能直接访问Internet,需要通过代理服务器才可以访问,请参考配置开发环境。
效果展示
项目结构
实现步骤
1.编写界面
ability_main.xml 主界面
这个界面会显示获取到城市,以及地区的风险等级,然后就是安康码和行程卡的入口。
itinerary_card_slice.xml行程卡界面
行程卡的显示界面,上半部分是通过短信验证码获取行程信息,下半部分是显示获取到的行程信息。
health_code_slice安康码界面
安康码的显示界面,上半部部分显示当前所在城市,下半部分显示获取的安康码信息,然后是一个行程卡的入口。
form_image_with_info_date_card_2_2.xml 2x2的卡片界面
form_image_with_info_date_card_2_4.xml 2x4的卡片界面
2.编写启动应用代码
MainAbility.java
/**
* Card Main Ability
*/
public class MainAbility extends Ability {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x0D1001, "=>MainAbility");
//卡片规格编号
private static final int DEFAULT_DIMENSION_2X2 = 2;
private static final int DEFAULT_DIMENSION_2X4 = 3;
//ACTION路由
private final String ACTION_HEALTH_CODE = "action.custom.healthcode";
private final String ACTION_ITINERARY_CARD = "action.custom.itinerarycard";
//权限
private String[] requestPermissions = {SystemPermission.LOCATION};
//卡片ID
private long formId;
//卡片信息
private ProviderFormInfo formInfo;
//二维码
private QRCodeUtil qrCodeUtil;
//所在城市文本组件
private Text regionText;
@Override
public void onStart(Intent intent) {
HiLog.info(LABEL, "onStart ");
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
//必要的
super.setUIContent(ResourceTable.Layout_ability_main);
//添加ACTION路由
addActionRoute(ACTION_HEALTH_CODE, HealthCodeSlice.class.getName());
addActionRoute(ACTION_ITINERARY_CARD, ItineraryCardSlice.class.getName());
//向用户请求权限
PermissionsUtils.getInstance(this).requestPermissions(this, requestPermissions);
//获取位置
regionText = (Text) findComponentById(ResourceTable.Id_text_main_region);
new LocationHelper().getMyLocation(getContext(), currentRegion -> {
getUITaskDispatcher().asyncDispatch(() -> {
regionText.setText(currentRegion);
});
});
}
@Override
protected ProviderFormInfo onCreateForm(Intent intent) {
HiLog.info(LABEL, "创建卡片");
if (intent == null) {
return new ProviderFormInfo();
}
if (qrCodeUtil == null) {
qrCodeUtil = new QRCodeUtil(this);
}
// 获取卡片id
if (intent.hasParameter(AbilitySlice.PARAM_FORM_IDENTITY_KEY)) {
formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, -1);
} else {
HiLog.info(LABEL, "未获取到卡片id....");
return new ProviderFormInfo();
}
HiLog.info(LABEL, "获取卡片id:" + formId);
// 获取卡片名称
String formName = "疫情助手";
if (intent.hasParameter(AbilitySlice.PARAM_FORM_NAME_KEY)) {
formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);
}
HiLog.info(LABEL, "获取卡片名称:" + formName);
// 获取卡片规格
int dimension = DEFAULT_DIMENSION_2X4;
if (intent.hasParameter(AbilitySlice.PARAM_FORM_DIMENSION_KEY)) {
dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X4);
}
Map<String, Integer> viewIdMap = new HashMap<>();
HiLog.info(LABEL, "获取卡片规格:" + dimension);
//获取卡片布局ID
int layoutId = getLayoutId(dimension, viewIdMap);
HiLog.info(LABEL, "通过布局文件id实例化formInfo");
formInfo = new ProviderFormInfo(layoutId, this);
// 存储卡片信息
HiLog.info(LABEL, "存储卡片信息");
Form form = new Form(formId, formName, dimension);
HiLog.info(LABEL, "根据Form实例化ComponentProvider");
ComponentProvider componentProvider = getComponentProvider(form, viewIdMap, layoutId, this);
HiLog.info(LABEL, "设置formInfo的 ComponentProvider 对象");
formInfo.mergeActions(componentProvider);
try {
HiLog.info(LABEL, "通过DatabaseUtils保存Form信息到DB:" + form.toString());
DatabaseUtils.getInstance(this).insertForm(form);
} catch (Exception e) {
HiLog.info(LABEL, "发生异常,通过DatabaseUtils删除DB中的Form信息");
DatabaseUtils.getInstance(this).deleteFormData(form.getFormId());
}
return formInfo;
}
/**
* @param dimension 卡片规格
* @param viewIdMap 健康码/行程码所在布局ID
* @return
*/
public int getLayoutId(int dimension, Map<String, Integer> viewIdMap) {
viewIdMap.clear();
HiLog.info(LABEL, "getLayoutId");
int layoutId = 0;
if (dimension == DEFAULT_DIMENSION_2X2) {
HiLog.info(LABEL, "获取2*2的布局文件");
layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_2;
//
viewIdMap.put(ACTION_HEALTH_CODE, ResourceTable.Id_layout_ankang_2x2);
} else if (dimension == DEFAULT_DIMENSION_2X4) {
HiLog.info(LABEL, "获取2*4的布局文件");
layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_4;
//
viewIdMap.put(ACTION_HEALTH_CODE, ResourceTable.Id_layout_ankang_2x4);
viewIdMap.put(ACTION_ITINERARY_CARD, ResourceTable.Id_layout_itinerary_2x4);
}
return layoutId;
}
/**
* 获取卡片信息提供者对象
*
* @param form
* @param viewIdMap
* @param layoutId
* @param context
* @return
*/
public ComponentProvider getComponentProvider(Form form, Map<String, Integer> viewIdMap, int layoutId, Context context) {
HiLog.info(LABEL, "getComponentProvider");
ComponentProvider componentProvider = new ComponentProvider(layoutId, context);
for (Map.Entry entry : viewIdMap.entrySet()) {
String actionKey = (String) entry.getKey();
int viewId = (int) entry.getValue();
HiLog.info(LABEL, "actionKey = " + actionKey + ", viewId = " + viewId);
//设置组件值
setComponentProviderValue(componentProvider, form);
//设置跳转事件
componentProvider.setIntentAgent(viewId, getIntentAgent(actionKey));
}
return componentProvider;
}
/**
* 设置卡片信息
*
* @param componentProvider
* @param form
*/
private void setComponentProviderValue(ComponentProvider componentProvider, Form form) {
//HiLog.debug(LABEL, "setComponentProviderValue,PixelMap:"+QRCodeUtil.getCurrentPixelMap());
try {
if (form.getDimension() == DEFAULT_DIMENSION_2X2) {
HiLog.info(LABEL, "setComponentProviderValue2x2");
componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity());
//设置QR
componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, QRCodeUtil.getCurrentPixelMap());
} else {
HiLog.info(LABEL, "setComponentProviderValue2x4");
componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity());
//设置安康码
componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, QRCodeUtil.getCurrentPixelMap());
//设置行程卡信息
componentProvider.setImageContent(ResourceTable.Id_image_itinerary_right, ResourceTable.Graphic_icon_itinerary);
}
} catch (Exception e) {
HiLog.error(LABEL, "setComponentProviderValueError:" + e.getMessage());
e.printStackTrace();
}
}
/**
* 获取IntentAgent,事件控制对象
*
* @param ACTION
* @return
*/
private IntentAgent getIntentAgent(String ACTION) {
HiLog.info(LABEL, "getIntentAgent");
// 设置点击的跳转页面
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName(getBundleName())
.withAbilityName(MainAbility.class)
.withAction(ACTION)
.build();
// 携带参数
intent.setParam("formId", 1);
intent.setOperation(operation);
List<Intent> intentList = new ArrayList<>();
intentList.add(intent);
// 对于不同的响应事件,第一个参数requestCode需要不同,此处用电影id设为requestCode
IntentAgentInfo paramsInfo = new IntentAgentInfo(200,
IntentAgentConstant.OperationType.START_ABILITY,
IntentAgentConstant.Flags.UPDATE_PRESENT_FLAG, intentList, null);
IntentAgent intentAgent = IntentAgentHelper.getIntentAgent(this, paramsInfo);
HiLog.info(LABEL, "getIntentAgent:FINISH");
return intentAgent;
}
/**
* 用户删除卡片时会自动调用
*
* @param formId
*/
@Override
protected void onDeleteForm(long formId) {
super.onDeleteForm(formId);
// 删除数据库中的卡片信息
HiLog.info(LABEL, "删除DB中的Form信息:" + formId);
DatabaseUtils.getInstance(this).deleteFormData(formId);
}
@Override
public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
PermissionsUtils.getInstance(this).onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
MainAbilitySlice.java
/**
* MainAbilitySlice
*/
public class MainAbilitySlice extends AbilitySlice {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001003, "=>MainAbilitySlice");
@Override
public void onStart(Intent intent) {
HiLog.info(LABEL, "onStart");
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_main);
//
initComponent();
//初始化更新卡片服务
startServiceAbility();
}
private void initComponent() {
HiLog.info(LABEL, "initComponent");
//
Component componentAnkang = findComponentById(ResourceTable.Id_text_bottom_card_ankang);
Component componentItinerary = findComponentById(ResourceTable.Id_text_bottom_card_itinerary);
//跳转到健康码和行程卡页面
componentAnkang.setClickedListener(listener -> present(new HealthCodeSlice(),new Intent()));
componentItinerary.setClickedListener(listener -> present(new ItineraryCardSlice(), new Intent()));
}
/**
* 启动更新卡片服务Ability
*/
private void startServiceAbility() {
// 启动TimerAbility
Intent intentService = new Intent();
Operation operation =
new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName(getBundleName())
.withAbilityName(TimerAbility.class.getName())
.build();
intentService.setOperation(operation);
startAbility(intentService);
HiLog.info(LABEL, "启动TimerAbility ");
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
protected void onStop() {
}
}
TimerAbility.java
主要实现卡片的数据定时更新,代码如下:
/**
* 用于定时更新卡片的服务
* Time PA
*/
public class TimerAbility extends Ability {
private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001003, "=>TimerAbility");
//卡片规格编号
public static final int DEFAULT_DIMENSION_2X2 = 2;
//卡片规格编号
public static final int DEFAULT_DIMENSION_2X4 = 3;
//更新卡片周期:毫秒
private static final long SEND_PERIOD = 10000L;
private static final int QR_COLOR = 0xFF009900;
//DB 帮助类
private DatabaseHelper helper = new DatabaseHelper(this);
//ORM上下文
private OrmContext connect;
//二维码工具类
private QRCodeUtil qrCodeUtil;
//全局定时器
private Timer timer = null;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
HiLog.info(LABEL, "初始化数据库连接");
connect = helper.getOrmContext("FormDatabase", "FormDatabase.db", FormDatabase.class);
//
qrCodeUtil = new QRCodeUtil(this);
//
HiLog.info(LABEL, "启动定时");
startTimer();
}
/**
* 启动定时器,定期刷新卡片数据,
* 一个卡片对应一个定时器
*/
private void startTimer() {
/*if (timer != null) {
timer.cancel();
}*/
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
updateForms();
}
}, 0, SEND_PERIOD);
}
/**
* 更细卡片数据
*/
private void updateForms() {
// 从数据库中获取卡片信息
HiLog.info(LABEL, "从数据库中获取卡片");
OrmPredicates ormPredicates = new OrmPredicates(Form.class);
List<Form> formList = connect.query(ormPredicates);
int layoutId = 0;
// 更新时分秒
if (formList.size() <= 0) {
return;
}
HiLog.info(LABEL, "遍历卡片列表,逐个更新");
for (Form form : formList) {
//获取卡片刷新的数据提供对象
ComponentProvider componentProvider = getComponentProvider(form, this);
try {
Long updateFormId = form.getFormId();
HiLog.info(LABEL, "卡片ID[" + updateFormId + "]");
//更新卡片数据到数据库
boolean isSucc = updateForm(updateFormId, componentProvider);
HiLog.info(LABEL, "更新卡片数据完成," + isSucc);
} catch (FormException e) {
// 删除不存在的卡片
DatabaseUtils.getInstance(this).deleteFormData(form.getFormId());
HiLog.error(LABEL, "更新卡片异常,删除数据库中不存在的卡片");
}
}
}
/**
* Obtains the ComponentProvider object
*
* @param form form info
* @param context context
* @return component provider
*/
public ComponentProvider getComponentProvider(Form form, Context context) {
HiLog.info(LABEL, "getComponentProvider:" + form);
//获取卡片规格
int layoutId = getLayoutId(form.getDimension());
HiLog.info(LABEL, "layoutId:" + layoutId);
ComponentProvider componentProvider = new ComponentProvider(layoutId, context);
HiLog.info(LABEL, "更新卡片上组件的值");
setComponentProviderValue(componentProvider, form);
return componentProvider;
}
/**
* 获取对应规格的布局文件
*
* @param dimension
* @return
*/
public int getLayoutId(int dimension) {
HiLog.info(LABEL, "getLayoutId");
int layoutId = 0;
if (dimension == DEFAULT_DIMENSION_2X2) {
HiLog.info(LABEL, "获取2*2的布局文件");
layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_2;
}
if (dimension == DEFAULT_DIMENSION_2X4) {
HiLog.info(LABEL, "获取2*4的布局文件");
layoutId = ResourceTable.Layout_form_image_with_info_date_card_2_4;
}
return layoutId;
}
/**
* Set the value of componentProvider
* 根据规格来更新卡片信息
*
* @param componentProvider component provider
*/
private void setComponentProviderValue(ComponentProvider componentProvider, Form form) {
HiLog.info(LABEL, "setComponentProviderValue");
PixelMap pixels;
if (form.getDimension() == DEFAULT_DIMENSION_2X2) {
HiLog.info(LABEL, "setComponentProviderValue2x2");
componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity());
//设置QR
pixels = qrCodeUtil.generateColorQRCode(new Date().getTime() + "", QR_COLOR);
componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, pixels);
} else {
HiLog.info(LABEL, "setComponentProviderValue2x4");
componentProvider.setText(ResourceTable.Id_text_city, LocationHelper.getCity());
//设置QR
pixels = qrCodeUtil.generateColorQRCode(new Date().getTime() + "", QR_COLOR);
componentProvider.setImagePixelMap(ResourceTable.Id_image_ankang_right, pixels);
//设置行程卡信息
componentProvider.setImageContent(ResourceTable.Id_image_itinerary_right, ResourceTable.Graphic_icon_itinerary);
}
}
@Override
public void onBackground() {
super.onBackground();
HiLog.info(LABEL, "TimerAbility::onBackground");
}
@Override
public void onStop() {
super.onStop();
timer.cancel();
HiLog.info(LABEL, "TimerAbility::onStop");
}
}
HealthCodeSlice.java
public class HealthCodeSlice extends AbilitySlice {
static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001005, "=>HealthCodeSlice");
private static final String accessToken = "";
/**
* 随机定义生成不同颜色的二维码.
*/
private static final int QR_COLOR = 0xFF009900;
/**
* 生成英文二维码的内容.
*/
private final String englishContent = "http://www.huawei.com";
private EventHandler handler;
private QRCodeUtil qrCodeUtil;
/**
* 显示不同颜色二维码.
*/
private Image colorQRCode;
private Text regionText;
@Override
public void onStart(Intent intent) {
HiLog.info(LABEL, "onStart");
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_health_code_slice);
//二维码
colorQRCode = (Image) findComponentById(ResourceTable.Id_text_main_card_icon);
//所在城市
regionText = (Text) findComponentById(ResourceTable.Id_text_health_region);
//设置行程卡跳转
Component component = findComponentById(ResourceTable.Id_text_bottom_card_itinerary);
//行程卡跳转
Intent itineraryIntent = new Intent();
component.setClickedListener(listener -> present(new ItineraryCardSlice(), itineraryIntent));
//生成安康码
handler = new EventHandler(EventRunner.create("qr"));
qrCodeUtil = new QRCodeUtil(this);
generateColorQRCode();
//获取所在位置
String currentRegion = LocationHelper.getProvinceAndCity();
HiLog.info(LABEL, "currentRegion: " + currentRegion);
regionText.setText(currentRegion);
}
/**
* 生成不同颜色二维码.
*/
private void generateColorQRCode() {
handler.postTask(() -> {
PixelMap pixelMap = qrCodeUtil.generateColorQRCode(
englishContent, QR_COLOR);
getMainTaskDispatcher().syncDispatch(() -> {
// 显示二维码图像
colorQRCode.setPixelMap(pixelMap);
});
});
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
protected void onStop() {
HiLog.info(LABEL, "onStop");
}
/**
* 调用阿里提供API,未实现
*/
public void queryGovHealthcode() {
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", "app_id", "your private_key", "json", "GBK", "alipay_public_key", "RSA2");
AlipayEbppIndustryGovHealthcodeQueryRequest request = new AlipayEbppIndustryGovHealthcodeQueryRequest();
request.setBizContent("{" +
"\"city_code\":\"88684\"," +
"\"biz_info\":\"{\\\"location\\\":\\\"浙江省杭州市\\\",\\\"bizTime\\\":\\\"2020-04-13 14:20:30\\\"}\"," +
"\"biz_type\":\"HEALTHCODE\"" +
" }");
AlipayEbppIndustryGovHealthcodeQueryResponse response = null;
try {
response = alipayClient.execute(request, accessToken);
if (response.isSuccess()) {
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
}
}
ItineraryCardSlice.java
/**
* 行程卡页面
*/
public class ItineraryCardSlice extends AbilitySlice {
static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001003, "=>ItineraryCardSlice");
@Override
public void onStart(Intent intent) {
HiLog.info(LABEL, "onStart");
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_itinerary_card_slice);
//获取传递过来的所在城市
String currentRegion = intent.getStringParam("currentRegion");
HiLog.debug(LABEL, "currentRegion:" + currentRegion);
if (currentRegion!=null) {
}
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
@Override
protected void onStop() {
HiLog.info(LABEL, "onStop");
}
}
LocationHelper.java 获取位置工具类
/**
* 获取本机位置信息实现类
*
* @since 2021-03-15
*/
public class LocationHelper {
static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x001205, "=>LocationHelper");
//当前位置
private static String provinceAndCity;
private static String city;
//当前的经纬度
private static String longlat;
private LocCallBack locCallBack;
private Context context;
public static String getProvinceAndCity() {
return provinceAndCity;
}
public static void setProvinceAndCity(String provinceAndCity) {
LocationHelper.provinceAndCity = provinceAndCity;
}
public static String getCity() {
return city;
}
public static void setCity(String city) {
LocationHelper.city = city;
}
public static String getLonglat() {
return longlat;
}
public static void setLonglat(String longlat) {
LocationHelper.longlat = longlat;
}
/**
* 获取本机位置信息
*
* @param con Context con
* @param callBack LocCallBack callBack
*/
public void getMyLocation(Context con, LocCallBack callBack) {
locCallBack = callBack;
context = con;
Locator locator = new Locator(context);
if (locator.isLocationSwitchOn()) {
RequestParam requestParam = new RequestParam(RequestParam.SCENE_NAVIGATION);
MyLocatorCallback locatorCallback = new MyLocatorCallback();
locator.requestOnce(requestParam, locatorCallback);
} else {
ToastDialog toastDialog = new ToastDialog(context);
toastDialog.setAutoClosable(false);
toastDialog.setContentText("请前往设置打开位置开关");
toastDialog.show();
}
}
/**
* 调用高德地图逆地理编码api,获取城市编码
*
* @param location Location
*/
public void getRegionDetail(Location location) {
HiLog.info(LABEL, "getRegionDetail");
String locations = location.getLongitude() + "," + location.getLatitude();
HiLog.info(LABEL, "getRegionDetail,locations:" + locations + ",longlat:" + longlat);
try {
//如果经纬度和上次的一致就不再地理编码
if (!locations.isEmpty() && locations.equals(longlat)) {
HiLog.info(LABEL, "getRegionDetail repeat");
if (locCallBack != null) {
locCallBack.locCallBack(provinceAndCity);
}
} else {
String url = String.format(Const.REGION_DETAIL_URL, locations, Const.MAP_KEY);
HttpUtils.getInstance(context).get(url, result -> {
HiLog.info(LABEL, "result:" + result);
if (result != null) {
RegionDetailResult regionDetailResult = GsonUtils.jsonToBean(result, RegionDetailResult.class);
HiLog.info(LABEL, "regionDetailResult");
String province = regionDetailResult.getRegeocode().getAddressComponent().getProvince();
String city = regionDetailResult.getRegeocode().getAddressComponent().getCity();
StringBuilder stringBuilder = new StringBuilder(province);
stringBuilder.append("-").append(city);
//保存获取的位置
setCity(city);
setProvinceAndCity(stringBuilder.toString());
setLonglat(locations);
HiLog.info(LABEL, "regionLocation:" + stringBuilder);
//
if (locCallBack != null) {
locCallBack.locCallBack(provinceAndCity);
}
} else {
HiLog.info(LABEL, "get Location Error!");
}
});
}
} catch (Exception e) {
HiLog.error(LABEL, "getRegionDetail error:" + e.getMessage());
e.printStackTrace();
}
}
/**
* 获取位置信息后的回调接口
*
* @since 2021-03-15
*/
public interface LocCallBack {
/**
* locCallBack
*
* @param currentRegion 当前位置
*/
void locCallBack(String currentRegion);
}
/**
* MyLocatorCallback
*
* @since 2021-03-12
*/
private class MyLocatorCallback implements LocatorCallback {
@Override
public void onLocationReport(Location location) {
HiLog.info(LABEL, "onLocationReport:" + location);
//经纬度转地理位置
getRegionDetail(location);
}
@Override
public void onStatusChanged(int type) {
HiLog.info(LABEL, "onStatusChanged:" + type);
}
@Override
public void onErrorReport(int type) {
HiLog.info(LABEL, "onErrorReport:" + type);
}
}
}
全局config.json配置文件
{
"app": {
"bundleName": "com.buty.esa",
"vendor": "huawei",
"version": {
"code": 1000000,
"name": "1.0"
}
},
"deviceConfig": {
"default": {
"keepAlive": true
}
},
"module": {
"package": "com.huawei.learnharmony",
"name": "com.huawei.learnharmony.MyApplication",
"deviceType": [
"phone"
],
"distro": {
"deliveryWithInstall": true,
"moduleName": "entry",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home",
"action.custom.healthcode",
"action.custom.itinerarycard"
]
}
],
"orientation": "unspecified",
"name": "com.huawei.learnharmony.MainAbility",
"icon": "$media:icon",
"description": "$string:mainability_description",
"label": "$string:app_name",
"type": "page",
"launchType": "singleton",
"formsEnabled": true,
"visible": true,
"forms": [
{
"landscapeLayouts": [
"$layout:form_image_with_info_date_card_2_2",
"$layout:form_image_with_info_date_card_2_4"
],
"isDefault": true,
"scheduledUpdateTime": "10:30",
"defaultDimension": "2*2",
"name": "EpidemicCard",
"description": "查看安康码、行程卡",
"colorMode": "auto",
"type": "Java",
"supportDimensions": [
"2*2",
"2*4"
],
"portraitLayouts": [
"$layout:form_image_with_info_date_card_2_2",
"$layout:form_image_with_info_date_card_2_4"
],
"updateEnabled": true,
"updateDuration": 1,
"formVisibleNotify": true
}
],
"metaData":{
"customizeData":[
{
"name" :"hwc-theme",
"value":"androidhwext:style/Theme.Emui.Light.NoTitleBar",
"extra":""
}
]
}
},
{
"name": "com.huawei.learnharmony.TimerAbility",
"icon": "$media:icon",
"description": "$string:TimeAbility_description",
"type": "service",
"visible": true
}
],
"reqPermissions": [
{
"reason": "获取您所在城市",
"name": "ohos.permission.LOCATION",
"usedScene": {
"ability": [
"com.huawei.learnharmony.MainAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.LOCATION_IN_BACKGROUND"
},
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.GET_BUNDLE_INFO"
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
},
{
"name": "ohos.permission.SET_NETWORK_INFO"
}
]
}
}
问题总结
1.解决页面布局问题,模拟器看到的效果和真机显示不完整存在差异
//卡片布局中 ohos:remote=“true” 一定要加
2.解决一个卡片,不同功能区跳转到不同的Slice问题
//设置跳转事件
componentProvider.setIntentAgent(viewId, getIntentAgent(actionKey));
3.解决获取位置问题
使用LocationHelper,HttpUtils,GsonUtils工具类,获取经纬度后还需要逆地理编码
//获取位置
regionText = (Text) findComponentById(ResourceTable.Id_text_main_region);
new LocationHelper().getMyLocation(getContext(), currentRegion -> {
getUITaskDispatcher().asyncDispatch(() -> {
regionText.setText(currentRegion);
});
});
4.二维码生成的问题
使用到了QRCodeUtil工具类,
官方指导:
https://developer.huawei.com/consumer/cn/codelabsPortal/carddetails/HarmonyOS-QRCode
5.待解决安康码,行程卡相关接口调用问题,需要找到相关的开放接口
完整代码
附件直接下载
疫情期间还是不能掉以轻心,鸿蒙的卡片确实对需要扫码的地方十分方便。
请问楼主,setImagePixelMap,我设置了int id和pixelMap,但是就是没效果。你遇到这个问题没?
有,在创建服务卡片的时候,想生成QR码显示在卡片上,不生效,最后用setImageContent方法设置了一张默认的QR码。卡片更新的时候却能生效,很奇怪。
那个setImageContent我试了没问题,能显示。问题出在setImagePixelMap(RT.Id,pixelMap),其中pixelMap我能打印出来值,并且实验在其他组件,例如setPixelmap(pixelMap)也没问题,就是setImagePixelMap没效果,哭死了。看来只能js去解决卡片获取网络图片的问题了。