2.0优化

Signed-off-by: weiyunxing <weiyunxing@huawei.com>
This commit is contained in:
weiyunxing 2022-03-24 16:40:22 +08:00
parent c5c71fc8e3
commit a850c46482
54 changed files with 674 additions and 909 deletions

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright (c) 2021 Huawei Device Co., Ltd.
<!-- Copyright (c) 2022 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

View File

@ -1,64 +1,87 @@
# applications_call
## 1. 简介
### 1.1 内容介绍:
基于系统平台能力设计和开发通话应用提供语音通话、视频通话、通话设置、移动网络设置、SIM卡管理设置、紧急拨号以及添加个人紧急信息的功能。从不同视角构建模型设计通话应用的架构确保在满足基本功能的同时确保安全、韧性、可靠、隐私等。
- [简介](#section11660541593)
- [架构图](#section78574815486)
- [目录](#section161941989596)
- [相关仓](#section1371113476307)
## 简介
基于系统平台能力设计和开发通话应用提供语音通话、视频通话、通话设置、移动网络设置、SIM卡管理设置、紧急拨号以及添加个人紧急信息的功能。从不同视角构建模型设计通话应用的架构确保在满足基本功能的同时确保安全、韧性、可靠、隐私等。
### 架构图
### 1.2 架构图介绍:
![img](./figures/callui_en.png)
## 目录
| 模块 | 层级 | 类名 | 作用 |
| ---- | ---- | ---- | ---- |
| FA-UI | 视图层 | Voice Calls FA | 主要提供语音通话相关用户交互界面 |
| FA-UI | 视图层 | video Calls FA | 主要提供视频通话相关用户交互界面 |
| FA-UI | 视图层 | video Calls FA | 主要提供视频通话相关用户交互界面 |
| FA-UI | 视图层 | Voice Calls FA | 主要提供语音通话相关用户交互界面 |
| FA-UI | 视图层 | video Calls FA | 主要提供视频通话相关用户交互界面 |
| FA-UI | 视图层 | video Calls FA | 主要提供视频通话相关用户交互界面 |
| FA-UI | 视图层 | video Calls FA | 主要提供视频通话相关用户交互界面 |
## 2. 目录
```
/applications
├── callui # 通话应用主Ability提供拉起应用入口
/applications_call
├── callui # 通话应用主Ability提供拉起应用入口
│ └── src
│ └── main
│ ├── ets # ets代码目录
│ ├── default
│ ├── assets # 图片目录
│ ├── assets # 图片资源
│ ├── common # 公共组件或方法配置目录
│ ├── components # 公共组件
│ ├── configs # 应用配置对象目录
│ ├── constant # 应用常量对象目
│ ├── constant # 应用常量对象目
│ ├── utils # 公共方法
│ ├── model # Model层代码目录
│ ├── pages # 通话页面目录
│ ├── ServiceAbilty # ServiceAbilty启动
│ ├── callManagerService.js # ServiceAbilty方法
│ ├── service.js # ServiceAbilty方法
│ ├── telephonyApi.js # ServiceAbilty方法
│ ├── resources # 资源目录
│ ├── config.json # 项目配置信息
| ├── app.ets # 全局ets逻辑和应用生命周期管理文件
│ ├── ServiceAbility # 服务ability
│ ├── callManagerService.ets # ServiceAbility方法
│ ├── service.ts # ServiceAbility方法
│ ├── telephonyApi.ets # ServiceAbility方法
│ ├── resources # 资源配置文件存放目录
| ├── base # 默认图片资源,字体大小,颜色资源存放目录
| ├── zh_CN # 中文语言场景资源内容存放目录
│ ├── config.json # 全局配置文件
├── doc # 使用说明目录
| ├── image # 使用说明图片资源
| ├── Instructions.md # 使用说明
├── mobiledatasettings # 移动数据设置
│ └── src
│ └── main
│ ├── ets # ets代码目录
│ ├── default
│ ├── pages # 移动数据页面目录
│ ├── resources # 资源目录
│ ├── config.json # 项目配置信息
│ ├── resources # 资源配置文件存放目录
| ├── base # 默认图片资源,字体大小,颜色资源存放目录
| ├── zh_CN # 中文语言场景资源内容存放目录
│ ├── config.json # 全局配置文件
├── figures # 架构图目录
│ └── callui_en.png # 架构设计图片
├── signature # 签名文件
│ └── com.ohos.callui.p7b # com.ohos.callui签名文件
│ └── callui_en.png # 架构设计图
├── signature # 签名证书文件目录
│ └── com.ohos.callui.p7b # 签名文件
├── LICENSE # 许可证
├── build.gradle # 全局编译配置文件
```
## 相关仓
系统应用
**applications_standard_call**
## 3. 使用说明
* 参见使用说明([使用说明](doc/Instructions.md)
## 4. 相关仓
* 系统应用
[**applications_call**](https://gitee.com/openharmony/applications_call)

View File

@ -64,8 +64,7 @@
"type": "pageAbility"
},
"pages": [
"pages/index",
"pages/conferenceManage"
"pages/index"
],
"name": ".MainAbility",
"window": {
@ -78,6 +77,9 @@
{
"name" : "ohos.permission.READ_CONTACTS"
},
{
"name" : "ohos.permission.SEND_MESSAGES"
},
{
"name": "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED"
}

View File

@ -30,7 +30,7 @@ const CALL_STATUS_INCOMING = 4;
const CALL_STATUS_DIALING = 2;
const CALL_STATUS_DISCONNECTED = 6;
const CALL_STATUS_DISCONNECTING = 7;
const events = ['callui.event.callEvent'];
const events = ['callui.event.callEvent', 'callui.event.click'];
/**
* class CallManagerService
@ -50,8 +50,10 @@ export default class CallManagerService {
* add callui app subscriber
*/
async addSubscriber() {
subscriber = await new Promise((resolve) => {
commonEvent.createSubscriber({events }, (err, data) => {
subscriber = await new Promise((resolve) => {
commonEvent.createSubscriber({
events
}, (err, data) => {
HiLog.i(TAG, "addSubscriber %s")
resolve(data);
});
@ -59,10 +61,16 @@ export default class CallManagerService {
commonEvent.subscribe(subscriber, (err, res) => {
if (err.code === 0) {
const obj = JSON.parse(res.data);
const {key} = obj;
if (key === 'getInitCallData') {
this.publishData(this.callData);
if (res.event === events[0]) {
const obj = JSON.parse(res.data);
if (obj && obj.key === 'getInitCallData') {
this.publishData(this.callData);
}
}
if (res.event === events[1]) {
const {callId,btnType} = res.parameters
this.btnclickAgent(callId, btnType)
}
} else {
HiLog.i(TAG, "callui service commonEvent.subscribe failed err : %s" + JSON.stringify(err))
@ -70,6 +78,30 @@ export default class CallManagerService {
});
}
/**
* click button agent
*
* @param { number } callId - call id
* @param { string } btnType - button type
*/
btnclickAgent(callId, btnType) {
HiLog.i(TAG, "btnType : %s" + btnType)
this.getMapObj(btnType, callId)
}
getMapObj(typeKey, callId) {
if (typeKey === 'answer') {
this.mTelephonyCall.acceptCall(callId)
this.startAbility(this.callData)
}
if (typeKey === 'reject') {
this.mTelephonyCall.rejectCall(callId)
}
if (typeKey === 'hangUp') {
this.mTelephonyCall.hangUpCall(callId)
}
}
/**
* add register listener
*/
@ -92,7 +124,7 @@ export default class CallManagerService {
*/
if ((callState === CALL_STATUS_INCOMING && this.callList.length === 1) || callState === CALL_STATUS_DIALING) {
this.startAbility(callData);
} else if (callState!== CALL_STATUS_DISCONNECTING){
} else if (callState !== CALL_STATUS_DISCONNECTING) {
this.publishData(callData);
}
}
@ -107,9 +139,10 @@ export default class CallManagerService {
want: {
bundleName: CALL_BUNDLE_NAME,
abilityName: ABILITY_NAME,
parameters: callData}
parameters: callData
}
}).then((data) => {
HiLog.i(TAG, "callUI service PA.startAbility data : %s" + JSON.stringify(data))
HiLog.i(TAG, "callUI service PA.startAbility data : %s")
}).catch((err) => {
HiLog.i(TAG, "callUI service PA.startAbility err : %s" + JSON.stringify(err))
});
@ -147,7 +180,7 @@ export default class CallManagerService {
isOrdered: false,
data: JSON.stringify(callData)
}, (res) => {
HiLog.i(TAG, "callUI service commonEvent.publish callback res : %s" + JSON.stringify(res))
HiLog.i(TAG, "callUI service commonEvent.publish callback res : %s")
});
}

View File

@ -50,9 +50,58 @@ export default class TelephonyApi {
HiLog.i(TAG,prefixLog + 'call.off unRegisterCallStateCallback' + JSON.stringify(err))
return;
}
HiLog.i(TAG,prefixLog + 'call.off unRegisterCallStateCallback' + JSON.stringify(res))
HiLog.i(TAG,prefixLog + 'call.off unRegisterCallStateCallback')
});
}
/**
* accept call
*
* @param { number } callId - call id
*/
public acceptCall = function (callId) {
call.answer(callId).then((res) => {
HiLog.i(TAG,prefixLog + "call.answer : %s")
}).catch((err) => {
HiLog.i(TAG, prefixLog + "call.answer catch : %s" + JSON.stringify(err))
})
}
/**
* reject call
*
* @param { number } callId - call id
*
* @param { boolean } isSendSms - is send sms
*
* @param { string } msg - message string
*/
public rejectCall = function (callId, isSendSms = false, msg = '') {
const rejectCallPromise = isSendSms ? call.reject(callId, {messageContent: msg}) : call.reject(callId);
rejectCallPromise.then((res) => {
HiLog.i(TAG,prefixLog + "then:rejectCall : %s")
})
.catch((err) => {
HiLog.i(TAG, prefixLog + "catch:rejectCall : %s" + JSON.stringify(err))
});
};
/**
* hang up Call
*
* @param { number } callId - call id
*
* @return { Object } promise object
*/
public hangUpCall = (callId) => new Promise((resolve, reject) => {
call.hangup(callId).then((res) => {
resolve(res);
HiLog.i(TAG, prefixLog + "then:hangUpCall : %s")
}).catch((err) => {
reject(err);
HiLog.i(TAG, prefixLog + "catch:hangUpCall : %s" + JSON.stringify(err))
});
});
}

View File

@ -13,6 +13,10 @@
* limitations under the License.
*/
/**
* @file: bottom button component
*/
import CallServiceProxy from '../../model/CallServiceProxy.ets';
import HiLog from '../utils/Hilog.ets';
@ -33,7 +37,9 @@ export default struct BottomBtn {
this.getImageList();
this.mCallServiceProxy = CallServiceProxy.getInstance();
}
/**
* get Image List
*/
private getImageList() {
this.imageList = [
{
@ -59,19 +65,6 @@ export default struct BottomBtn {
HiLog.i(TAG, "onHangUp this.callData.callId : ");
}
/**
* click to amplify
*/
async showAudio() {
try {
await this.mCallServiceProxy.setAudioDevice();
this.openSpeaker = !this.openSpeaker;
} catch (err) {
this.openSpeaker = !this.openSpeaker;
}
HiLog.i(TAG, "showAudio this.openSpeaker : %s" ,this.openSpeaker);
}
/**
* Image size
*/
@ -99,10 +92,6 @@ export default struct BottomBtn {
this.onHangUp();
}
if (type == 'speakerphone') {
// this.showAudio()
}
}
build() {
@ -126,7 +115,7 @@ export default struct BottomBtn {
}
.columnsGap(24)
.height(56)
.columnsTemplate('1fr 1fr 1fr ')
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr')
}
.useSizeType({

View File

@ -16,7 +16,7 @@
import CallServiceProxy from "../../model/CallServiceProxy";
import HiLog from '../utils/Hilog.ets';
const TAG = "DtmfBTn";
const TAG = "DtmfBtn";
@Component
export default struct DtmfBtn {
@ -25,7 +25,6 @@ export default struct DtmfBtn {
@Link dataList: any;
@Link textInput: string;
@Link textInputValue: string;
private item: any;
private mCallServiceProxy;
callData :any;

View File

@ -24,11 +24,11 @@ export default struct FuncBtn {
@State iconDisableUrl: string = '';
@State iconDefaultUrl: string = '';
@State iconActiveUrl: string = '';
@State isDisable: boolean = false;
@State @Watch('iconClassName') isActive: boolean = false;
@State @Watch('iconClassName') isDisable: boolean = false;
@State iconText: string= '';
btnClick: Function = null;
@State textColor: string = 'rgb(255, 255, 255)';
btnClick: Function = null;
/**
* Button group picture change control
@ -40,8 +40,6 @@ export default struct FuncBtn {
HiLog.i(TAG, "iconUrl this.isDisable : %s" + this.isDisable);
return this.iconDisableUrl;
}
HiLog.i(TAG, "show icon status : %s" + JSON.stringify(this.isDisable) + JSON.stringify( this.iconDisableUrl));
HiLog.i(TAG, "show icon status : %s" + JSON.stringify(this.isActive) + JSON.stringify(this.iconDefaultUrl));
return this.isActive && this.iconDefaultUrl ? this.iconActiveUrl : this.iconDefaultUrl;
}
@ -49,7 +47,7 @@ export default struct FuncBtn {
* Button group change picture
*/
changeBtn(type) {
HiLog.i(TAG, "changeBtn type : %s" + type);
HiLog.i(TAG, "changeBtn type : %s");
const BtnName = ['record', 'keep', 'video', 'mute'];
if (Method.includes(BtnName, type)) {
this.isActive = !this.isActive;
@ -70,6 +68,10 @@ export default struct FuncBtn {
this.textColor = '#007DFF';
return 'enable';
}
if(this.btnType == 'msg'){
this.textColor = '#8c8c8c';
return '';
}
this.textColor = 'rgb(255, 255, 255)';
HiLog.i(TAG, "iconClassName this.isDisable : " );
return 'default';

View File

@ -23,8 +23,7 @@ import ConferenceConst from '../constant/ConferenceConst.ets';
import BtnGroupConfig from '../configs/BtnGroupConfig.ets';
import HiLog from '../utils/Hilog.ets';
const TAG = "FuncBtnGroup";
const TAG = 'FuncBtnGroup';
const textMap =
{
'record': $r('app.string.recording'),
@ -39,7 +38,7 @@ const textMap =
@Component
export default struct FuncBtnGroup {
@Link @Watch ('updataBtnList') callData: any;
@Link @Watch ('updateBtnList') callData: any;
@Link callList: Array<any>;
@State count: number = 0;
@State btnList: Array<any> = [];
@ -64,39 +63,32 @@ export default struct FuncBtnGroup {
v.iconText = textMap[v.type];
});
this.btnListCall = this.mClone.clone(this.mBtnGroupConfig.btnGroupList);
this.getbtnListCall()
this.getBtnListCall()
this.btnList = this.btnListCall
this.updataBtnList()
this.updateBtnList()
HiLog.i(TAG, "aboutToAppear : ");
}
/**
* Switching BtnList Based on CallStatus
*/
updataBtnList() {
updateBtnList() {
if (this.callData.callState === CallStateConst.CALL_STATUS_DIALING|| this.callData.callState === CallStateConst.CALL_STATUS_ALERTING) {
this.btnList = this.btnListDialing
}else{
this.btnList = this.btnListCall
}
HiLog.i(TAG, "upData BtnList : %s" + this.btnList);
}
getbtnListCall() {
this.btnListDialing = this.mClone.clone(this.mBtnGroupConfig.btnGroupList);
this.btnListDialing[1].isDisable = true
this.btnListDialing[2].isDisable = true
HiLog.i(TAG, "get btnListCall : %s" + JSON.stringify(this.btnListDialing));
HiLog.i(TAG, "upData BtnList : %s");
}
/**
* call state
*
* @return {number} - call state
* Get BtnList Based on CallStatus
*/
callState() {
HiLog.i(TAG, "get callState : ");
return this.callData.callState;
getBtnListCall() {
this.btnListDialing = this.mClone.clone(this.mBtnGroupConfig.btnGroupList);
this.btnListDialing[1].isDisable = true
this.btnListDialing[2].isDisable = true
HiLog.i(TAG, "get btnListCall : %s");
}
/**
@ -105,7 +97,7 @@ export default struct FuncBtnGroup {
* @param {Object} callData - call data
*/
onCallStateChange(newVal) {
HiLog.i(TAG, "Calling status changed : %s" + JSON.stringify(newVal));
HiLog.i(TAG, "Calling status changed : %s");
const BtnName= ['video', 'record', 'add', 'mute', 'contact']
if (this.callList.length >= 2 && this.callList.every((v) =>
v.conferenceState !== ConferenceConst.TEL_CONFERENCE_ACTIVE)) {
@ -139,7 +131,7 @@ export default struct FuncBtnGroup {
* @param {Object} obj - object
*/
btnClick(obj) {
HiLog.i(TAG, "btnClick get icon type : %s" + JSON.stringify(obj));
HiLog.i(TAG, "btnClick get icon type : %s");
const BtnName= ['record', 'keep', 'video', 'mute']
const type = obj.type;
const { callId } = this.callData;
@ -210,7 +202,7 @@ export default struct FuncBtnGroup {
*/
keepHandle(type) {
const awaitIsActive = this.btnList.find((v) => v.type === type).isActive;
HiLog.i(TAG, "keep handle %s" + JSON.stringify(awaitIsActive));
HiLog.i(TAG, "keep handle %s");
awaitIsActive ? this.mCallServiceProxy.holdCall(this.callData.callId) : this.mCallServiceProxy.unHoldCall(this.callData.callId);
}
@ -221,7 +213,7 @@ export default struct FuncBtnGroup {
*/
muteHandle(type) {
const awaitIsActive = this.btnList.find((v) => v.type === type).isActive;
HiLog.i(TAG, "mute Handle %s" + JSON.stringify(awaitIsActive));
HiLog.i(TAG, "mute Handle %s");
awaitIsActive ? this.mCallServiceProxy.setMuted() : this.mCallServiceProxy.cancelMuted();
}
@ -258,7 +250,7 @@ export default struct FuncBtnGroup {
.columnsGap(24)
.rowsGap(29.5)
.height(132.5)
.columnsTemplate('1fr 1fr 1fr ')
.columnsTemplate('1fr 1fr 1fr')
.rowsTemplate('1fr 1fr ')
}
.useSizeType({

View File

@ -15,7 +15,7 @@
import HiLog from '../utils/Hilog.ets';
const TAG = "InComDialog";
const TAG = 'InComDialog';
@CustomDialog
export default struct InComDialog {
@ -51,7 +51,7 @@ export default struct InComDialog {
.onClick(() => {
this.controller.close();
this.confirm(item)
HiLog.i(TAG, "onClick and confirm : %s",JSON.stringify(item));
HiLog.i(TAG, "onClick and confirm : %s");
})
if(item.id !== 4){
Image($r("app.media.divider"))

View File

@ -49,7 +49,7 @@ const SEND_SMS_FAILURE_SERVICE_UNAVAILABLE = 3;
@Component
export default struct IncomingCom {
@State SendResult: any = {}
@State SendResult: any = {};
@Link callData: any;
private btnList= [];
private msgList = [];
@ -62,7 +62,7 @@ export default struct IncomingCom {
cancel: () => {
},
confirm: (item) => {
HiLog.i(TAG, "confirm : %s" + JSON.stringify(item));
HiLog.i(TAG, "confirm : %s");
this.msgItemClick(item);
},
cancelHandle: () => {
@ -94,23 +94,25 @@ export default struct IncomingCom {
content = typeName
HiLog.i(TAG, "sendMessage resourceManager.getResourceManager : " );
return new Promise(function (resolve, reject) {
sms.sendMessage({
slotId: slotId,
destinationHost: destinationHost,
content: content,
sendCallback: (err, sendResult) => {
this.SendResult = sendResult
if (err) {
reject(err);
} else {
if (sendResult.result === SEND_SMS_SUCCESS) {
resolve(true);
if(globalThis.sendPermissionFlag){
sms.sendMessage({
slotId: slotId,
destinationHost: destinationHost,
content: content,
sendCallback: (err, sendResult) => {
this.SendResult = sendResult
if (err) {
reject(err);
} else {
resolve(false);
if (sendResult.result === SEND_SMS_SUCCESS) {
resolve(true);
} else {
resolve(false);
}
}
}
}
});
});
}
}
);
})
@ -135,10 +137,6 @@ export default struct IncomingCom {
id: 4,
msg: $r("app.string.beThereSoon")
},
// {
// id: 5,
// msg: $r("app.string.customSMS")
// }
];
}
@ -162,7 +160,7 @@ export default struct IncomingCom {
*/
private msgItemClick(obj) {
let Content: string = "";
let Err: string = ""
let Err: string = "";
this.sendMessage(obj)
if (this.SendResult) {
resourceManager.getResourceManager().then(result => {
@ -187,7 +185,6 @@ export default struct IncomingCom {
})
})
}
}
/**
@ -208,7 +205,7 @@ export default struct IncomingCom {
* Enable the SMS reply pop-up
*/
private btnClick(type){
HiLog.i(TAG, "btnClick : %s" + JSON.stringify(type));
HiLog.i(TAG, "btnClick : %s");
if (type === 'msg') {
this.msgDialogController.open();
}

View File

@ -15,7 +15,6 @@
import CallServiceProxy from '../../model/CallServiceProxy.ets';
import DtmfBtn from '../components/DtmfBtn.ets';
import cellClick from '../../pages/index.ets';
import HiLog from '../utils/Hilog.ets';
const TAG = "Keyboard";

View File

@ -1,175 +0,0 @@
/**
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import callStateConst from '../constant/CallStateConst.ets';
import router from '@system.router';
import callManger from '../../model/CallManager.ets'
import HiLog from '../utils/Hilog.ets';
const TAG = "Test";
@Component
export default struct Test {
private numValue: Number = 0;
@State showList:boolean =false;
public btnList = [
{
id: 1,
type: 'active',
txt: '正在通话',
callState: 0,
videoState: 0,
conferenceState: 0
},
{
id: 2,
type: 'holding',
txt: '通话挂起保持',
callState: 1,
videoState: 0,
conferenceState: 0
},
{
id: 3,
type: 'dialing',
txt: '拨号开始',
callState: 2,
videoState: 0,
conferenceState: 0
},
{
id: 4,
type: 'alerting',
txt: '正在呼出',
callState: 3,
videoState: 0,
conferenceState: 0
},
{
id: 5,
type: 'incoming',
txt: '对方来电',
callState: 4,
videoState: 0,
conferenceState: 0
},
{
id: 6,
type: 'waiting',
txt: '第三方来电等待',
callState: 5,
videoState: 0,
conferenceState: 0
},
{
id: 7,
type: 'disconnected',
txt: '挂断完成',
callState: 6,
videoState: 0,
conferenceState: 0
},
];
private firstCallData = {
callId: 1001,
callState: 8,
accountNumber: '13888888888',
videoState: 0,
callType: 0,
startTime: 0,
contactName: '幸运虾',
conferenceState: 0
};
private secondCallData = {
callId: 1002,
callState: 8,
accountNumber: '13666666666',
videoState: 0,
callType: 0,
startTime: 0,
contactName: '倒霉虾',
conferenceState: 0
};
private mCallManger: callManger;
@State test: boolean = false;
@Link callData : any;
@Link callList:Array<any>;
private aboutToAppear(): void {
this.mCallManger =new callManger(this)
}
onDialClick() {
router.push({
uri: 'pages/dial/dial',
});
}
onMenuSelected(item) {
let id = parseInt(item.id);
const targetObj = this.btnList.find((v) => v.id === id);
HiLog.i(TAG, "onMenuSelected : %s" + JSON.stringify(targetObj));
const { callState, videoState, conferenceState } = targetObj;
let obj = {};
let len = this.callList.length;
if ((targetObj.callState === 5 && len === 1) || len > 1) {
if (targetObj.callState === 0) {
this.mCallManger.update({ ...this.firstCallData, callState: 1 });
}
Object.assign(obj, {
...this.secondCallData,
callState,
videoState,
conferenceState
});
} else {
Object.assign(obj, {
...this.firstCallData,
callState,
videoState,
conferenceState
});
}
this.mCallManger.update(obj);
HiLog.i(TAG, "onMenuSelected end : " );
}
build() {
Column(){
Button('测试')
.onClick(() => {
this.showList = !this.showList
})
Column() {
ForEach(this.btnList, (item) => {
Column() {
Text(item.txt)
.padding(5)
.fontSize(25)
}
.onClick(() => {
this.showList =! this.showList
this.onMenuSelected(item)
})
})
}
.borderWidth(1)
.borderRadius(5)
.visibility(this.showList ? Visibility.Visible:Visibility.Hidden)
.backgroundColor(Color.White)
}
}
}

View File

@ -13,6 +13,10 @@
* limitations under the License.
*/
/**
* @file: User list component
*/
import CallStateConst from '../constant/CallStateConst.ets';
import CallServiceProxy from '../../model/CallServiceProxy.ets';
import HiLog from '../utils/Hilog.ets';

View File

@ -13,10 +13,13 @@
* limitations under the License.
*/
/**
* @file: Header information display component
*/
import callList from '../components/CallList.ets';
import Utils from '../utils/utils.ets';
import callStateConst from '../constant/CallStateConst.ets';
import conferenceConst from '../constant/ConferenceConst.ets';
import HiLog from '../utils/Hilog.ets';
const TAG = "contactCard";
@ -32,8 +35,6 @@ if (defaultTemp != undefined) {
@Component
export default struct ContactCard {
// @State address: string = "北京";
// @State simCardType: string = "移动";
@State callStateText: string = '';
@State pointText: string = "";
@Prop isShowKeyboard: boolean;
@ -44,6 +45,7 @@ export default struct ContactCard {
@StorageLink("CallTimeList") callTimeList: any = [];
@StorageLink("TextInput") textInput: string = '';
@StorageLink("TextInputValue") textInputValue: string = '';
@StorageLink("AccountNumber") accountNumber: string = '';
public aboutToAppear(callData, callList, callTimeList): void {
HiLog.i(TAG, "aboutToAppear");
@ -56,7 +58,7 @@ export default struct ContactCard {
* @return {number} - Call status
*/
public callState() {
HiLog.i(TAG, "callState this.callData.callState : %s",this.callData.callState);
HiLog.i(TAG, "callState this.callData.callState : %s", this.callData.callState);
return this.callData.callState;
}
@ -79,15 +81,6 @@ export default struct ContactCard {
v.callState === callStateConst.CALL_STATUS_WAITING));
}
/**
* Conference call status
*
* @return {number} - Conference call status
*/
conferenceState() {
return this.callData.conferenceState;
}
/**
* Reference call-list component
*
@ -100,125 +93,108 @@ export default struct ContactCard {
build() {
GridContainer({ gutter: 24, margin: 24 }) {
Row() {
GridContainer({ gutter: 24, margin: 0 }) {
Column() {
if (!this.isShowKeyboard) {
Column() {
if (!this.isShowKeyboard) {
Column() {
Image($r("app.media.ic_public_avatar"))
.width(110)
.height(110)
.borderRadius(55)
.margin({ bottom: 18 })
}
}
if (this.isShowKeyboard && this.textInput.length === 0) {
Column() {
Text(this.callData.contactName ? this.callData.contactName : this.callData.accountNumber)
.fontSize(30)
.height(40)
.lineHeight(40)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
.margin({ bottom: 8, top: 64 })
}
} else if (!this.isShowKeyboard) {
Column() {
Text(this.callData.contactName ? this.callData.contactName : this.callData.accountNumber)
.fontSize(30)
.height(40)
.lineHeight(40)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
.margin({ bottom: 8 })
}
} else if (this.isShowKeyboard && this.textInput.length != 0) {
Scroll() {
Text(this.textInputValue)
.height(40)
.fontSize(30)
.lineHeight(40)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 8, top: 64 })
.fontColor('#FFFFFF')
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Move) {
this.textInputValue = this.textInput
}
})
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
}
Row() {
if (this.isShowKeyboard && this.kbCommand) {
Text(this.kbCommand)
} else if (!this.isShowKeyboard || this.isShowKeyboard && this.textInput.length === 0) {
Text(this.callData.contactName ? this.callData.accountNumber : '')
.fontSize(14)
.height(19)
.lineHeight(16)
.fontColor('#FFFFFF')
}
if (this.isShowTime() && this.callData.contactName == '') {
Column() {
Text(this.callTimeList[0].callTime)
.fontSize(14)
.height(19)
.lineHeight(19)
.fontColor('#FFFFFF')
}
}
if (this.callData.callState === 2) {
Column() {
Text($r("app.string.dialing"))
.fontSize(14)
.height(19)
.lineHeight(16)
.fontColor('#FFFFFF')
.margin({ left: 10 })
}
}
if (this.callData.callState === 3) {
Column() {
Text($r("app.string.partyIsRinging"))
.fontSize(14)
.height(19)
.lineHeight(16)
.fontColor('#FFFFFF')
.margin({ left: 10 })
}
}
if (this.isShowTime() && this.callData.contactName != '') {
Column() {
Text(this.callTimeList[0].callTime)
.fontSize(14)
.height(19)
.lineHeight(19)
.fontColor('#FFFFFF')
}
}
}
.useSizeType({
sm: { span: 4, offset: 0 },
md: { span: 6, offset: 0 },
lg: { span: 4, offset: 0 }
})
Image($r("app.media.ic_public_avatar"))
.width(110)
.height(110)
.borderRadius(55)
.margin({ bottom: 18 })
}
}
if (this.isShowKeyboard && this.textInput.length === 0) {
Column() {
Text(this.callData.contactName ? this.callData.contactName : this.accountNumber)
.fontSize(30)
.height(40)
.lineHeight(40)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
.margin({ bottom: 8, top: 64 })
}
} else if (!this.isShowKeyboard) {
Column() {
Text(this.callData.contactName ? this.callData.contactName : this.accountNumber)
.fontSize(30)
.height(40)
.lineHeight(40)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
.margin({ bottom: 8 })
}
} else if (this.isShowKeyboard && this.textInput.length != 0) {
Scroll() {
Text(this.textInputValue)
.height(40)
.fontSize(30)
.lineHeight(40)
.fontWeight(FontWeight.Medium)
.margin({ bottom: 8, top: 64 })
.fontColor('#FFFFFF')
.onTouch((event: TouchEvent) => {
if (event.type === TouchType.Move) {
this.textInputValue = this.textInput
}
})
}
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.Off)
.width('100%')
}
Row() {
if (this.isShowKeyboard && this.kbCommand) {
Text(this.kbCommand)
} else if (!this.isShowKeyboard || this.isShowKeyboard && this.textInput.length === 0) {
Text(this.callData.contactName ? this.accountNumber : '')
.fontSize(14)
.height(19)
.lineHeight(16)
.fontColor('#FFFFFF')
.visibility(this.callData.contactName && !this.isShowKeyboard ? Visibility.Visible : Visibility.None)
}
if (this.callData.callState === 2) {
Column() {
Text($r("app.string.dialing"))
.fontSize(14)
.height(19)
.lineHeight(16)
.fontColor('#FFFFFF')
.margin({ left: 10 })
}
}
if (this.callData.callState === 3) {
Column() {
Text($r("app.string.partyIsRinging"))
.fontSize(14)
.height(19)
.lineHeight(16)
.fontColor('#FFFFFF')
.margin({ left: 10 })
}
}
}
if (this.isShowTime()) {
Column() {
Text(this.callTimeList[0].callTime)
.fontSize(14)
.height(19)
.lineHeight(19)
.fontColor('#FFFFFF')
}
}
.useSizeType({
sm: { span: 4, offset: 0 },
md: { span: 6, offset: 1 },
lg: { span: 6, offset: 3 }
})
}
.useSizeType({
sm: { span: 4, offset: 0 },
md: { span: 6, offset: 1 },
lg: { span: 6, offset: 3 }
})
}
}
}

View File

@ -97,11 +97,11 @@ const secondBtns = [
}
];
/**
* Process the image text of the button group
*
* @param {Array} arr - Pass in an array
*/
/**
* Process the image text of the button group
*
* @param {Array} arr - Pass in an array
*/
function addIconUrl(arr) {
const regExp = /^icon.*.*Url$/;
arr.forEach((item) => {

View File

@ -39,6 +39,7 @@ export default class Getclone {
public static getInstance(): Getclone{
return this.getclone;
}
/**
* forEach
*

View File

@ -16,10 +16,16 @@
/**
* @file: Tools
*/
// Carry when the time is greater than 9 seconds
/**
* Carry when the time is greater than 9 seconds
*/
const NINE_MAX = 9;
// Divide by 60 to get minutes and seconds
/**
* Divide by 60 to get minutes and seconds
*/
const SIXTY_SECONDS = 60;
export default class Utils {

View File

@ -19,7 +19,6 @@
import CallStateManager from './CallStateManager.ets';
import CallStateConst from '../common/constant/CallStateConst.ets';
import app from '@system.app';
import SendNotification from './SendNotification.ets';
import NotificationManager from '../model/NotificationManager.ets';
import HiLog from '../common/utils/Hilog.ets';
@ -34,14 +33,13 @@ export default class CallDataManager {
callTimeList :any = [];
private callStateChange: any;
private mCallStateManager: CallStateManager ;
private mSendNotification: SendNotification ;
private NotificationManager ;
private sCallDataManager : CallDataManager ;
constructor (callData, callList, callTimeList){
this.mSendNotification = SendNotification.getInstance();
this.NotificationManager =new NotificationManager()
this.mCallStateManager = CallStateManager.getInstance()
this.callData = callData;
this.callList = callList;
// this.callTimeList = callTimeList;
this.callStateChange = (arg) => arg;
this.mCallStateManager = new CallStateManager(this.callData);
}
@ -79,7 +77,7 @@ export default class CallDataManager {
if (callState === CallStateConst.CALL_STATUS_DISCONNECTED) {
if (this.callList.length === 1) {
this.mSendNotification.cancelNotification();
this.NotificationManager.cancelNotification();
AppStorage.Get<NotificationManager>('notificationManager').sendCapsuleNotification(callData, true);
app.terminate();
} else {

View File

@ -23,16 +23,16 @@ import featureAbility from '@ohos.ability.featureAbility';
import CallServiceProxy from './CallServiceProxy.ets';
import ContactManager from './ContactManager.ets';
import HiLog from '../common/utils/Hilog.ets';
import call from '@ohos.telephony.call';
const TAG = "CallManager";
let subscriber;
const TIMING = 1000;
const events = ['callui.event.callDetailsChange'];
/**
* class CallManager
*/
/**
* class CallManager
*/
export default class CallManager {
private callData: any = {};
private timer = null ;
@ -51,13 +51,14 @@ export default class CallManager {
this.callData = ctx.callData;
this.timer = null;
this.ctx = ctx;
this.callTimeList = ctx.callTimeList;
this.callTimeList =ctx.callTimeList;
this.mCallDataManager = new CallDataManager(ctx.callData, ctx.callList, ctx.callTimeList);
this.openTimer(this.updateCallTimeList.bind(this));
this.sendNotificationHandle = (arg) => arg;
this.registerSubscriber();
this.initCallData();
}
/*
* init CallData
*/
@ -122,21 +123,21 @@ export default class CallManager {
*
* @param { Object } callData -Object
*/
async update(callData) {
await this.contactManager.getContactInfo(callData);
async update(callData) {
if (globalThis.permissionFlag) {
await this.contactManager.getContactInfo(callData)
}
this.mCallDataManager.update(callData);
call.formatPhoneNumber(callData.accountNumber, (err, data) => {
if(data === undefined ){
AppStorage.SetOrCreate("AccountNumber",callData.accountNumber)
} else {
AppStorage.SetOrCreate("AccountNumber",data)
}
});
HiLog.i(TAG, "update : ")
}
/**
* add callStateChange callBack
*
* @param { Function } callBack - Function
*/
// addCallBack(callBack) {
// this.mCallDataManager.callStateChange = callBack;
// }
/**
* update call time list
*/

View File

@ -215,7 +215,7 @@ export default class CallServiceProxy {
HiLog.i(TAG,prefixLog + "call.on registerCallStateCallback : %s" + JSON.stringify(err))
return;
}
HiLog.i(TAG,prefixLog + "call.on registerCallStateCallback callState : %s" + JSON.stringify(res.callState))
HiLog.i(TAG,prefixLog + "call.on registerCallStateCallback callState : %s")
callBack(res);
});
}
@ -241,7 +241,7 @@ export default class CallServiceProxy {
if (err) {
HiLog.i(TAG,prefixLog + "call.on callEventChange : %s" + JSON.stringify(err))
} else {
HiLog.i(TAG,prefixLog + "call.on callEventChange : %s" + JSON.stringify(value))
HiLog.i(TAG,prefixLog + "call.on callEventChange : %s")
}
});
}
@ -254,7 +254,7 @@ export default class CallServiceProxy {
if (err) {
HiLog.i(TAG,prefixLog + "call.off unRegisterCallEventCallback : %s" + JSON.stringify(err))
} else {
HiLog.i(TAG,prefixLog + "call.off unRegisterCallEventCallback : %s" + JSON.stringify(value))
HiLog.i(TAG,prefixLog + "call.off unRegisterCallEventCallback : %s")
}
});
}

View File

@ -29,10 +29,6 @@ const ID = 0;
const CALL_BUNDLE_NAME = 'com.ohos.callui';
const CALL_ABILITY_NAME = 'com.ohos.callui.MainAbility';
//const wantAgent = {
// getWantAgent: (obj) => Promise.resolve(obj),
//};
const notificationRequest = {
content: {
contentType: notification.ContentType.NOTIFICATION_CONTENT_LONG_TEXT,
@ -72,14 +68,6 @@ export default class NotificationManager {
*/
async sendNotification(text, callData) {
const {callState, callId} = callData;
// const mapObj = new Map([
// [callStateConst.CALL_STATUS_INCOMING, ['answer', 'reject']],
// [callStateConst.CALL_STATUS_ACTIVE, ['hangUp', 'mute']],
// [callStateConst.CALL_STATUS_HOLDING, ['hangUp', 'callHold']],
// [callStateConst.CALL_STATUS_ALERTING, ['hangUp']],
// [callStateConst.CALL_STATUS_DIALING, ['hangUp']],
// [callStateConst.CALL_STATUS_WAITING, ['answer', 'reject']]
// ]);
const actionBtnKeys = this.getMapObj(callState) || [];
const {START_ABILITY, SEND_COMMON_EVENT} = wantAgent.OperationType;
const wantAgentObj = await this.getWantAgent(callData, START_ABILITY);
@ -102,29 +90,32 @@ export default class NotificationManager {
title: value,
wantAgent: wantAgentObj
});
Object.assign(notificationRequest.content.longText, {
title: text,
expandedTitle: text
});
notification.publish(notificationRequest);
}
});
});
}
}
Object.assign(notificationRequest.content.longText, {
title: text,
expandedTitle: text
});
notification.publish(notificationRequest);
HiLog.i(TAG, "sendNotification end : ")
}
//todo
/**
* Get call status
* @param callState
*/
getMapObj(callState) {
if (callState===callStateConst.CALL_STATUS_INCOMING) {
return ['answer', 'reject']
}
if (callState===callStateConst.CALL_STATUS_ACTIVE) {
return ['hangUp', 'mute']
return ['hangUp']
}
if (callState===callStateConst.CALL_STATUS_HOLDING) {
return ['hangUp', 'callHold']
return ['hangUp']
}
if (callState===callStateConst.CALL_STATUS_ALERTING) {
return ['hangUp']
@ -183,7 +174,7 @@ export default class NotificationManager {
*/
sendCapsuleNotification(callData, isBackground) {
HiLog.i(TAG, "sendCapsuleNotification isBackground : %s" + JSON.stringify(isBackground))
callData.startTime = (callData.startTime)*1000
callData.startTime = (callData.startTime)
HiLog.i(TAG, "sendCapsuleNotification callData.startTime : ")
const {callState, startTime} = callData;
commonEvent.publish('CAPSULE_EVENT_CALL_UI', {
@ -191,7 +182,7 @@ export default class NotificationManager {
isOrdered: false,
data: JSON.stringify({
callState,
startTime,
startTime: startTime*1000,
isBackground,
wantBundleName: CALL_BUNDLE_NAME,
wantAbilityName: CALL_ABILITY_NAME

View File

@ -1,70 +0,0 @@
/**
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file: send notification
*/
import wantAgent from '@ohos.wantAgent';
import notify from '@ohos.notification';
import HiLog from '../common/utils/Hilog.ets';
const TAG = "SendNotification";
export default class SendNotification {
private id: number = 1;
private static sSendNotification: SendNotification = null;
private notificationRequest: any = {
content: {
contentType: notify.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: 'voice call',
text: '',
},
},
slotType: notify.SlotType.OTHER_TYPES,
deliveryTime: new Date().getTime()
};
public static getInstance(): SendNotification {
if (SendNotification.sSendNotification == null) {
SendNotification.sSendNotification = new SendNotification()
}
return SendNotification.sSendNotification;
}
public async sendNotification(text) {
const res = await wantAgent.getWantAgent({
wants: [{
bundleName: 'com.ohos.callui',
abilityName: 'com.ohos.callui.MainAbility',
}],
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags: [wantAgent.WantAgentFlags.ONE_TIME_FLAG],
});
Object.assign(this.notificationRequest, {wantAgent: res});
this.notificationRequest.content.normal.title = text;
notify.publish(this.notificationRequest);
}
public cancelNotification() {
notify.cancel(this.id).then((res) => {
HiLog.i(TAG, "notify.cancel res data : %s");
}).catch((err) => {
HiLog.i(TAG, "notify.cancel err data : %s" + JSON.stringify(err))
});
}
}

View File

@ -1,101 +0,0 @@
/**
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file: Conference call
*/
import router from '@system.router';
import CallServiceProxy from "../model/callServiceProxy.ets";
@Entry
@Component
struct ConferenceManage {
@State callList: any = [];
mCallServiceProxy: CallServiceProxy= null;
private aboutToAppear(): void {
this.mCallServiceProxy = CallServiceProxy.getInstance()
}
/**
* Return to the conference call interface by Lu You
*/
returnBtn() {
router.back();
}
/**
* Call hangup interface
*
* @param {number} callID - callId
*/
hangUp(callId) {
this.mCallServiceProxy.hangUpCall(callId);
}
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {
Row() {
Image('/common/return.png')
.width(65)
.height(65)
.margin({ left: 52 })
.onClick(() => {
this.returnBtn()
})
Text($r("app.string.manageUsers"))
.margin({ left: 36 })
.fontSize(48)
.fontColor(0xCCCCCC)
}
.width('100%')
.height(112)
.align(Alignment.Center)
ForEach(this.callList, (item) => {
Flex({ alignItems: ItemAlign.Center }) {
Text('$item.accountNumber')
.fontColor(0xCCCCCC)
Image('/common/shunt.png')
.margin({ top:34 })
.margin({ left:42.78 })
.width(60)
.height(60)
Image('/common/shuntHang.png')
.margin({ top:34 })
.margin({ left:54 })
.width(60)
.height(60)
}
.width('100%')
.height(128)
.onClick(() => {
this.hangUp(item.callId);
})
Divider()
.strokeWidth(1)
.color(0X989A9C)
})
}
.backgroundImage('common/wallpaper.png', ImageRepeat.NoRepeat)
.backgroundImageSize(ImageSize.Cover)
.height('100%')
}
}

View File

@ -23,16 +23,16 @@ import Keyboard from '../common/components/Keyboard.ets';
import BottomBtn from '../common/components/BottomBtn.ets';
import IncomingCom from '../common/components/IncomingCom.ets';
import CallStateConst from '../common/constant/CallStateConst.ets';
import SendNotification from '../model/sendNotification.ets';
import NotificationManager from '../model/NotificationManager.ets';
import call from '@ohos.telephony.call';
import CallManager from '../model/CallManager.ets';
import HiLog from '../common/utils/Hilog.ets';
//import Test from "../common/components/Test.ets";
import bundle from '@ohos.bundle';
import abilityAccessCtrl from "@ohos.abilityAccessCtrl";
import featureAbility from "@ohos.ability.featureAbility"
const TAG = "Index";
const prefixLog = 'callUI app:@ohos.telephony.call:';
const MARGIN_VALUE = 60;
const SIM_CARD_DELAYED_DISPLAY = 100;
const TIMER_DELAY = 0;
const textMap =
@ -58,10 +58,6 @@ export default struct Index {
@State inputValue: string = '';
private consoleTxt: '';
private callStateConst;
private contactCard;
private funcBtnGroup;
private sendNotificationHandle;
private addCallBack;
private notificationManager: NotificationManager;
/**
@ -74,9 +70,9 @@ export default struct Index {
}
/**
* Input content
* method to control the display of DTMF keyboard
*
* @param {boolean} bool - Incoming value
* parent component pass by value child component
*/
public showKeyboard() {
this.isShowKeyboard = !this.isShowKeyboard;
@ -93,38 +89,18 @@ export default struct Index {
dialScene
});
}
/**
* Create timer
*
* @param {number} newVal - Incoming number
*/
onCallStateChange(newVal) {
// this.contactCard.onCallStateChange(newVal);
// let timer = setTimeout(() => {
// const funcBtnGroupDom = this.funcBtnGroup;
// if (funcBtnGroupDom && typeof funcBtnGroupDom.onCallStateChange === 'function') {
// funcBtnGroupDom.onCallStateChange(newVal);
// }
// clearTimeout(timer);
// }, TIMER_DELAY);
}
private aboutToAppear(): void {
this.initPermissions()
HiLog.i(TAG, "aboutToAppear :")
this.callStateConst = new CallStateConst();
this.notificationManager = new NotificationManager();
globalThis.callManager = new CallManager(this)
AppStorage.SetOrCreate<NotificationManager>('notificationManager', this.notificationManager);
globalThis.callManager.addCallBack(this.onCallStateChange.bind(this));
this.sendNotificationHandle = SendNotification;
this.onCallStateChange(this.callData.callState);
let delayMethod = setTimeout(() => {
clearTimeout(delayMethod);
}, SIM_CARD_DELAYED_DISPLAY);
this.callStateConst = new CallStateConst();
this.contactCard = new ContactCard();
this.funcBtnGroup = new FuncBtnGroup();
}
onPageShow() {
@ -132,7 +108,57 @@ export default struct Index {
this.appInactiveState = false;
this.notificationManager.cancelNotification();
this.notificationManager.sendCapsuleNotification(this.callData, false);
HiLog.i(TAG, "onPageShow end : " )
HiLog.i(TAG, "onPageShow end : ")
}
async initPermissions() {
let array: Array<string> = ["ohos.permission.READ_CONTACTS", "ohos.permission.SEND_MESSAGES"];
var bundleFlag = 0;
var tokenID = undefined;
var userID = 100;
var appInfo = await bundle.getApplicationInfo("com.ohos.callui", bundleFlag, userID);
tokenID = appInfo.accessTokenId;
var atManager = abilityAccessCtrl.createAtManager();
let requestPermissions: Array<string> = [];
for (let i = 0;i < array.length; i++) {
var result = await atManager.verifyAccessToken(tokenID, array[i]);
if (result != abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED) {
requestPermissions.push(array[i]);
}
}
HiLog.i(TAG, "initPermissions requestPermissions : " + requestPermissions.length)
if (requestPermissions.length > 0) {
let context = featureAbility.getContext()
context.requestPermissionsFromUser(requestPermissions, 2345, (data) => {
for (let i = 0;i < data.authResults.length; i++) {
if(data.permissions[i] === "ohos.permission.READ_CONTACTS"){
if (data.authResults[i] === 0) {
globalThis.permissionFlag = true
globalThis.callManager.update(this.callData)
} else {
globalThis.permissionFlag = false
globalThis.sendPermissionFlag = true
}
}
if(data.permissions[i] === "ohos.permission.SEND_MESSAGES"){
if (data.authResults[i] === 0) {
globalThis.sendPermissionFlag = true
} else {
globalThis.permissionFlag = true
globalThis.callManager.update(this.callData)
globalThis.sendPermissionFlag = false
}
}
}
}).catch((error)=>{
HiLog.i(TAG, "Application catch error")
})
} else {
globalThis.permissionFlag = true
globalThis.sendPermissionFlag = true
globalThis.callManager.update(this.callData)
}
HiLog.i(TAG, "Application requestPermissionsFromUser end")
}
onPageHide() {
@ -141,14 +167,6 @@ export default struct Index {
const {callState, accountNumber, contactName, callId} = this.callData;
let fool = (callState !== CallStateConst.callStateObj.CALL_STATUS_DISCONNECTED && callId)
if (callState !== CallStateConst.callStateObj.CALL_STATUS_DISCONNECTED && callId) {
const key = this.callStateConst.getCallStateText(callState) || '';
// let callStateText = key ? textMap[key] : '';
// if (callState === CallStateConst.callStateObj.CALL_STATUS_INCOMING) {
// callStateText = $r("app.string.incomingCall")
// }
// if (callState === CallStateConst.callStateObj.CALL_STATUS_ACTIVE) {
// callStateText = $r("app.string.calling")
// }
let text = contactName + ' ' + accountNumber + ' ';
if (!contactName) {
text = accountNumber + ' ' ;
@ -176,17 +194,17 @@ export default struct Index {
if (this.callState() !== CallStateConst.callStateObj.CALL_STATUS_WAITING
&& this.callState() !== CallStateConst.callStateObj.CALL_STATUS_INCOMING) {
Column() {
if (!this.isShowKeyboard) {
Column() {
FuncBtnGroup({ callData: $callData, callList: $callList })
}
.margin({ bottom: 29.5 })
} else {
Column() {
Keyboard({ callData: $callData })
}
.margin({ bottom: 32 })
Column() {
FuncBtnGroup({ callData: $callData, callList: $callList })
}
.visibility(!this.isShowKeyboard ? Visibility.Visible : Visibility.None)
.margin({ bottom: 29.5 })
Column() {
Keyboard({ callData: $callData })
}
.visibility(this.isShowKeyboard ? Visibility.Visible : Visibility.None)
.margin({ bottom: 32 })
Column() {
BottomBtn({
@ -207,27 +225,6 @@ export default struct Index {
.margin({ bottom: 106 })
}
}
// Column() {
// Test({
// callData: $callData,
// callList: $callList
// })
// Column() {
// Button("拨号开始")
// .onClick(() => {
// console.info("wuchaoert" + this.inputNum.join().replace(/,/g, ""))
// this.dialCall(this.inputNum.join().replace(/,/g, ""))
// })
// }
// .margin({ top: 15 })
// }
// .position({
// x: 15,
// y: 15
// })
}
}
.width("100%")

View File

@ -1,40 +0,0 @@
{
"color": [
{
"name": "red",
"value": "#ff0000"
},
{
"name": "blue",
"value": "#FF0022FF"
},
{
"name": "yellow",
"value": "#FFFFF200"
},
{
"name": "orange",
"value": "#FFFF7700"
},
{
"name": "black",
"value": "#FF0E0E0E"
},
{
"name": "green",
"value": "#FF3B8642"
},
{
"name": "pink",
"value": "#FFF6A2A0"
},
{
"name": "jing",
"value": "#FFE9DE10"
},
{
"name": "zi",
"value": "#FFC110E9"
}
]
}

View File

@ -1,28 +1,43 @@
# CallUI 使用说明
## 代码使用
### 代码下载
#### 配置码云ssh
1. 打开本地git bash窗口
2. 进入到.ssh 目录cd ~/.ssh
3. 找到id_rsa.pub文件ls
4. 查看公钥cat id_rsa.pub
5. 在码云个人设置-安全设置-ssh公钥中配置公钥
#### 下载代码
1. 搜索并打开gitee点击导航栏里面的开源软件搜索openharmony,点击进入openharmony搜索applications_call下载地址[applications_call](https://gitee.com/openharmony/applications_call)。
2. 选择克隆/下载 - ssh方式 -复制下载地址
3. 本机git bash 中执行:
## 1. 代码使用
### 1.1 代码下载
#### 1.1.1 配置码云ssh
1打开本地 git bash 窗口
2进入到 .ssh 目录cd ~/.ssh
3找到 id_rsa.pub 文件ls
4查看公钥cat id_rsa.pub
5在码云个人设置-安全设置-ssh公钥中配置公钥
#### 1.1.2下载代码
1搜索并打开gitee点击导航栏里面的开源软件搜索openharmony点击进入openharmony搜索applications_call下载地址[applications_call](https://gitee.com/openharmony/applications_call)
2选择克隆/下载 - ssh方式 -复制下载地址
3本机git bash 中执行:
```
git clone '复制的下载地址'
```
### 环境搭建
打开DevEco Studio链接下载安装安装步骤及安装说明详见下载见官网
## 基础开发说明
### 系统接口调用
### 异步回调的使用
- 在需要回调操作的js文件中创建回调函数
### 1.2 环境搭建
* 打开DevEco Studio链接下载安装安装步骤及安装说明详见下载见官网
## 2. 基础开发说明
### 2.1 系统接口调用
### 2.2 异步回调的使用
- 在需要回调操作的ets文件中创建回调函数
```JavaScript
subscribeCallback(err, data){
// do something
@ -38,20 +53,32 @@ subscribeCallback(err, data) {
Log.showInfo(TAG, 'subscribeCallback finished ====================' + JSON.stringify(data));
}
```
### 如何引用资源文件
##### 访问系统资源
### 2.3 如何引用资源文件
#### 2.3.1 访问系统资源
```
this.title = this.$s('sys.type.name');
```
访问应用资源
#### 2.3.2 访问应用资源
* 将应用资源放在工程的resources/base/element文件夹下的对应 .json 文件中,可通过$r()的方式引用资源
* 例如:引用字符串资源
```` JavaScript
this.title = this.$r('app.string.hello_world');
````
## 典型接口的使用
## 3. 典型接口的使用
```
import dataStorage from '@ohos.data.storage';
onCreate() {
@ -64,57 +91,92 @@ import dataStorage from '@ohos.data.storage';
this.globalData.storage = dataStorage.getStorageSync(path + this.globalData.path);
},
```
## 签名打包
### 签名
#### 签名文件的获取
2. 拷贝applications_call工程的 signature\com_ohos_Callui.p7b 、OpenHarmony.cer以及OpenHarmony.p12复制到sign文件夹下
#### 签名文件的配置
打开项目工程,选择 File → Project Structure
## 4. 签名打包
### 4.1 签名
#### 4.1.1 签名文件的获取
* 拷贝OpenHarmony/signcenter_tool/key文件下的OpenHarmony.p12到工程的signature文件夹下
* 拷贝OpenHarmony/signcenter_tool/certificates文件下的OpenHarmonyApplication.pem文件并将其后缀名.pem改为.cer然后放到工程的signature文件夹下
#### 4.1.2 签名文件的配置
1打开项目工程选择 File → Project Structure
![](../doc/image/signature_1.png)
选择 Modules → Signing Configs将对应的签名文件配置如下找到上述复制文件的路径依次填入下图中完成后点击Apply再点击OK。
2选择 Project → Signing Configs将对应的签名文件配置如下找到上述复制文件的路径依次填入下图中完成后点击Apply再点击OK
![](../doc/image/signature_2.png)
配置完成后对应的build.gradle文件中会出现如下内容
3配置完成后对应的build.gradle文件中会出现如下内容
![](../doc/image/signature_3.png)
### 打包
DevEco Studio 支持 debug 与 release 两种打包类型。可以在 OhosBuild Variants 窗口中进行切换。
### 4.2 打包
* DevEco Studio 支持 debug 与 release 两种打包类型。可以在 OhosBuild Variants 窗口中进行切换
![](../doc/image/ds_ohosbuild_variants.png)
#### debug打包
1. 代码准备完成后,在 OhosBuild Variants 窗口的 Selected Variant 中选择 debug。
![](../doc/image/ds_ohosbuild_variants_debug.png)
2. 选择Build → Build Haps(s)/APP(s) → Build Hap(s)
![](../doc/image/ds_build_haps.png)
#### 4.2.1 debug打包
3. 编译完成后hap包会生成在工程目录下的 `\build\outputs\hap\debug\phone\`路径下如果没有配置签名则只会生成未签名的hap包
1代码准备完成后在 OhosBuild Variants 窗口的 Selected Variant 中选择 debug
![](../doc/image/ds_ohosbuild_variants_release.png)
#### release打包
1. 代码准备完成后,在 OhosBuild Variants 窗口的 Selected Variant 中选择 release
![](../doc/image/ds_ohosbuild_variants_release.png)
![](../doc/image/ds_ohosbuild_variants_debug.png)
2. 选择Build → Build Haps(s)/APP(s) → Build Hap(s)
![](../doc/image/ds_build_haps.png)
3. 编译完成后hap包会生成在工程目录下的 `\build\outputs\hap\release\phone\`路径下配置好签名后生成的hap包会显示signed
![](../doc/image/ds_ohosbuild_output_dir_release.png)
## 安装、运行、调试
## 应用安装
配置 hdc
进入SDK目录中的toolchains文件夹下获取文件路径
2选择Build → Build Haps(s)/APP(s) → Build Hap(s)
![](../doc/image/ds_build_haps.png)
3编译完成后hap包会生成在工程目录下的 `\build\outputs\hap\debug\phone\`路径下如果没有配置签名则只会生成未签名的hap包
![](../doc/image/ds_ohosbuild_variants_release.png)
#### 4.2.2 release打包
1代码准备完成后在 OhosBuild Variants 窗口的 Selected Variant 中选择 release
![](../doc/image/ds_ohosbuild_variants_release.png)
2选择Build → Build Haps(s)/APP(s) → Build Hap(s)
![](../doc/image/ds_build_haps.png)
3编译完成后hap包会生成在工程目录下的 `\build\outputs\hap\release\phone\`路径下配置好签名后生成的hap包会显示signed
![](../doc/image/ds_ohosbuild_output_dir_release.png)
## 5. 安装、运行、调试
### 5.1 应用安装
1配置 hdc进入SDK目录中的toolchains文件夹下获取文件路径
![](../doc/image/sdk_catalogue.png)
@ -122,30 +184,39 @@ DevEco Studio 支持 debug 与 release 两种打包类型。可以在 OhosBuild
> hdc命令介绍与下载详见[hdc仓库地址](https://gitee.com/openharmony/developtools_hdc_standard)
并将此路径配置到环境变量中:
2并将此路径配置到环境变量中重启电脑使环境变量生效
![](../doc/image/sdk_environment_variable.png)
重启电脑使环境变量生效
连接开发板打开cmd命令窗口执行hdc list targets弹出窗口如下
3连接开发板打开cmd命令窗口执行hdc list targets弹出窗口如下
![](../doc/image/cmd1.png)
等待一段时间后,窗口出现如下打印,可回到输入 hdc list targets 的命令窗口继续操作:
4等待一段时间后窗口出现如下打印可回到输入 hdc list targets 的命令窗口继续操作
![](../doc/image/cmd2.png)
再次输入hdc list targets出现如下结果说明hdc连接成功
5再次输入hdc list targets出现如下结果说明hdc连接成功
![](../doc/image/cmd3.png)
获取读写权限:
6获取读写权限
```
hdc target mount
```
将签名好的 hap 包放入设备的 `/system/app` 目录下并修改hap包的权限
7将签名好的 hap 包放入设备的 `/system/app` 目录下并修改hap包的权限
```
hdc file send 本地路径 /system/app/hap包名称
@ -158,15 +229,20 @@ hdc file send 本地路径 /system/app/hap包名称
> mkdir app
> chmod 777 app
> ```
> `/system/app` 目录放置系统应用例如Contacts 等。
> `/system/app` 目录放置系统应用例如CallUI等。
>
> 但hap包需要在该目录下手动设置权限
> ```
> chmod 666 hap包名
> ```
> 此目录应用不用手动安装,系统自动拉起。
## 应用运行
applications_call属于系统应用在将签名的 hap 包放入 `/system/app` 目录后,重启系统,应用会自动拉起。
### 5.2 应用运行
* applications_call属于系统应用在将签名的 hap 包放入 `/system/app` 目录后,重启系统,应用会自动拉起
```
hdc shell reboot
```
@ -182,14 +258,21 @@ hdc shell reboot
> hdc shell "reboot"
> ```
>
>
## 应用调试
### log打印
### 5.3 应用调试
#### 5.3.1 log打印
- 在程序中添加 log
```JS
console.info("contacts log info");
console.info("callui log info");
```
### log获取及过滤
#### 5.3.2 log获取及过滤
- log获取
将log输出至文件
@ -197,12 +280,13 @@ console.info("contacts log info");
hdc shell hilog > 输出文件名称
```
例:
在真实环境查看log将全log输出到当前目录的hilog.log文件中
在真实环境查看log将全log输出到当前目录的hilog.log文件中
```
hdc shell hilog > hilog.log
```
- log过滤
在命令行窗口中过滤log
@ -214,34 +298,42 @@ hilog │ grep 过滤信息
```
hilog │ grep Label
```
## 贡献代码
### Fork 代码仓库
1. 在码云上打开 applications_call代码仓库[仓库地址](https://gitee.com/openharmony/applications_call))。
2. 点击仓库右上角的 Forked 按钮,在弹出的画面中,选择将仓库 fork 到哪里,点击确认。
3. Fork 成功之后,会在自己的账号下看见 fork 的代码仓库。
### 提交代码
1. 访问我们自己在码云账号上 fork 的代码仓库,点击“克隆/下载”按钮,选择 SSH点击“复制”按钮。
## 6. 贡献代码
2. 在本地新建 Contacts 目录,在 Contacts 目录中执行如下命令
```
git clone 步骤1中复制的地址
```
### 6.1 Fork 代码仓库
1在码云上打开 applications_call代码仓库[仓库地址](https://gitee.com/openharmony/applications_call)
3. 修改代码。
> 将代码引入工程,以及编译工程等相关内容请参见 **3. 代码使用** 部分的相关内容。
4. 提交代码到 fork 仓库。
> 修改后的代码,使用git status 查看修改代码,执行 `git add` 命令,然后执行 `git commit` 命令与 `git push` 命令,将代码 push 到我们自己的 fork 仓中。
> 关于代码提交的这部分内容涉及 git 的使用,可以参照 [git官网](https://git-scm.com/) 的内容,在此不再赘述。
2点击仓库右上角的 Forked 按钮,在弹出的画面中,选择将仓库 fork 到个人仓,点击确认
### 发起 Pull Request (PR)
在将代码提交到 fork 仓之后,我们可以通过发起 Pull RequestPR的方式来为 OpenHarmony 的相关项目贡献代码。
3Fork 成功之后,会在自己的账号下看见 fork 的代码仓库
1. 打开 fork 仓库。选择 `Pull Requests``新建 Pull Request`
2. 在 `新建 Pull Request` 画面填入标题与说明,点击 `创建` 按钮。
3. 创建 Pull Request 完成。 PR 创建完成后,会有专门的代码审查人员对代码进行评审,评审通过之后会合入相应的代码库。
### 6.2 提交代码
1访问我们自己在码云账号上 fork 的代码仓库,点击“克隆/下载”按钮,选择 SSH点击“复制”按钮
2在本地新建 CallUI文件夹在 CallUI文件夹中执行如下命令
```
git clone 步骤1中复制的地址
```
3修改代码
4提交代码到 fork 仓库。
> 修改后的代码,使用git status 查看修改代码,执行 `git add` 命令,然后执行 `git commit` 命令与 `git push` 命令,将代码 push 到我们自己的 fork 仓中。关于代码提交的这部分内容涉及 git 的使用,可以参照 [git官网](https://git-scm.com/) 的内容,在此不再赘述。
### 6.3 发起 Pull Request (PR)
* 在将代码提交到 fork 仓之后,我们可以通过发起 Pull RequestPR的方式来为 OpenHarmony 的相关项目贡献代码。
1打开 fork 仓库。选择 `Pull Requests``新建 Pull Request`
2`新建 Pull Request` 页面填入标题与说明,点击 `创建` 按钮
3创建 Pull Request 完成。 PR 创建完成后,会有专门的代码审查人员对代码进行评审,评审通过之后会合入相应的代码库

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 189 KiB

View File

@ -63,6 +63,14 @@
"autoDesignWidth": false
}
}
],
"reqPermissions" : [
{
"name": "ohos.permission.GET_NETWORK_INFO"
},
{
"name": "ohos.permission.SET_TELEPHONY_STATE"
}
]
}
}

View File

@ -19,9 +19,7 @@
export default {
onCreate() {
console.info('MobileDataApplication onCreate');
},
onDestroy() {
console.info('MobileDataApplication onDestroy');
},
}

View File

@ -34,71 +34,66 @@ struct Index {
build() {
Column() {
Row() {
Image($r("app.media.ic_back"))
.height(24)
.width(24)
.margin({ top:2, bottom: 2, right: 16 })
.onClick(() => {
router.back()
})
Text($r("app.string.mobile_data"))
.height(28)
.lineHeight(28)
.fontSize(20)
.fontWeight(FontWeight.Medium)
.fontColor('#182431')
}
.width("100%")
.height(56)
.padding({ left: 24, top: 14, bottom: 14 })
.margin({ bottom: 8 })
GridContainer({ gutter: 12, margin: 12 }) {
List() {
ListItem() {
Row() {
Image($r("app.media.ic_back"))
.height(24)
.width(24)
.margin({ top:2, bottom: 2, right: 16 })
.onClick(() => {
router.back()
})
Text($r("app.string.mobile_data"))
.height(28)
.lineHeight(28)
.fontSize(20)
.fontWeight(FontWeight.Medium)
.fontColor('#182431')
}
.width("100%")
.height(56)
.padding({ left: 24, top: 14, bottom: 14 })
.margin({ bottom: 8 })
}
ListItem() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Column() {
Row() {
Text($r("app.string.mobile_data"))
.height(22)
.lineHeight(22)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#182431')
}
.margin({ left: 12, top: 14, bottom: 2 })
Text($r("app.string.mobile_data"))
.height(22)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.fontColor('#182431')
.margin({ bottom: 2 })
Row() {
Text($r("app.string.mobile_data_charges"))
.height(19)
.lineHeight(19)
.fontSize(14)
.fontWeight(FontWeight.Regular)
.fontColor('#182431')
.opacity(0.6)
}
.margin({ left: 12, bottom: 15 })
Text($r("app.string.mobile_data_charges"))
.height(19)
.fontSize(14)
.fontWeight(FontWeight.Regular)
.fontColor('#182431')
.opacity(0.6)
}
.margin({ left: 12 })
.alignItems(HorizontalAlign.Start)
.height(64)
Toggle({ type: ToggleType.Switch, isOn: this.isDataEnable })
.onChange((isOn: boolean) => {
if (isOn) {
telephonyData.enableCellularData().then((data) => {
}).catch((error) => {
});
telephonyData.enableCellularData()
.then((data) => {})
.catch((error) => {});
} else {
telephonyData.disableCellularData().then((data) => {
}).catch((error) => {
});
telephonyData.disableCellularData()
.then((data) => {})
.catch((error) => {});
}
})
.height(20)
.width(36)
.margin({ top: 26, bottom: 26, right: 12 })
.margin({ right: 12 })
}
.height(72)
.width('100%')

View File

@ -2,7 +2,7 @@
"string": [
{
"name": "mobiledatasettings_MainAbility",
"value": "mobiledatasettings_MainAbility"
"value": "Phone"
},
{
"name": "mainability_description",
@ -14,7 +14,7 @@
},
{
"name": "mobile_data_charges",
"value": "mobile data charges"
"value": "After activation, the charges incurred are charged by the operator"
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -2,7 +2,7 @@
"string": [
{
"name": "mobiledatasettings_MainAbility",
"value": "mobiledatasettings_MainAbility"
"value": "通话"
},
{
"name": "mainability_description",