/*
* Copyright (c) 2026 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 type { common, Want } from '@kit.AbilityKit';
import { wantAgent } from '@kit.AbilityKit';
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
import Logger from '../utils/Logger';
const TAG = '[ContinueTaskController]';
function callbackAuth(authResult: backgroundTaskManager.UserAuthResult): void {
Logger.info(TAG, `Operation requestAuthFromUser success. auth result: ${JSON.stringify(authResult)}`);
}
export class ContinueTaskController {
private continuousTaskId?: number = -1;
private context?: common.UIAbilityContext = undefined;
private wantAgentCache?: Want = undefined;
private static instance: ContinueTaskController;
constructor(context: common.UIAbilityContext) {
this.context = context;
}
public static getInstance(context: common.UIAbilityContext): ContinueTaskController {
if (!ContinueTaskController.instance) {
ContinueTaskController.instance = new ContinueTaskController(context);
}
return ContinueTaskController.instance;
}
// [Start task_get_task]
private static getTask(): backgroundTaskManager.ContinuousTaskRequest {
let continuousTaskRequest = new backgroundTaskManager.ContinuousTaskRequest();
let modeList: number[] = [backgroundTaskManager.BackgroundTaskMode.MODE_SPECIAL_SCENARIO_PROCESSING];
continuousTaskRequest.backgroundTaskModes = modeList;
let subModeList: number[] =
[backgroundTaskManager.BackgroundTaskSubmode.SUBMODE_MEDIA_PROCESS_NORMAL_NOTIFICATION];
continuousTaskRequest.backgroundTaskSubmodes = subModeList;
return continuousTaskRequest;
}
// [End task_get_task]
public requestPermit(callback: (authResult: backgroundTaskManager.UserAuthResult) => void = callbackAuth): void {
let continuousTaskRequest = ContinueTaskController.getTask();
try {
continuousTaskRequest.requestAuthFromUser(this.context, callback);
Logger.info(TAG, `Operation requestAuthFromUser success.`);
} catch (error) {
Logger.error(TAG, `Operation requestAUthFromUser failed, code is ${error.code}, message is ${error.message}`);
}
}
public checkSpecialScenarioAuth(): Promise<backgroundTaskManager.UserAuthResult> {
return new Promise((resolve) => {
let continuousTaskRequest = ContinueTaskController.getTask();
continuousTaskRequest.checkSpecialScenarioAuth(this.context)
.then((authResult: backgroundTaskManager.UserAuthResult) => {
Logger.info(TAG, `Operation checkSpecialScenarioAuth success. result is ${authResult}`);
resolve(authResult);
})
.catch((error: BusinessError) => {
resolve(backgroundTaskManager.UserAuthResult.NOT_DETERMINED);
Logger.error(TAG, `Operation checkSpecialScenarioAuth error, code is ${error.code},
message is ${error.message}`);
});
});
}
private async buildWantAgent(): Promise<Want | undefined> {
if (!this.context) {
Logger.error(TAG, `invalid context`);
return undefined;
}
let wantAgentInfo: wantAgent.WantAgentInfo = {
wants: [
{
bundleName: this.context.abilityInfo.bundleName,
abilityName: 'EntryAbility'
}
],
actionType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
};
try {
this.wantAgentCache = await wantAgent.getWantAgent(wantAgentInfo);
return this.wantAgentCache;
} catch (e) {
Logger.error(TAG,
`getWantAgent error, code is ${e.code}, message is ${e.message}`);
return undefined;
}
}
// [Start task_start]
public isRunning(): boolean {
// Prevent duplicate start of background continuous task
return this.continuousTaskId !== undefined && this.continuousTaskId > 0;
}
public async start(): Promise<void> {
if (this.isRunning()) {
Logger.warn(TAG, `continuous task already running, id=${this.continuousTaskId}`);
return;
}
if (!this.context) {
Logger.error(TAG, `invalid context`);
return;
}
try {
let wantAgentObj = this.wantAgentCache ?? await this.buildWantAgent();
if (!wantAgentObj) {
Logger.error(TAG, `wantAgent is undefined`);
return;
}
// Build continuousTaskRequest object
let continuousTaskRequest: backgroundTaskManager.ContinuousTaskRequest = ContinueTaskController.getTask();
if (continuousTaskRequest === undefined) {
Logger.info(TAG, `continuousTaskRequest is undefined`);
return;
}
continuousTaskRequest.wantAgent = wantAgentObj;
continuousTaskRequest.combinedTaskNotification = false;
continuousTaskRequest.continuousTaskId = -1;
let res: backgroundTaskManager.ContinuousTaskNotification =
await backgroundTaskManager.startBackgroundRunning(this.context, continuousTaskRequest);
Logger.info(TAG,
`Operation startBackgroundRunning succeeded.
notificationId=${res.notificationId} continuousTaskId=${res.continuousTaskId}`);
this.continuousTaskId = res.continuousTaskId;
} catch (error) {
Logger.error(TAG, `Operation startBackgroundRunning failed, code is ${error.code}, message is ${error.message}`);
}
}
// [End task_start]
public async stop(): Promise<void> {
try {
await backgroundTaskManager.stopBackgroundRunning(this.context, this.continuousTaskId);
this.continuousTaskId = -1;
Logger.info(TAG, `Operation stopBackgroundRunnning succ`);
} catch (error) {
Logger.error(TAG, `Operation stopBackgroundRunnning failed, code is ${error.code}, message is ${error.message}`);
}
}
}