人工智能

HarmonyOS 项目实战之通讯录(Java)

时间:2010-12-5 17:23:32  作者:应用开发   来源:应用开发  查看:  评论:0
内容摘要:想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com1 简介通讯录demo主要分为联系人界面、设置紧急联系人、服务卡片3个模块,分为Java和

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

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

https://harmonyos.51cto.com

1 简介

通讯录demo主要分为联系人界面、设置紧急联系人、目实服务卡片3个模块,通讯分为Java和JS两个版本,目实本篇主要讲解用尽可能的通讯用Java去实现。

1.1 原型

感兴趣的目实小伙伴,可以自己根据原型效果自己尝试着去实现【通讯录demo简易原型】。通讯

1.2 场景示例

通过学习与练习本demo,目实可以延伸至以下场景。通讯

1.3 项目实战

《HarmonyOS 项目实战之通讯录Demo(JS)》

《HarmonyOS 项目实战之通讯录(Java)》

《HarmonyOS 项目实战之新闻头条(ArkUI-TS》

2 功能开发

2.1 联系人列表

2.1.1 实现效果

2.1.2 核心代码

参考:ListContainer-常用组件开发指导-Java UI框架-UI-开发-HarmonyOS应用开发

ListContainer设置StickyContactProvider适配器 HeaderDecor头部联动效果设置 ContactData数据处理相关类,目实sortContactData方法用于排序等数据处理 ContactData categoryData = ContactData.get();     categoryData.sortContactData();     contactList = (ListContainer) findComponentById(ResourceTable.Id_contactList);     Text headerText = (Text) findComponentById(ResourceTable.Id_sticky_text);     List<ContactBean> dataList = categoryData.getResultList();     mStickyContactProvider = new StickyContactProvider(this,通讯 dataList);     contactList.setItemProvider(mStickyContactProvider);     HeaderDecor headerDecor = new HeaderDecor(contactList, headerText); 

 sortContactData方法数据处理,排序,目实字母索引:

public void sortContactData() {      List<ContactBean> mContactList = new ArrayList<>();     Map<String,通讯 String> map = new HashMap<>();     for (ContactBean contactBean : mContactBeans) {          String pinyin = Utils.getPingYin(contactBean.getName());         map.put(pinyin, contactBean.getName());         contactBean.setNamepy(pinyin);         mContactList.add(contactBean);     }     mContactList.sort(new ContactComparator());     characterList = new ArrayList<>();     resultList = new ArrayList<>();     for (ContactBean contactBean : mContactList) {          String namepy = contactBean.getNamepy();         String character = (namepy.charAt(0) + "").toUpperCase(Locale.ENGLISH);         if (!characterList.contains(character)) {              if (character.hashCode() >= "A".hashCode() && character.hashCode() <= "Z".hashCode()) {  // 是字母                 characterList.add(character);                 resultList.add(new ContactBean(character, ContactBean.ITEM_TYPE.ITEM_TYPE_CHARACTER.ordinal()));             } else {                  if (!characterList.contains("#")) {                      characterList.add("#");                     resultList.add(new ContactBean("#", ContactBean.ITEM_TYPE.ITEM_TYPE_CHARACTER.ordinal()));                 }             }         }         resultList.add(new ContactBean(contactBean.getName(), contactBean.getTelephone(), map.get(namepy), ContactBean.ITEM_TYPE.ITEM_TYPE_CONTACT.ordinal()));     } } 

2.2 数据的增删改查

2.2.1 实现效果

2.2.2 增删改查实现

ListContainer删除实现

categoryData.deleteContactBeans(item); categoryData.sortContactData(); mStickyContactProvider.setDataListChanged(categoryData.getResultList()); 

 随机添加一个联系人

categoryData.addContactBean("胡六一", "15269856587"); categoryData.sortContactData(); mStickyContactProvider.setDataListChanged(categoryData.getResultList()); 

 ContactData数据处理效果类,实现数据增删改查

// Generate the javaBean of ContactData public static ContactData get() {      return new ContactData(); } public List<ContactBean> getDefaultContactBeans() {      return mDefaultContactBeans; } public List<ContactBean> getContactBeans() {      return mContactBeans; } public void addContactBean(String name,目实 String phone) {      mContactBeans.add(new ContactBean(name, phone)); } public List<ContactBean> deleteContactBeans(ContactBean item) {      mContactBeans.removeIf(contactBean -> contactBean.getName().equals(item.getName()));     return mContactBeans; } public List<ContactBean> getResultList() {      return resultList; } public List<String> getCharacterList() {      return characterList; } public int getScrollPosition(String character) {      if (characterList.contains(character)) {          for (int i = 0; i < resultList.size(); i++) {              if (resultList.get(i).getCharacter().equals(character)) {                  return i;             }         }     }     return -1; // -1不会滑动 } 

2.2.3 紧急联系人数据存储

轻量级数据存储:轻量级数据存储概述-轻量级数据存储-数据管理-开发-HarmonyOS应用开发

Key-Value数据结构

一种键值结构数据类型。Key是不重复的关键字,Value是数据值。

运作机制

本模块提供轻量级数据存储的操作类,应用通过这些操作类完成数据库操作。服务器托管 借助DatabaseHelper API,应用可以将指定文件的内容加载到Preferences实例,每个文件最多有一个Preferences实例,系统会通过静态容器将该实例存储在内存中,直到应用主动从内存中移除该实例或者删除该文件。 获取到文件对应的Preferences实例后,应用可以借助Preferences API,从Preferences实例中读取数据或者将数据写入Preferences实例,通过flush或者flushSync将Preferences实例持久化。

核心代码实现

添加紧急联系人,并通知java卡片更新。

ZSONObject zsonObject = new ZSONObject(); zsonObject.put("urgent1", nameTf1.getText()); zsonObject.put("urgentPhone1", phoneTf1.getText()); zsonObject.put("urgent2", nameTf2.getText()); zsonObject.put("urgentPhone2", phoneTf2.getText()); PreferenceUtils.putString(getContext(),"urgentPerson", ZSONObject.toZSONString(zsonObject)); FormBindingData formBindingData = new FormBindingData(zsonObject); ((ContactPersonAbility) getAbility()).confirmUpdateForm(formBindingData); 

 PreferenceUtils封装工具类,实现数据存储。

public class PreferenceUtils {      private static String PREFERENCE_FILE_NAME = "prefrence_file";     private static Preferences preferences;     private static DatabaseHelper databaseHelper;     private static Preferences.PreferencesObserver mPreferencesObserver;     private static void initPreference(Context context) {          if (databaseHelper == null) {              databaseHelper = new DatabaseHelper(context);         }         if (preferences == null) {              preferences = databaseHelper.getPreferences(PREFERENCE_FILE_NAME);         }     }     //存放、获取时传入的context必须是同一个context,否则存入的数据无法获取     public static void putString(Context context, String key, String value) {          initPreference(context);         preferences.putString(key, value);         preferences.flush();     }     /**      * @param context 上下文      * @param key     键      * @return 获取的String 默认值为:null      */     public static String getString(Context context, String key) {          initPreference(context);         return preferences.getString(key, null);     }     public static String getString(Context context, String key, String d) {          initPreference(context);         return preferences.getString(key, d);     }     public static void putInt(Context context, String key, int value) {          initPreference(context);         preferences.putInt(key, value);         preferences.flush();     }     /**      * @param context 上下文      * @param key     键      * @return 获取int的默认值为:-1      */     public static int getInt(Context context, String key) {          initPreference(context);         return preferences.getInt(key, -1);     }     public static void putLong(Context context, String key, long value) {          initPreference(context);         preferences.putLong(key, value);         preferences.flush();     }     /**      * @param context 上下文      * @param key     键      * @return 获取long的默认值为:-1      */     public static long getLong(Context context, String key) {          initPreference(context);         return preferences.getLong(key, -1L);     }     public static void putBoolean(Context context, String key, boolean value) {          initPreference(context);         preferences.putBoolean(key, value);         preferences.flush();     }     /**      * @param context 上下文      * @param key     键      * @return 获取boolean的默认值为:false      */     public static boolean getBoolean(Context context, String key) {          initPreference(context);         return preferences.getBoolean(key, false);     }     public static void putFloat(Context context, String key, float value) {          initPreference(context);         preferences.putFloat(key, value);         preferences.flush();     }     /**      * @param context 上下文      * @param key     键      * @return 获取float的默认值为:0.0      */     public static float getFloat(Context context, String key) {          initPreference(context);         return preferences.getFloat(key, 0.0F);     }     public static void putStringSet(Context context, String key, Set<String> set) {          initPreference(context);         preferences.putStringSet(key, set);         preferences.flush();     }     /**      * @param context 上下文      * @param key     键      * @return 获取set集合的默认值为:null      */     public static Set<String> getStringSet(Context context, String key) {          initPreference(context);         return preferences.getStringSet(key, null);     }     public static boolean deletePreferences(Context context) {          initPreference(context);         boolean isDelete = databaseHelper.deletePreferences(PREFERENCE_FILE_NAME);         return isDelete;     }     public static void registerObserver(Context context, Preferences.PreferencesObserver preferencesObserver) {          initPreference(context);         mPreferencesObserver = preferencesObserver;         preferences.registerObserver(mPreferencesObserver);     }     public static void unregisterObserver() {          if (mPreferencesObserver != null) {              // 向preferences实例注销观察者             preferences.unregisterObserver(mPreferencesObserver);         }     } 

2.3 第三方跳转

2.3.1 实现效果

2.3.2 拨打电话与发送短信

/**      * 跳转系统短信      */     private void doMessage(String telephone) {          Intent intent = new Intent();         Operation operation = new Intent.OperationBuilder() //                .withAction("android.intent.action.SENDTO") // Android写法 android.intent.action.SENDTO                 .withAction(IntentConstants.ACTION_SEND_SMS)                 .withUri(Uri.parse("smsto:" + telephone)) // 设置号码                 .withFlags(Intent.FLAG_NOT_OHOS_COMPONENT)                 .build();         intent.setOperation(operation);         context.startAbility(intent, 11);     }     /**      * 申请拨打电话权限      */     private boolean requestPermissions() {          if (context.verifySelfPermission("android.permission.CALL_PHONE") != IBundleManager.PERMISSION_GRANTED) {              // 应用未被授予权限             if (context.canRequestPermission("android.permission.CALL_PHONE")) {                  // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)                 context.requestPermissionsFromUser(new String[]{ "android.permission.CALL_PHONE"}, 100);             }             return false;         } else {              // 权限已被授予             return true;         }     }     /**      * 直接拨打电话      * 需要申请权限      */     private void doCall(String destinationNum) {          if (!requestPermissions()) {              return;         }         Intent intent = new Intent();         Operation operation = new Intent.OperationBuilder()                 .withAction("android.intent.action.CALL") // 系统应用拨号盘                 .withUri(Uri.parse("tel:" + destinationNum)) // 设置号码                 .withFlags(2)                 .build();         intent.setOperation(operation);         // 启动Ability         context.startAbility(intent, 10);     }     /**      * 跳转系统拨打电话界面      */     private void doDial(String destinationNum) {          Intent intent = new Intent();         Operation operation = new Intent.OperationBuilder()                 .withAction(IntentConstants.ACTION_DIAL) // 系统应用拨号盘 //                .withBundleName(context.getCallingBundle()) // 应用拨号选择器                 .withUri(Uri.parse("tel:" + destinationNum)) // 设置号码                 .withFlags(2)                 .build();         intent.setOperation(operation);         // 启动Ability         context.startAbility(intent, 10);     } 

2.4 JS服务卡片

2.4.1 实现效果

2.4.2 创建卡片模板

使用DevEco Studio创建卡片工程

创建成功后,源码下载在config.json的module中会生成js模块,用于对应卡片的js相关资源,配置示例如下:

"js": [   {      "pages": [       "pages/index/index"     ],     "name": "widget",     "window": {        "designWidth": 720,       "autoDesignWidth": true     },     "type": "form"   } ] 

 config.json文件“abilities”配置forms模块细节如下:

"name": "com.huhu.contact.ContactPersonAbility", "icon": "$media:icon", "description": "$string:contactpersonability_description", "formsEnabled": true, "label": "$string:contact_ContactPersonAbility", "type": "page", "forms": [   {      "jsComponentName": "widget",     "isDefault": true,     "scheduledUpdateTime": "10:30",     "defaultDimension": "2*2",     "name": "widget",     "description": "This is a service widget",     "colorMode": "auto",     "type": "JS",     "supportDimensions": [       "2*2"     ],     "updateEnabled": true,     "updateDuration": 1   } ] 

 创建一个ContactPersonAbility,覆写卡片相关回调函数。

onCreateForm(Intent intent) onUpdateForm(long formId) onDeleteForm(long formId) onCastTempForm(long formId) onEventNotify(Map onTriggerFormEvent(long formId, String message) onAcquireFormState(Intent intent)

当卡片使用方请求获取卡片时,卡片提供方会被拉起并调用onCreateForm(Intent intent)回调,intent中会带有卡片ID、卡片名称和卡片外观规格信息,可按需获取使用。

开发JS卡片时,FormAbility可以继承AceAbility或Ability,继承Ability时,需在onStart()方法中额外设置路由信息。

2.4.3 卡片数据绑定

@Override  public ProviderFormInfo bindFormData() {       HiLog.info(TAG, "bind form data");      ProviderFormInfo providerFormInfo = new ProviderFormInfo();      String urgentPersonStr = PreferenceUtils.getString(context, "urgentPerson", "");      ZSONObject zsonObject = ZSONObject.stringToZSON(urgentPersonStr);      if (dimension == DEFAULT_DIMENSION_2X2) {           if (zsonObject != null) {               providerFormInfo.setJsBindingData(new FormBindingData(zsonObject));          }      }      return providerFormInfo;  } 

 2.4.4 卡片数据更新

public void confirmUpdateForm(FormBindingData formBindingData) {      FormControllerManager formControllerManager = FormControllerManager.getInstance(this);     List<Long> allFormIdFromSharePreference = formControllerManager.getAllFormIdFromSharePreference();     if (allFormIdFromSharePreference == null || allFormIdFromSharePreference.isEmpty()) return;     Long formId = allFormIdFromSharePreference.get(0);     try {          updateForm(formId,formBindingData);     } catch (FormException e) {          e.printStackTrace();     } 

 2.4.5 卡片事件处理

{    "data": {      "text_content": "Name",     "cardPrimaryText": "Contacts",     "cardSecondaryText": "+8612345678912",     "urgent1": "无",     "urgent2": "无",     "urgentPhone1": "+8612345678912",     "urgentPhone2": "+8612345678915"   },   "actions": {      "urgentCall1": {        "action": "message",       "params": {          "action": "urgentCall1",         "phoneNumber": "10086"       }     },     "urgentCall2": {        "action": "message",       "params": {          "action": "urgentCall2",         "phoneNumber": "15565339857"       }     },     "startMainRouter": {        "action": "router",       "abilityName": "com.huhu.contact.ContactPersonAbility"     }   } } 

卡片支持触发事件,覆写onTriggerFormEvent方法实现对事件的触发,doCall就是前面的播打电话的方法

@Override protected void onTriggerFormEvent(long formId, String message) {      super.onTriggerFormEvent(formId, message);     HiLog.info(loglabel, "onTriggerFormEvent: " + message);     FormControllerManager formControllerManager = FormControllerManager.getInstance(this);     FormController formController = formControllerManager.getController(formId);     formController.onTriggerFormEvent(formId, message);     ZSONObject params = ZSONObject.stringToZSON(message);     String action = params.getString("action");     String phoneNumber = params.getString("phoneNumber");     HiLog.info(loglabel, "onTriggerFormEvent: action:" + action);     String urgentPersonStr = PreferenceUtils.getString(this, "urgentPerson", "");     ZSONObject zsonObject = ZSONObject.stringToZSON(urgentPersonStr);     switch (action) {          case "urgentCall1":             String urgentPhone1 = zsonObject.getString("urgentPhone1");             doCall(urgentPhone1);             break;         case "urgentCall2":             String urgentPhone2 = zsonObject.getString("urgentPhone2");             doCall(urgentPhone2);             break;         default:             break;     } } 

3 注意事项

Demo还有很多需要完善的地方

滑动时,上滑头部联动效果,索引有时会错乱; 搜索功能未实现; 紧急联系人没有和列表数据联动。

4 总结

代码地址: https://gitee.com/hu-lingqing/contact-person.git

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

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

https://harmonyos.51cto.com

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap