HarmonyOS基于Java开发的服务卡片

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

和华为官方合作共建的发的服务鸿蒙技术社区

https://harmonyos.51cto.com

服务卡片介绍:

服务卡片是将重要信息或操作前置的一种界面展示,目的开卡片是减少体验层级,服务直达,发的服务增强用户交互体验。开卡片

卡片基本信息说明:

卡片使用方

显示卡片内容的发的服务宿主应用,控制卡片在宿主中展示的开卡片位置。

卡片管理服务

用于管理系统中所添加卡片的发的服务常驻代理服务,包括卡片对象的开卡片管理与使用,以及卡片周期性刷新等。发的服务

卡片提供方

提供卡片显示内容的开卡片HarmonyOS应用或原子化服务,控制卡片的发的服务显示内容、控件布局以及控件点击事件。开卡片

以下是发的服务器托管服务官方提供的运作机制:

项目介绍:

本篇主要对系统时间日期来展示服务卡片,该Demo是开卡片Java为基础,无JS相关代码,以下将对项目详细介绍。

项目目录如下:

database中FormBean是所需的bean文件并设置数据库表名,包含卡片的id、名称以及布局id,FormDatabase是bean绑定Orm数据库类。

Slice中MainAbilitySlice与TimeCardSlice是展示页面,MainAbilitySlice是创建项目系统生成,我设置初始化页面为TimeCardSlice。

Utils中是分别是卡片工具类、数据库工具类、日期工具类。

MainAbility以及MyApplication也是创建项目系统生成的。

注意MainAbility中的setMainRoute可以设置指定初始化页面。

TimerAbility是一个服务类,云服务器提供商用来更新卡片时间。

配置文件如下:

{    "app": {      "bundleName": "com.fei.yuan.myapplication",     "vendor": "fei",     "version": {        "code": 1000000,       "name": "1.0.0"     }   },   "deviceConfig": {      "default": {        "keepAlive": true     }   },   "module": {      "package": "com.fei.yuan.myapplication",     "name": ".MyApplication",     "mainAbility": "com.fei.yuan.myapplication.MainAbility",     "deviceType": [       "phone"     ],     "distro": {        "deliveryWithInstall": true,       "moduleName": "entry",       "moduleType": "entry",       "installationFree": false     },     "reqPermissions": [       {          "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",         "reason": "keep service ability backgroud running",         "usedScene": {            "ability": [             ".TimerAbility"           ],           "when": "always"         }       }     ],     "abilities": [       {          "skills": [           {              "entities": [               "entity.system.home"             ],             "actions": [               "action.system.home"             ]           }         ],         "orientation": "unspecified",         "name": "com.fei.yuan.myapplication.MainAbility",         "icon": "$media:icon",         "description": "$string:mainability_description",         "launchType": "standard",         "formsEnabled": true,         "label": "$string:entry_MainAbility",         "type": "page",         "visible": true,         "forms": [           {              "landscapeLayouts": [               "$layout:form_image_with_info_time_2_2",               "$layout:form_image_with_info_time_2_4"             ],             "isDefault": true,             "scheduledUpdateTime": "10:30",             "defaultDimension": "2*2",             "name": "widget",             "description": "This is a service widget",             "colorMode": "auto",             "type": "Java",             "supportDimensions": [               "1*2",               "2*2",               "2*4"             ],             "portraitLayouts": [               "$layout:form_image_with_info_time_2_2",               "$layout:form_image_with_info_time_2_4",               "$layout:form_image_with_info_time_1_2"             ],             "updateEnabled": true,             "updateDuration": 30,             "formVisibleNotify": true,             "metaData": {                "customizeData": [                 {                    "name": "needBlurBackgroundForLauncher",                   "value": "true"                 }               ]             }           }         ]       },       {          "icon": "$media:icon",         "name": "com.fei.yuan.myapplication.TimerAbility",         "description": "$string:timerability_description",         "type": "service",         "visible": true,         "backgroundModes": [           "dataTransfer",           "location"         ]       }     ]   } } 

forms内属性说明:

先上效果图:

代码详解:

下面开始项目解析:

首先介绍MainAbility主页,主要方法有onStart,onCreateForm,onDeleteForm

//主页初始化 public void onStart(Intent intent) {      HiLog.info(TAG, "onStart");     super.onStart(intent);     //添加在数据库中添加FormDatabase表     ormContext = databaseHelper.getOrmContext("FormBean", "FormDatabase.db", FormDatabase.class);     // 这里是开启服务,用来即时更新服务卡片时间(后天有说明)     Intent intentService = new Intent();     Operation operation = new Intent.OperationBuilder()             .withBundleName(getBundleName())             .withAbilityName(TimerAbility.class.getName())             .build();     intentService.setOperation(operation);     startAbility(intentService);     //加载初始页     super.setMainRoute(TimeCardSlice.class.getName()); }  //创建卡片 protected ProviderFormInfo onCreateForm(Intent intent) {      HiLog.info(TAG, "onCreateForm");     if (intent == null) {          return new ProviderFormInfo();     }     //获取卡片id     formId = INVALID_FORM_ID;     if (intent.hasParameter(AbilitySlice.PARAM_FORM_IDENTITY_KEY)) {          formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);     } else {          return new ProviderFormInfo();     }     //获取卡片名称     String formName = "";     if (intent.hasParameter(AbilitySlice.PARAM_FORM_NAME_KEY)) {          formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);     }     //获取卡片规格     int dimension = DEFAULT_DIMENSION_2X2;     if (intent.hasParameter(AbilitySlice.PARAM_FORM_DIMENSION_KEY)) {          dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);     }     int layoutId = ResourceTable.Layout_form_image_with_info_time_2_2;     if (dimension == DEFAULT_DIMENSION_2X4) {          layoutId = ResourceTable.Layout_form_image_with_info_time_2_4;     }else if (dimension == DEFAULT_DIMENSION_1X2){          layoutId = ResourceTable.Layout_form_image_with_info_time_1_2;     }     formInfo = new ProviderFormInfo(layoutId, this);     //存储卡片信息     FormBean formBean = new FormBean(formId, formName, dimension);     ComponentProvider componentProvider = ComponentProviderUtils.getComponentProvider(formBean, this);     formInfo.mergeActions(componentProvider);     if (ormContext == null) {          ormContext = databaseHelper.getOrmContext("FormBean", "FormDatabase.db", FormDatabase.class);     }     try {          //保存数据到数据库         DatabaseUtils.insertForm(formBean, ormContext);     } catch (Exception e) {          //删除数据库中保存的数据         DatabaseUtils.deleteFormData(formBean.getFormId(), ormContext);     }     return formInfo; }  //删除卡片 protected void onDeleteForm(long formId) {      HiLog.info(TAG, "onDeleteForm: formId=" + formId);     super.onDeleteForm(formId);     DatabaseUtils.deleteFormData(formId, ormContext); } 

接下来就是TimeCardSlice页,进行时间获取展示,并使用计时器来进行刷新页面。

private void initData() {      //获取日期     String currentDate = DateUtils.getCurrentDate("yyyy-MM-dd");     String[] split = currentDate.split("-");     monthText.setText(split[1]);     dayText.setText(split[2]);     //获取时间     Calendar calendar = Calendar.getInstance();     int hour = calendar.get(Calendar.HOUR_OF_DAY);     hourText.setText(intToString(hour));     int min = calendar.get(Calendar.MINUTE);     minText.setText(intToString(min));     int second = calendar.get(Calendar.SECOND);     secondText.setText(intToString(second));     //获取星期     int week = calendar.get(Calendar.DAY_OF_WEEK);     weekText.setText(getWeek(this,week)); }  // 计时器刷新数据 private void startTimer() {      timer = new Timer();     timer.schedule(new TimerTask() {          @Override         public void run() {              runnable.run();             myEventHandler.sendEvent(1);         }     }, 0, PERIOD); } 

最后是TimerAbility页,主要是对服务卡片进行刷新操作:

protected void onStart(Intent intent) {      HiLog.info(TAG, "onStart");     ormContext = databaseHelper.getOrmContext("FormBean", "FormDatabase.db", FormDatabase.class);     startTimer();     super.onStart(intent); } 

重点是这个方法,进行更新数据。

private void upDateFormBean() {      OrmPredicates ormPredicates = new OrmPredicates(FormBean.class);     List<FormBean> beanList = ormContext.query(ormPredicates);     if (beanList.size() <= 0) {          return;     }     for (FormBean formBean : beanList) {          //更新卡片信息         ComponentProvider componentProvider = ComponentProviderUtils.getComponentProvider(formBean,this);         try {              updateForm(formBean.getFormId(),componentProvider);         } catch (FormException e) {              DatabaseUtils.deleteFormData(formBean.getFormId(),ormContext);         }     } } 

注意:Java卡片与JS卡片选型指导,官方提倡使用JS来实现卡片,支持的控件和场景都很丰富

Java/JS卡片场景能力差异如下表所示:

综上所述,JS卡片比Java卡片支持的控件和能力都更丰富:

Java卡片:适合作为一个直达入口,没有复杂的页面和事件。 JS卡片:适合有复杂界面的卡片。

完整代码如下:

MainAbility.java:

public class MainAbility extends Ability {      private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0x0, "TAG---");     private static final int INVALID_FORM_ID = -1;     private static final int DEFAULT_DIMENSION_1X2 = 1;     private static final int DEFAULT_DIMENSION_2X2 = 2;     private static final int DEFAULT_DIMENSION_2X4 = 3;     private static final int DEFAULT_DIMENSION_4X4 = 4;     private long formId;     private DatabaseHelper databaseHelper = new DatabaseHelper(this);     private OrmContext ormContext;     private ProviderFormInfo formInfo;     @Override     public void onStart(Intent intent) {          HiLog.info(TAG, "onStart");         super.onStart(intent);         ormContext = databaseHelper.getOrmContext("FormBean", "FormDatabase.db", FormDatabase.class);         // 开启服务         Intent intentService = new Intent();         Operation operation = new Intent.OperationBuilder()                 .withBundleName(getBundleName())                 .withAbilityName(TimerAbility.class.getName())                 .build();         intentService.setOperation(operation);         startAbility(intentService);         super.setMainRoute(TimeCardSlice.class.getName());     }     /**      * 创建卡片时回调      *      * @param intent      * @return ProviderFormInfo      */     @Override     protected ProviderFormInfo onCreateForm(Intent intent) {          HiLog.info(TAG, "onCreateForm");         if (intent == null) {              return new ProviderFormInfo();         }         //获取卡片id         formId = INVALID_FORM_ID;         if (intent.hasParameter(AbilitySlice.PARAM_FORM_IDENTITY_KEY)) {              formId = intent.getLongParam(AbilitySlice.PARAM_FORM_IDENTITY_KEY, INVALID_FORM_ID);         } else {              return new ProviderFormInfo();         }         //获取卡片名称         String formName = "";         if (intent.hasParameter(AbilitySlice.PARAM_FORM_NAME_KEY)) {              formName = intent.getStringParam(AbilitySlice.PARAM_FORM_NAME_KEY);         }         //获取卡片规格         int dimension = DEFAULT_DIMENSION_2X2;         if (intent.hasParameter(AbilitySlice.PARAM_FORM_DIMENSION_KEY)) {              dimension = intent.getIntParam(AbilitySlice.PARAM_FORM_DIMENSION_KEY, DEFAULT_DIMENSION_2X2);         }         int layoutId = ResourceTable.Layout_form_image_with_info_time_2_2;         if (dimension == DEFAULT_DIMENSION_2X4) {              layoutId = ResourceTable.Layout_form_image_with_info_time_2_4;         }else if (dimension == DEFAULT_DIMENSION_1X2){              layoutId = ResourceTable.Layout_form_image_with_info_time_1_2;         }         formInfo = new ProviderFormInfo(layoutId, this);         //存储卡片信息         FormBean formBean = new FormBean(formId, formName, dimension);         ComponentProvider componentProvider = ComponentProviderUtils.getComponentProvider(formBean, this);         formInfo.mergeActions(componentProvider);         if (ormContext == null) {              ormContext = databaseHelper.getOrmContext("FormBean", "FormDatabase.db", FormDatabase.class);         }         try {              DatabaseUtils.insertForm(formBean, ormContext);         } catch (Exception e) {              DatabaseUtils.deleteFormData(formBean.getFormId(), ormContext);         }         return formInfo;     }     /**      * 更新卡片时回调      *      * @param formId      */     @Override     protected void onUpdateForm(long formId) {          HiLog.info(TAG, "onUpdateForm");         super.onUpdateForm(formId);     }     /**      * 请求删除卡片时回调      *      * @param formId      */     @Override     protected void onDeleteForm(long formId) {          HiLog.info(TAG, "onDeleteForm: formId=" + formId);         super.onDeleteForm(formId);         DatabaseUtils.deleteFormData(formId, ormContext);     }     @Override     protected void onActive() {          HiLog.info(TAG, "onActive");         super.onActive();     }     @Override     protected void onInactive() {          HiLog.info(TAG, "onInactive");         super.onInactive();     }     @Override     protected void onBackground() {          HiLog.info(TAG, "onBackground");         super.onBackground();     }     @Override     protected void onStop() {          HiLog.info(TAG, "onStop");         super.onStop();     }     @Override     protected void onForeground(Intent intent) {          HiLog.info(TAG, "onForeground");         super.onForeground(intent);     }     @Override     protected void onOrientationChanged(AbilityInfo.DisplayOrientation displayOrientation) {          super.onOrientationChanged(displayOrientation);     } } 

TimeCardSlice.java:

public class TimeCardSlice extends AbilitySlice {      private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, TimeCardSlice.class.getName());     private static final Long PERIOD = 1000L;     private Text monthText;     private Text dayText;     private Text hourText;     private Text minText;     private Text secondText;     private Text weekText;     private EventRunner eventRunner;     private MyEventHandler myEventHandler;     private Timer timer;     private Runnable runnable = new Runnable() {          private void initHandler() {              eventRunner = EventRunner.getMainEventRunner();             if (eventRunner == null) {                  return;             }             myEventHandler = new MyEventHandler(eventRunner);         }         @Override         public void run() {              initHandler();         }     };     @Override     protected void onStart(Intent intent) {          super.onStart(intent);         super.setUIContent(ResourceTable.Layout_form_image_with_info_time_2_2);         initComponent();         initData();         startTimer();     }     // 计时器刷新数据     private void startTimer() {          timer = new Timer();         timer.schedule(new TimerTask() {              @Override             public void run() {                  runnable.run();                 myEventHandler.sendEvent(1);             }         }, 0, PERIOD);     }     private void initComponent() {          monthText = (Text) findComponentById(ResourceTable.Id_month);         dayText = (Text) findComponentById(ResourceTable.Id_day);         weekText = (Text) findComponentById(ResourceTable.Id_week);         hourText = (Text) findComponentById(ResourceTable.Id_hour);         minText = (Text) findComponentById(ResourceTable.Id_min);         secondText = (Text) findComponentById(ResourceTable.Id_second);     }     private void initData() {          //获取日期         String currentDate = DateUtils.getCurrentDate("yyyy-MM-dd");         String[] split = currentDate.split("-");         monthText.setText(split[1]);         dayText.setText(split[2]);         //获取时间         Calendar calendar = Calendar.getInstance();         int hour = calendar.get(Calendar.HOUR_OF_DAY);         hourText.setText(intToString(hour));         int min = calendar.get(Calendar.MINUTE);         minText.setText(intToString(min));         int second = calendar.get(Calendar.SECOND);         secondText.setText(intToString(second));         //获取星期         int week = calendar.get(Calendar.DAY_OF_WEEK);         weekText.setText(getWeek(this,week));     }     private class MyEventHandler extends EventHandler {          public MyEventHandler(EventRunner runner) throws IllegalArgumentException {              super(runner);         }         @Override         protected void processEvent(InnerEvent event) {              super.processEvent(event);             int eventId = event.eventId;             if (eventId == 1) {                  initData();             }         }     }     @Override     protected void onActive() {          super.onActive();     }     @Override     protected void onForeground(Intent intent) {          super.onForeground(intent);     }     @Override     protected void onStop() {          super.onStop();         timer.cancel();     } } 

FormBean.java:

@Entity(tableName = "formBean") public class FormBean extends OrmObject {      @PrimaryKey()     private Long formId;     private String formName;     private Integer dimension;     public FormBean(Long formId, String formName, Integer dimension) {          this.formId = formId;         this.formName = formName;         this.dimension = dimension;     }     public FormBean() {      }     public Long getFormId() {          return formId;     }     public void setFormId(Long formId) {          this.formId = formId;     }     public String getFormName() {          return formName;     }     public void setFormName(String formName) {          this.formName = formName;     }     public Integer getDimension() {          return dimension;     }     public void setDimension(Integer dimension) {          this.dimension = dimension;     } } 

TimerAbility.java:

public class TimerAbility extends Ability {      private static final HiLogLabel TAG = new HiLogLabel(HiLog.LOG_APP, 0x0, "TAG---Service");     private static final long PERIOD = 1000L;     private static final int NOTIFICATION_ID = 1001;     private DatabaseHelper databaseHelper = new DatabaseHelper(this);     private OrmContext ormContext;     @Override     protected void onStart(Intent intent) {          HiLog.info(TAG, "onStart");         ormContext = databaseHelper.getOrmContext("FormBean", "FormDatabase.db", FormDatabase.class);         startTimer();         super.onStart(intent);     }     private void startTimer(){          Timer timer = new Timer();         timer.schedule(new TimerTask() {              @Override             public void run() {                  upDateFormBean();             }         },0,PERIOD);     }     private void upDateFormBean() {          OrmPredicates ormPredicates = new OrmPredicates(FormBean.class);         List<FormBean> beanList = ormContext.query(ormPredicates);         if (beanList.size() <= 0) {              return;         }         for (FormBean formBean : beanList) {              //更新卡片信息             ComponentProvider componentProvider = ComponentProviderUtils.getComponentProvider(formBean,this);             try {                  updateForm(formBean.getFormId(),componentProvider);             } catch (FormException e) {                  DatabaseUtils.deleteFormData(formBean.getFormId(),ormContext);             }         }     }     private void notice(){          NotificationRequest request = new NotificationRequest(NOTIFICATION_ID);         request.setAlertOneTime(true);         NotificationRequest.NotificationNormalContent normalContent = new NotificationRequest.NotificationNormalContent();         normalContent.setText(DateUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss"));         NotificationRequest.NotificationContent content = new NotificationRequest.NotificationContent(normalContent);         request.setContent(content);         keepBackgroundRunning(NOTIFICATION_ID,request);     }     @Override     protected void onBackground() {          HiLog.info(TAG, "onBackground");         super.onBackground();     }     @Override     protected void onStop() {          HiLog.info(TAG, "onStop");         super.onStop();     } } 

FormDatabase.java:

@Database(entities = { FormBean.class}, version = 1) public abstract class FormDatabase extends OrmDatabase {  } 

 ComponentProviderUtils.java:

public class ComponentProviderUtils {      private static Context mContext;     private static final int DIMENSION_1X2 = 1;     private static final int DIMENSION_2X2 = 2;     private static final int DIMENSION_2X4 = 3;     private static final int DIMENSION_4X4 = 4;     /**      * 获取ComponentProvider      *      * @param formBean      * @param context      * @return ComponentProvider      */     public static ComponentProvider getComponentProvider(FormBean formBean, Context context){          mContext = context;         int layoutId = ResourceTable.Layout_form_image_with_info_time_2_2;         if (formBean.getDimension() == DIMENSION_2X4){              layoutId = ResourceTable.Layout_form_image_with_info_time_2_4;         }else if (formBean.getDimension() == DIMENSION_1X2){              layoutId = ResourceTable.Layout_form_image_with_info_time_1_2;         }         ComponentProvider componentProvider =new ComponentProvider(layoutId,context);         setComponentProvider(componentProvider);         return componentProvider;     }     /**      * 设置信息      *      * @param componentProvider      */     private static void setComponentProvider(ComponentProvider componentProvider) {          Calendar instance = Calendar.getInstance();         // 时分秒         int hour = instance.get(Calendar.HOUR_OF_DAY);         int min = instance.get(Calendar.MINUTE);         int second = instance.get(Calendar.SECOND);         componentProvider.setText(ResourceTable.Id_hour,intToString(hour));         componentProvider.setText(ResourceTable.Id_min,intToString(min));         componentProvider.setText(ResourceTable.Id_second,intToString(second));         // 星期         int week = instance.get(Calendar.DAY_OF_WEEK);         String weekString = getWeek(week);         componentProvider.setText(ResourceTable.Id_week,weekString);         // 日期         String currentDate = DateUtils.getCurrentDate("yyyy-MM-dd");         String[] split = currentDate.split("-");         componentProvider.setText(ResourceTable.Id_month,split[1]);         componentProvider.setText(ResourceTable.Id_day,split[2]);     }     public static String intToString(int time) {          if (String.valueOf(time).length() < 2){              return "0"+time;         }else {              return time+"";         }     }     //获取星期     public static String getWeek(int week) {          int stringId;         switch (week) {              case 1:                 stringId = ResourceTable.String_SUNDAY;                 break;             case 2:                 stringId = ResourceTable.String_MONDAY;                 break;             case 3:                 stringId = ResourceTable.String_TUESDAY;                 break;             case 4:                 stringId = ResourceTable.String_WEDNESDAY;                 break;             case 5:                 stringId = ResourceTable.String_THURSDAY;                 break;             case 6:                 stringId = ResourceTable.String_FRIDAY;                 break;             case 7:                 stringId = ResourceTable.String_SATURDAY;                 break;             default:                 stringId = ResourceTable.String_SUNDAY;                 break;         }         return mContext.getString(stringId);     } } 

DatabaseUtils.java:

public class DatabaseUtils {      /**      * 添加卡片信息到数据库      *      * @param formBean      * @param ormContext      */     public static void insertForm(FormBean formBean, OrmContext ormContext){          ormContext.insert(formBean);         ormContext.flush();     }     /**      * 删除卡片信息      *      * @param formId      * @param ormContext      */     public static void deleteFormData(long formId,OrmContext ormContext){          OrmPredicates where = ormContext.where(FormBean.class);         where.equalTo("formId",formId);         List<FormBean> query = ormContext.query(where);         if (!query.isEmpty()){              ormContext.delete(query.get(0));             ormContext.flush();         }     } } 

DateUtils.java:

public class DateUtils {      /**      * 获取当前日期      *      * @param format format      * @return 日期      */     public static String getCurrentDate(String format) {          DateFormat dateFormat = new SimpleDateFormat(format);         Date date = new Date();         String formatDate = dateFormat.format(date);         return formatDate;     }     //获取星期     public static String getWeek(Context context, int week) {          int stringId;         switch (week) {              case 1:                 stringId = ResourceTable.String_SUNDAY;                 break;             case 2:                 stringId = ResourceTable.String_MONDAY;                 break;             case 3:                 stringId = ResourceTable.String_TUESDAY;                 break;             case 4:                 stringId = ResourceTable.String_WEDNESDAY;                 break;             case 5:                 stringId = ResourceTable.String_THURSDAY;                 break;             case 6:                 stringId = ResourceTable.String_FRIDAY;                 break;             case 7:                 stringId = ResourceTable.String_SATURDAY;                 break;             default:                 stringId = ResourceTable.String_SUNDAY;                 break;         }         return context.getString(stringId);     } } 

git地址:https://gitee.com/fzyme_admin/time-card.git

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

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

https://harmonyos.51cto.com

滇ICP备2023000592号-31