04-24 20:51:29.264 998 2232 W C01713/resource_schedule_service/SUSPEND_MANAGER: [(ReportKillAppEvent):277] hisysevent write result=0, send event [FRAMEWORK,PROCESS_KILL], pid=64424, processName=com.hm.example, msg=Kill Reason:ILLEGAL_AUDIO_CAPTURER_BY_SUSPEND, foreground=0 04-24 20:51:29.264 3674 3674 I A01B05/com.ohos.sceneboard/AOD: AodSettingsModule --> Check isInTimeRange, currentTime: 1745499089264, startTime: 1745449200000, endTime: 1745506800000 04-24 20:51:29.264 998 2232 I C01713/resource_schedule_service/SUSPEND_MANAGER: [(IsKillAppWhenIllegalUseAudio):248] Application 20020222_com.hm.example_[64424] current has media and not apply background_task or Resource::AUDIO
04-24 20:50:57.360 998 1306 I C01724/resource_schedule_service/TASK_DETECTION: [UpdateAudioRecord:89]Get Audio info uid: 20020222, sessionId: 100020, State: 2, type: player, streamType: 1 04-24 20:50:57.419 998 1307 I C01724/resource_schedule_service/TASK_DETECTION: [UpdateAudioRecord:89]Get Audio info uid: 20020222, sessionId: 100021, State: 2, type: recorder, streamType: 0 04-24 20:51:27.254 998 2230 I C01724/resource_schedule_service/TASK_DETECTION: [OnAppStateChanged:595]Application State change to background, uid: 20020222, pid: 64424,bundleName: com.hm.example // ... 04-24 20:51:29.309 998 2136 I C01724/resource_schedule_service/TASK_DETECTION: [UpdateAudioRecord:103]Get Audio info uid: 20020222, sessionId: 100020, State: 4, type: player, streamType: 1 04-24 20:51:29.309 998 2136 I C01724/resource_schedule_service/TASK_DETECTION: [UpdateAudioRecord:103]Get Audio info uid: 20020222, sessionId: 100021, State: 4, type: recorder, streamType: 0
04-24 20:51:03.376 998 1173 I C01713/resource_schedule_service/SUSPEND_MANAGER: [(FreezePids):246] Freeze pid: 59581 success. 04-24 20:51:09.392 998 1173 I C01713/resource_schedule_service/SUSPEND_MANAGER: [(FreezePids):246] Freeze pid: 59581 success. 04-24 20:51:29.258 998 1173 I C01713/resource_schedule_service/SUSPEND_MANAGER: [(FreezePids):246] Freeze pid: 64424 success. 04-24 20:51:40.381 998 1173 I C01713/resource_schedule_service/SUSPEND_MANAGER: [(FreezePids):246] Freeze pid: 3847 success. 04-24 20:51:40.384 998 1173 I C01713/resource_schedule_service/SUSPEND_MANAGER: [(FreezePids):246] Freeze pid: 3653 success.
04-24 20:51:29.264 64424 64424 I C01711/com.hm.example/CONTINUOUS_TASK: [GetModes:433] get bgModes arraylen: 2 04-24 20:51:29.264 64424 64424 I C01711/com.hm.example/CONTINUOUS_TASK: [GetModes:449] GetBackgroundMode audioRecording. 04-24 20:51:29.264 64424 64424 I C01711/com.hm.example/CONTINUOUS_TASK: [GetModes:449] GetBackgroundMode audioPlayback. 04-24 20:51:29.267 64424 65310 I C01711/com.hm.example/CONTINUOUS_TASK: [StartBackgroundRunningExecuteCB:240] RequestStartBackgroundRunning isBatch: 1, bgModeSize: 2
参考长时任务(ArkTS),在开始录音时开启长时任务,在停止录音时停止长时任务。
import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { fileIo as fs } from '@kit.CoreFileKit';
import { abilityAccessCtrl, WantAgent, wantAgent } from '@kit.AbilityKit';
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
@Entry
@Component
export struct AudioRecordPage {
private avRecorder: media.AVRecorder | undefined = undefined;
private avProfile: media.AVRecorderProfile = {
audioBitrate: 112000, // 音频比特率。
audioChannels: 2, // 音频声道数。
audioCodec: media.CodecMimeType.AUDIO_AAC, // 音频编码格式,当前支持ACC,MP3,G711MU。
audioSampleRate: 48000, // 音频采样率。
fileFormat: media.ContainerFormatType.CFT_MPEG_4A, // 封装格式,当前支持MP4,M4A,MP3,WAV,AMR,AAC。
};
private avConfig: media.AVRecorderConfig = {
audioSourceType: media.AudioSourceType.AUDIO_SOURCE_TYPE_MIC, // 音频输入源,这里设置为麦克风。
profile: this.avProfile,
url: 'fd://35', // 参考应用文件访问与管理开发示例新建并读写一个文件。
};
private fileFd: number = 0;
// 通过getUIContext().getHostContext()方法,来获取page所在的UIAbility上下文
private context: Context | undefined = this.getUIContext().getHostContext();
@State recordState: string = '未开始录制';
@State longTaskState: string = '未申请';
startContinuousTask() {
let wantAgentInfo: wantAgent.WantAgentInfo = {
// 点击通知后,将要执行的动作列表
// 添加需要被拉起应用的bundleName和abilityName
wants: [
{
bundleName: 'com.example.commondemofordfx',
abilityName: 'EntryAbility'
}
],
// 指定点击通知栏消息后的动作是拉起ability
actionType: wantAgent.OperationType.START_ABILITY,
// 使用者自定义的一个私有值
requestCode: 0,
// 点击通知后,动作执行属性
actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG],
// 车钥匙长时任务子类型。只有申请bluetoothInteraction类型的长时任务,车钥匙子类型才能生效。
};
try {
// 通过wantAgent模块下getWantAgent方法获取WantAgent对象
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
try {
let list: Array<string> = ['audioRecording'];
backgroundTaskManager.startBackgroundRunning(this.context, list, wantAgentObj).then(() => {
console.info('Operation startBackgroundRunning succeeded');
// 此处执行具体的长时任务逻辑,如录音,录制等。
this.longTaskState = '已申请';
}).catch((error: BusinessError) => {
console.error(`Failed to Operation startBackgroundRunning. code is ${error.code} message is ${error.message}`);
});
} catch (error) {
console.error(`Failed to Operation startBackgroundRunning. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
}
});
} catch (error) {
console.error(`Failed to Operation getWantAgent. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
}
}
stopContinuousTask() {
backgroundTaskManager.stopBackgroundRunning(this.context).then(() => {
console.info(`Succeeded in operationing stopBackgroundRunning.`);
this.longTaskState = '已取消';
}).catch((err: BusinessError) => {
console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
});
}
// 创建文件以及设置avConfig.url。
async createAndSetFd(): Promise<void> {
const context: Context = this.getUIContext().getHostContext()!; // 非空断言,Context类型且非空
const path: string = context.filesDir + '/example.mp3'; // 文件沙箱路径,文件后缀名应与封装格式对应。
const audioFile: fs.File | null = null;
try {
const audioFile: fs.File = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
this.avConfig.url = 'fd://' + audioFile.fd; // 更新url。
this.fileFd = audioFile.fd;
} catch (error) {
console.error(`Failed to openSync. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
} finally {
if (audioFile !== null) {
fs.closeSync(audioFile);
}
}
}
// 注册audioRecorder回调函数。
setAudioRecorderCallback() {
if (this.avRecorder !== undefined) {
// 状态机变化回调函数。
this.avRecorder.on('stateChange', (state: media.AVRecorderState) => {
console.info(`Aud ioRecorder current state is ${state.toString()}`);
this.recordState = state;
});
// 错误上报回调函数。
this.avRecorder.on('error', (err: BusinessError) => {
console.error(`AudioRecorder failed, code is ${err.code}, message is ${err.message}`);
});
}
}
// 开始录制对应的流程。
async startRecordingProcess() {
if (this.avRecorder !== undefined) {
await this.avRecorder.release();
this.avRecorder = undefined;
}
// 1.创建录制实例。
this.avRecorder = await media.createAVRecorder();
this.setAudioRecorderCallback();
// 2.获取录制文件fd赋予avConfig里的url;参考FilePicker文档。
this.createAndSetFd();
// 3.配置录制参数完成准备工作。
await this.avRecorder.prepare(this.avConfig);
// 4.开始录制。
await this.avRecorder.start();
}
// 暂停录制对应的流程。
async pauseRecordingProcess() {
if (this.avRecorder !== undefined && this.avRecorder.state === 'started') { // 仅在started状态下调用pause为合理状态切换。
await this.avRecorder.pause();
}
}
// 恢复录制对应的流程。
async resumeRecordingProcess() {
if (this.avRecorder !== undefined && this.avRecorder.state === 'paused') { // 仅在paused状态下调用resume为合理状态切换。
await this.avRecorder.resume();
}
}
// 停止录制对应的流程。
async stopRecordingProcess() {
if (this.avRecorder !== undefined) {
// 1. 停止录制。
if (this.avRecorder.state === 'started' ||
this.avRecorder.state === 'paused') { // 仅在started或者paused状态下调用stop为合理状态切换。
await this.avRecorder.stop();
}
// 2.重置。
await this.avRecorder.reset();
// 3.释放录制实例。
await this.avRecorder.release();
this.avRecorder = undefined;
// 4.关闭录制文件fd。
await fs.close(this.fileFd);
}
}
async checkPermissions(): Promise<void> {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
atManager.requestPermissionsFromUser(this.context, [
'ohos.permission.MICROPHONE',
], () => {
console.info('request camera permission');
});
}
aboutToAppear(): void {
this.checkPermissions();
if (this.avRecorder !== undefined) {
if (this.avRecorder.state === 'paused') {
this.resumeRecordingProcess();
}
}
}
aboutToDisappear(): void {
if (this.avRecorder !== undefined) {
if (this.avRecorder.state === 'started') {
this.pauseRecordingProcess();
}
}
}
build() {
Column({ space: 10 }) {
Text(`录制状态:${this.recordState}`)
.fontSize(20)
Button('开始录音')
.onClick(() => {
this.startRecordingProcess();
})
Button('暂停录音')
.onClick(() => {
this.pauseRecordingProcess();
})
Button('恢复录音')
.onClick(() => {
this.resumeRecordingProcess();
})
Button('停止录音')
.onClick(() => {
this.stopRecordingProcess();
})
Text(`长时任务状态:${this.longTaskState}`)
.fontSize(20)
Button('申请长时任务')
.onClick(() => {
// 通过按钮申请长时任务
this.startContinuousTask();
})
Button('取消长时任务')
.onClick(() => {
// 通过按钮取消长时任务
this.stopContinuousTask();
})
}
.width('100%')
.height('100%')
.margin({ top: 30 })
}
}