#星光计划2.0# HarmonyOS 项目实战之通讯录Demo(JS) 原创 精华
作者:彭为杰
【本文正在参与51CTO HarmonyOS技术社区创作者激励计划-星光计划2.0】
1 简介
通讯录demo主要分为联系人界面、设置紧急联系人、服务卡片3个模块,分为Java
和JS
两个版本,本篇主要讲解用尽可能的用纯JS
去实现,实在无法实现的地方采用JS
与Java
结合。
1.1 原型
感兴趣的小伙伴,可以自己根据原型效果自己尝试着去实现【通讯录demo简易原型】
1.2 场景延伸
通过学习与练习本demo,可以延伸至以下场景
2 功能开发
2.1 联系人列表
2.1.1 实现效果
2.1.2 核心代码
参考:基于JS扩展的类Web开发范式-组件-容器组件-list
- 关键属性 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 三方跳转
2.2.1 实现效果
2.2.2 js和java通信
js
打开三方应用目前还不知道如何操作,我们通过js
调java
方法来实现跳转。
JS LocalParticleAbility
机制请看官方链接:API 6
开始支持
参考:JS LocalParticleAbility机制-概述
通过js
获取到java
接口
export default {
data: {
javaInterface: {}
},
onInit() {
console.log(TAG + " ;onInit())");
},
onShow() {
console.log(TAG + " ;onShow())");
// onInit生命周期中Java接口对象还未创建完成,请勿在onInit中调用。
this.javaInterface = createLocalParticleAbility('com.pvj.addresslistdemo.MyLocalParticleAbility');
}
onClickPhone() {
this.javaInterface.doDial(this.item_phone)
},
onClickMail() {
this.javaInterface.doMessage(this.item_phone)
}
}
java
实现
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;
}
/**
* 跳转系统拨打电话界面
*/
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 拨打电话与发送短信
/**
* 跳转系统拨打电话界面
*/
public void doDial(String destinationNum) {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction(IntentConstants.ACTION_DIAL) // 系统应用拨号盘
.withUri(Uri.parse("tel:" + destinationNum)) // 设置号码
.withFlags(2)
.build();
intent.setOperation(operation);
// 启动Ability
context.startAbility(intent, 10);
}
//发送短信
public void doMessage(String telephone) {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction(IntentConstants.ACTION_SEND_SMS)
.withUri(Uri.parse("smsto:" + telephone)) // 设置号码
.withFlags(Intent.FLAG_NOT_OHOS_COMPONENT)
.build();
intent.setOperation(operation);
context.startAbility(intent, 11);
}
2.3 紧急联系人
2.3.1 实现效果
2.3.2 js数据存储
js
关系型数据库: 优先用关系型数据库,发现 JS
从API Version 7
开始支持。
js
轻量级存储:
① 它是key-value的存储的方法,从 API Version 6
开始支持;
参考:数据管理-轻量级存储
② 麻烦的是:每次存数据前,需要取一次,再新增数据;
在实现服务卡片更新信息时,需要动态的更新数据,而java
的轻量级存储与JS
存储的不是同一目录,目录改成一致程序出错,最终只能采用js
与java
通信,由java
侧统一完成数据新增与插入。
2.3.3 java数据存储实现
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表示文件名,其取值不能为空,也不能包含路径,默认存储目录可以通过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入参类型为ohos.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;
//点击删除时弹出对话框
prompt.showDialog({
title: "操作提示",
message: "添加" + item.item_name + "为紧急联系人吗?",
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服务卡片
2.4.1 实现效果
2.4.2 创建卡片模板
2.4.3 卡片数据绑定
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;是否支持其他类型?比如数组
} 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": "紧急联系人",
"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 注意事项
Demo还有很多需要完善的地方
- 删除时,索引不会被删除;
-
索引想要自定义样式,目前实现不了;
-
运行在api为7的手机的bug,一开始莫名的#显示;
-
纯js实现一个应用,目前还是行不通;
-
js官方文档上,有些不是很完善和稳定,对入门选手极其不友好;
4 总结
有不对或者更优的处理技术方案请多多指教,共同学习,共同进步。
代码地址: https://gitee.com/guangdong-wangduoyu/addresslistdemo
更多原创内容请关注:开鸿 HarmonyOS 学院
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
开鸿老师对鸿蒙的热情还是一如既往的高,感谢老师分享
哈哈哈,还有更多的内容,感谢关注。