HarmonyOS 項(xiàng)目實(shí)戰(zhàn)之通訊錄Demo(JS)
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
1 簡介
通訊錄demo主要分為聯(lián)系人界面、設(shè)置緊急聯(lián)系人、服務(wù)卡片3個模塊,分為Java和JS兩個版本,本篇主要講解用盡可能的用純JS去實(shí)現(xiàn),實(shí)在無法實(shí)現(xiàn)的地方采用JS與Java結(jié)合。
1.1 原型
感興趣的小伙伴,可以自己根據(jù)原型效果自己嘗試著去實(shí)現(xiàn)【通訊錄demo簡易原型】。



1.2 場景延伸
通過學(xué)習(xí)與練習(xí)本demo,可以延伸至以下場景。



2 功能開發(fā)
2.1 聯(lián)系人列表
2.1.1 實(shí)現(xiàn)效果

2.1.2 核心代碼
參考:基于JS擴(kuò)展的類Web開發(fā)范式-組件-容器組件-list
關(guān)鍵屬性 indexer=“true”
- <!-- list -->
 - <list id="address_list" class="list-wrapper" indexer="true" indexerbubble="true" shapemode="rect"
 - initialindex="0">
 - <block for="{{ list_data }}">
 - <list-item section="{{ $item.item_section }}" class="todo-item">
 - <div class="item-wrapper" @click="onItemClick($item)" @longpress="onItemLongPress($item)">
 - <image class="item-icon" src="{{ $item.item_icon }}"></image>
 - <text class="item-name">{{ $item.item_name }}</text>
 - </div>
 - </list-item>
 - </block>
 - </list>
 
2.2 三方跳轉(zhuǎn)
2.2.1 實(shí)現(xiàn)效果

2.2.2 js和java通信
js打開三方應(yīng)用目前還不知道如何操作,我們通過js調(diào)java方法來實(shí)現(xiàn)跳轉(zhuǎn)。
JS LocalParticleAbility機(jī)制請看官方鏈接:API 6開始支持
參考:JS LocalParticleAbility機(jī)制-概述
通過js 獲取到j(luò)ava接口
- export default {
 - data: {
 - javaInterface: {}
 - },
 - onInit() {
 - console.log(TAG + " ;onInit())");
 - },
 - onShow() {
 - console.log(TAG + " ;onShow())");
 - // onInit生命周期中Java接口對象還未創(chuàng)建完成,請勿在onInit中調(diào)用。
 - this.javaInterface = createLocalParticleAbility('com.pvj.addresslistdemo.MyLocalParticleAbility');
 - }
 - onClickPhone() {
 - this.javaInterface.doDial(this.item_phone)
 - },
 - onClickMail() {
 - this.javaInterface.doMessage(this.item_phone)
 - }
 - }
 
java實(shí)現(xiàn)
- public class MyLocalParticleAbility implements LocalParticleAbility {
 - private static MyLocalParticleAbility instance;
 - Context applicationContext;
 - Context context;
 - private MyLocalParticleAbility(Context context) {
 - this.context = context;
 - this.applicationContext = context.getApplicationContext();
 - }
 - public static MyLocalParticleAbility getInstance(Context applicationContext) {
 - if (instance == null) {
 - instance = new MyLocalParticleAbility(applicationContext);
 - }
 - return instance;
 - }
 - /**
 - * 跳轉(zhuǎn)系統(tǒng)撥打電話界面
 - */
 - public void doDial(String destinationNum) {
 - ...
 - }
 - public void doMessage(String telephone) {
 - ....
 - }
 - }
 
LocalParticleAbility 需要 register與 deregister
- public class MainAbility extends AceAbility {
 - @Override
 - public void onStart(Intent intent) {
 - super.onStart(intent);
 - ....
 - MyLocalParticleAbility.getInstance(getContext()).register(this);
 - }
 - @Override
 - public void onStop() {
 - super.onStop();
 - MyLocalParticleAbility.getInstance(getContext()).deregister(this);
 - }
 - }
 
2.2.3 撥打電話與發(fā)送短信
- /**
 - * 跳轉(zhuǎn)系統(tǒng)撥打電話界面
 - */
 - public void doDial(String destinationNum) {
 - Intent intent = new Intent();
 - Operation operation = new Intent.OperationBuilder()
 - .withAction(IntentConstants.ACTION_DIAL) // 系統(tǒng)應(yīng)用撥號盤
 - .withUri(Uri.parse("tel:" + destinationNum)) // 設(shè)置號碼
 - .withFlags(2)
 - .build();
 - intent.setOperation(operation);
 - // 啟動Ability
 - context.startAbility(intent, 10);
 - }
 - //發(fā)送短信
 - public void doMessage(String telephone) {
 - Intent intent = new Intent();
 - Operation operation = new Intent.OperationBuilder()
 - .withAction(IntentConstants.ACTION_SEND_SMS)
 - .withUri(Uri.parse("smsto:" + telephone)) // 設(shè)置號碼
 - .withFlags(Intent.FLAG_NOT_OHOS_COMPONENT)
 - .build();
 - intent.setOperation(operation);
 - context.startAbility(intent, 11);
 - }
 
2.3 緊急聯(lián)系人
2.3.1 實(shí)現(xiàn)效果

2.3.2 js數(shù)據(jù)存儲
js關(guān)系型數(shù)據(jù)庫: 優(yōu)先用關(guān)系型數(shù)據(jù)庫,發(fā)現(xiàn) JS從API Version 7開始支持。
js輕量級存儲:
① 它是key-value的存儲的方法,從 API Version 6 開始支持;
參考:數(shù)據(jù)管理-輕量級存儲
② 麻煩的是:每次存數(shù)據(jù)前,需要取一次,再新增數(shù)據(jù);
在實(shí)現(xiàn)服務(wù)卡片更新信息時,需要動態(tài)的更新數(shù)據(jù),而java的輕量級存儲與JS存儲的不是同一目錄,目錄改成一致程序出錯,最終只能采用js與java通信,由java側(cè)統(tǒng)一完成數(shù)據(jù)新增與插入。
2.3.3 java數(shù)據(jù)存儲實(shí)現(xiàn)
java代碼:
- public class MyLocalParticleAbility implements LocalParticleAbility {
 - private static MyLocalParticleAbility instance;
 - private static final HiLogLabel TAG = new HiLogLabel(HiLog.DEBUG, 0x0, MyLocalParticleAbility.class.getName());
 - Preferences preferences;
 - public static final String KEY = "key_list";
 - Context applicationContext;
 - Context context;
 - private MyLocalParticleAbility(Context context) {
 - this.context = context;
 - this.applicationContext = context.getApplicationContext();
 - DatabaseHelper databaseHelper = new DatabaseHelper(applicationContext);
 - String fileName = "main_list.xml";
 - // fileName表示文件名,其取值不能為空,也不能包含路徑,默認(rèn)存儲目錄可以通過context.getPreferencesDir()獲取。
 - preferences = databaseHelper.getPreferences(fileName);
 - }
 - public static MyLocalParticleAbility getInstance(Context applicationContext) {
 - if (instance == null) {
 - instance = new MyLocalParticleAbility(applicationContext);
 - }
 - return instance;
 - }
 - public String getContactPersonList() {
 - // context入?yún)㈩愋蜑閛hos.app.Context。
 - String preferencesString = preferences.getString(KEY, "");
 - HiLog.info(TAG, "getContactPersonList preferencesString : " + preferencesString);
 - return preferencesString;
 - }
 - public void addContactPersonList(String content) {
 - HiLog.info(TAG, "addContactPersonList content : " + content);
 - preferences.putString(KEY, content);
 - preferences.flushSync();
 - }
 - }
 
js代碼:
- import prompt from '@system.prompt';
 - onItemLongPress(item) {
 - console.log(TAG + " ;onItemLongPress:" + item.item_name);
 - let THIS = this;
 - //點(diǎn)擊刪除時彈出對話框
 - prompt.showDialog({
 - title: "操作提示",
 - message: "添加" + item.item_name + "為緊急聯(lián)系人嗎?",
 - buttons: [{
 - "text": "確定",
 - "color": ""
 - },
 - {
 - "text": "取消",
 - "color": ""
 - }],
 - success: function (data) {
 - if (data.index == 0) {
 - THIS.addContactPersonList(item);
 - }
 - }
 - });
 - }
 - async addContactPersonList(item) {
 - let content = await this.getContactPersonList();
 - console.info(TAG + "addContactPersonList content: " + content);
 - let list = []
 - if(content != ""){
 - list = JSON.parse(content);
 - }
 - list.push(item);
 - let temp = JSON.stringify(list);
 - console.info(TAG + "addContactPersonList temp: " + temp);
 - this.javaInterface.addContactPersonList(temp).then();
 - return true
 - // store.putSync(key, temp);
 - },
 - async getContactPersonList() {
 - let ret = await this.javaInterface.getContactPersonList()
 - console.info(TAG + "getContactPersonList ret:" + ret);
 - return ret
 - }
 
2.4 js服務(wù)卡片
2.4.1 實(shí)現(xiàn)效果
2.4.2 創(chuàng)建卡片模板
2.4.3 卡片數(shù)據(jù)綁定
- public ProviderFormInfo bindFormData(long formId) {
 - HiLog.info(TAG, "bind form data");
 - ZSONObject zsonObject = new ZSONObject();
 - String contactPersonList = MyLocalParticleAbility.getInstance(context.getApplicationContext()).getContactPersonList();
 - JSONArray jsonArray = JSON.parseArray(contactPersonList);
 - for (int i = 0; i < jsonArray.size(); i++) {
 - String name = jsonArray.getJSONObject(i).getString("item_name");
 - String phone = jsonArray.getJSONObject(i).getString("item_phone");
 - if (i == 0) {
 - zsonObject.put("titleText", name);
 - zsonObject.put("contentText", phone);
 - } else if (i == 1) {
 - zsonObject.put("titleText1", name);
 - zsonObject.put("contentText1", phone); //傳遞的是string;是否支持其他類型?比如數(shù)組
 - } else {
 - break;
 - }
 - HiLog.info(TAG, "bind form data :" + jsonArray.getJSONObject(i).get("item_name"));
 - HiLog.info(TAG, "bind form data :" + jsonArray.getJSONObject(i).get("item_phone"));
 - }
 - ProviderFormInfo providerFormInfo = new ProviderFormInfo();
 - providerFormInfo.setJsBindingData(new FormBindingData(zsonObject));
 - return providerFormInfo;
 - }
 
2.4.4 事件處理
- {
 - "data": {
 - "appName": "緊急聯(lián)系人",
 - "contactPersonList": "",
 - "titleText": "Title",
 - "contentText": "Introduction",
 - "titleText1": "",
 - "contentText1": "",
 - "actionName1": "Action 1",
 - "actionName2": "Action 2"
 - },
 - "actions": {
 - "routerEvent": {
 - "action": "router",
 - "abilityName": "com.pvj.addresslistdemo.MainAbility",
 - "params": {
 - "message": "weather"
 - }
 - },
 - "callEvent1": {
 - "action": "message",
 - "params": {
 - "mAction": "callEvent1"
 - }
 - },
 - "callEvent2": {
 - "action": "message",
 - "params": {
 - "mAction": "callEvent2" //
 - }
 - }
 - }
 - }
 
call 就是前面的播打電話的方法
- @Override
 - public void onTriggerFormEvent(long formId, String message) {
 - HiLog.info(TAG, "handle card click event." + message);
 - ZSONObject zsonObject = ZSONObject.stringToZSON(message);
 - // Do something here after receive the message from js card
 - ZSONObject result = new ZSONObject();
 - switch (zsonObject.getString("mAction")) {
 - case "callEvent1":
 - call(0);
 - break;
 - case "callEvent2":
 - call(1);
 - break;
 - }
 - }
 
3 注意事項(xiàng)
Demo還有很多需要完善的地方
刪除時,索引不會被刪除;
索引想要自定義樣式,目前實(shí)現(xiàn)不了;
運(yùn)行在api為7的手機(jī)的bug,一開始莫名的#顯示;
純js實(shí)現(xiàn)一個應(yīng)用,目前還是行不通;
js官方文檔上,有些不是很完善和穩(wěn)定,對入門選手極其不友好。
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)




















 
 
 



 
 
 
 