1/** 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import dataShare from '@ohos.data.dataShare'; 17import dataSharePredicates from "@ohos.data.dataSharePredicates"; 18import ICallLogRepository from './ICallLogRepository'; 19import { CallLog } from '../entity/CallLog'; 20import CallLogBuilder from '../entity/CallLogBuilder'; 21import Calls from '../contract/Calls'; 22import CallLogDelta from './CallLogDelta'; 23import { StringUtil } from '../../../../../../common/src/main/ets/util/StringUtil'; 24import { HiLog } from '../../../../../../common/src/main/ets/util/HiLog'; 25import { ArrayUtil } from '../../../../../../common/src/main/ets/util/ArrayUtil'; 26 27const TAG = "CallLogRepository"; 28 29/** 30 * Account type service, which is used to display account characteristics such as account type holding contact details. 31 */ 32export class CallLogRepository implements ICallLogRepository { 33 private static instance: CallLogRepository; 34 private dataShareHelper; 35 private context: Context 36 37 private constructor() { 38 } 39 40 /* 41 * init if Call From serviceAbility globalThis.context is Null 42 *@param ctx Context used for dataShare 43 */ 44 init(ctx: Context) { 45 this.context = ctx; 46 } 47 48 public static getInstance(): CallLogRepository { 49 if (!CallLogRepository.instance) { 50 CallLogRepository.instance = new CallLogRepository() 51 } 52 return CallLogRepository.instance 53 } 54 55 private async getDataAbilityHelper() { 56 if (this.dataShareHelper == undefined) { 57 this.dataShareHelper = await dataShare.createDataShareHelper(this.context ? this.context : globalThis.context, 58 Calls.CONTENT_URI); 59 } 60 return this.dataShareHelper; 61 } 62 63 saveOne(callLog: CallLog, callback) { 64 if (callLog.id <= 0) { 65 this.getDataAbilityHelper().then((dataAbilityHelper) => { 66 let callLogDelta = new CallLogDelta(callLog); 67 dataAbilityHelper.insert(Calls.CALL_LOG_URI, callLogDelta.createValuesBucket()).then(data => { 68 callback(data); 69 }).catch(error => { 70 HiLog.w(TAG, 'saveOne error:%s', JSON.stringify(error.message)); 71 callback(); 72 }); 73 }).catch(error => { 74 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 75 callback(); 76 }); 77 } else { 78 callback(); 79 } 80 } 81 82 clear(callback) { 83 this.getDataAbilityHelper().then((dataAbilityHelper) => { 84 let condition = new dataSharePredicates.DataSharePredicates(); 85 dataAbilityHelper.delete(Calls.CALL_LOG_URI, condition).then(data => { 86 callback(data); 87 }).catch(error => { 88 HiLog.w(TAG, 'clear error:%s', JSON.stringify(error.message)); 89 callback(); 90 }); 91 }).catch(error => { 92 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 93 callback(); 94 }); 95 } 96 97 deleteById(id: number) { 98 return false; 99 } 100 101 deleteByIdIn(ids: number[], callback) { 102 if (ArrayUtil.isEmpty(ids)) { 103 callback(); 104 return; 105 } 106 this.getDataAbilityHelper().then((dataAbilityHelper) => { 107 let condition = new dataSharePredicates.DataSharePredicates(); 108 condition.in(Calls.ID, ids); 109 dataAbilityHelper.delete(Calls.CALL_LOG_URI, condition).then(data => { 110 callback(data); 111 }).catch(error => { 112 HiLog.w(TAG, 'deleteByIdIn error:%s', JSON.stringify(error.message)); 113 callback(); 114 }); 115 }).catch(error => { 116 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 117 callback(); 118 }); 119 } 120 121 deleteByNumber(number: string) { 122 return false; 123 } 124 125 deleteByLookupUri(number: string) { 126 return false; 127 } 128 129 readByNumber(number: string) { 130 return false; 131 } 132 133 readById(id: number) { 134 return false; 135 } 136 137 findAll(actionData, callback) { 138 this.getDataAbilityHelper().then((dataAbilityHelper) => { 139 let condition = new dataSharePredicates.DataSharePredicates(); 140 let offset = actionData.page < 3 ? (actionData.page - 1) * 50 : (actionData.page - 2) * 500 + 50; 141 condition.limit(actionData.limit, offset); 142 condition.orderByDesc(Calls.CREATE_TIME); 143 dataAbilityHelper.query(Calls.CALL_LOG_URI, condition, null).then(resultSet => { 144 let rst: CallLog[] = []; 145 if (resultSet.rowCount === 0) { 146 resultSet.close(); 147 callback(rst); 148 } else { 149 resultSet.goToFirstRow(); 150 do { 151 let builder = CallLogBuilder.fromResultSet(resultSet); 152 if (builder.id > 0) { 153 rst.push(new CallLog(builder)); 154 } 155 } while (resultSet.goToNextRow()); 156 resultSet.close(); 157 callback(rst); 158 } 159 }).catch(error => { 160 HiLog.w(TAG, 'findAll error:' + JSON.stringify(error.message)); 161 callback([]); 162 }); 163 }).catch(error => { 164 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 165 callback([]); 166 }); 167 } 168 169 findByFeature(feature: number) { 170 return []; 171 } 172 173 findByNumberIn(numbers: number[], callback) { 174 if (ArrayUtil.isEmpty(numbers)) { 175 callback([]); 176 return; 177 } 178 this.getDataAbilityHelper().then((dataAbilityHelper) => { 179 let realPhoneNumbers = []; 180 for (let key in numbers) { 181 let phoneNumber = StringUtil.removeSpace(numbers[key].toString()); 182 realPhoneNumbers.push(phoneNumber); 183 } 184 let condition = new dataSharePredicates.DataSharePredicates(); 185 condition.in(Calls.PHONE_NUMBER, realPhoneNumbers); 186 condition.orderByDesc(Calls.CREATE_TIME); 187 dataAbilityHelper.query(Calls.CALL_LOG_URI, condition, null).then(resultSet => { 188 let rst: CallLog[] = []; 189 if (resultSet.rowCount === 0) { 190 resultSet.close(); 191 callback(rst); 192 } else { 193 resultSet.goToFirstRow(); 194 do { 195 let builder = CallLogBuilder.fromResultSet(resultSet); 196 if (builder.id > 0) { 197 rst.push(new CallLog(builder)); 198 } 199 } while (resultSet.goToNextRow()); 200 resultSet.close(); 201 callback(rst); 202 } 203 }).catch(error => { 204 HiLog.w(TAG, 'findByNumberIn error:%s', JSON.stringify(error.message)); 205 callback([]); 206 }); 207 }).catch(error => { 208 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 209 callback([]); 210 }); 211 } 212 213 markMissedCallLogAsRead(phoneNum?: string) { 214 this.getDataAbilityHelper().then((dataAbilityHelper) => { 215 let condition = new dataSharePredicates.DataSharePredicates(); 216 condition.equalTo(Calls.IS_READ, 0) 217 .and().equalTo(Calls.CALL_DIRECTION, 0); 218 if (phoneNum && !StringUtil.isEmpty(phoneNum)) { 219 condition.and().equalTo(Calls.PHONE_NUMBER, phoneNum); 220 } 221 dataAbilityHelper.update(Calls.CALL_LOG_URI, condition, { 222 "is_read": 1 223 }).then(value => { 224 HiLog.i(TAG, 'markMissedCallLogIsRead update succ :%d', value); 225 }).catch(error => { 226 HiLog.w(TAG, 'markMissedCallLogIsRead error:%s', JSON.stringify(error.message)); 227 }); 228 }).catch(error => { 229 HiLog.w(TAG, 'markMissedCallLogIsRead error:%s' + JSON.stringify(error.message)); 230 }); 231 } 232 233 findMissedCallLogUnread(callback, lastId?: number) { 234 this.getDataAbilityHelper().then((dataAbilityHelper) => { 235 let condition = new dataSharePredicates.DataSharePredicates(); 236 condition.equalTo(Calls.IS_READ, 0).and().equalTo(Calls.CALL_DIRECTION, 0).and().equalTo(Calls.ANSWER_STATE, 0); 237 238 if (lastId && lastId > -1) { 239 condition.and().greaterThan(Calls.ID, lastId); 240 } 241 condition.orderByDesc(Calls.ID); 242 dataAbilityHelper.query(Calls.CALL_LOG_URI, condition, null).then(resultSet => { 243 let rst: CallLog[] = []; 244 if (resultSet.rowCount === 0) { 245 resultSet.close(); 246 callback(rst); 247 } else { 248 resultSet.goToFirstRow(); 249 do { 250 let builder = CallLogBuilder.fromResultSet(resultSet); 251 if (builder.id > 0) { 252 rst.push(new CallLog(builder)); 253 } 254 } while (resultSet.goToNextRow()); 255 resultSet.close(); 256 callback(rst); 257 } 258 }).catch(error => { 259 HiLog.w(TAG, 'findMissedCallLogUnread resultSet parse error:%s', JSON.stringify(error.message)); 260 callback([]); 261 }); 262 }).catch(error => { 263 HiLog.w(TAG, 'findMissedCallLogUnread error:%s' + JSON.stringify(error.message)); 264 callback([]); 265 }); 266 } 267 268 notifyChange() { 269 this.getDataAbilityHelper().then((dataAbilityHelper) => { 270 if (dataAbilityHelper) { 271 dataAbilityHelper.notifyChange(Calls.CALL_LOG_URI).then((data) => { 272 HiLog.i(TAG, "notifyChange success") 273 }).catch(error => { 274 HiLog.w(TAG, 'notifyChange error:%s' + JSON.stringify(error.message)); 275 }) 276 } 277 }).catch(error => { 278 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 279 }); 280 } 281 282 registerDataChangeObserver(callback) { 283 this.getDataAbilityHelper().then((dataAbilityHelper) => { 284 if (dataAbilityHelper) { 285 dataAbilityHelper.on("dataChange", Calls.CALL_LOG_URI, callback); 286 } 287 }).catch(error => { 288 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 289 }); 290 } 291 292 unRegisterDataChangeObserver(callback) { 293 this.getDataAbilityHelper().then((dataAbilityHelper) => { 294 if (dataAbilityHelper) { 295 dataAbilityHelper.off("dataChange", Calls.CALL_LOG_URI, callback); 296 } 297 }).catch(error => { 298 HiLog.w(TAG, 'error:%s' + JSON.stringify(error.message)); 299 }); 300 } 301}