二、长时任务
1.为什么使用长时任务
- 需要长时间在后台运行, 并且需要用户可以感知( 音频播放, 导航 )的事件
- 防止一段时间以后, 因为 App 被挂起, 导致系统管控导致运行结束
2.长时任务类型
3.长时任务限制
- 一个应用的同一个 UIiAbility 只能同时申请一个长时任务
- 你要根据你不同的长时任务类型, 去 module.json5 文件中申请不同的权限
- 所有的长时任务都需要 want 对象, 因为他需要拉起 Ability
- api
- startBackgroundRunning 申请长时任务
- stopBackgroundRunning 取消长时任务
4.长时任务示例(音频播放)
4.1 权限配置
-
申请权限 ohos.permission.KEEP_BACKGROUND_RUNNING
-
src > main > module.json5
"requestPermissions": [ { "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" } ],
-
-
声明后台模式类型,参照长时任务类型
-
src > main > module.json5 配置 backgroundModes
{ "module": { "name": "entry", "type": "entry", "description": "$string:module_desc", "mainElement": "EntryAbility", // 权限 "requestPermissions": [ { "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" } ], "deviceTypes": [ "phone", "tablet", "2in1" ], "deliveryWithInstall": true, "installationFree": false, "pages": "$profile:main_pages", "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", "description": "$string:EntryAbility_desc", // 后台模式类型 "backgroundModes":[ "audioPlayback" ], "icon": "$media:layered_image", "label": "$string:EntryAbility_label", "startWindowIcon": "$media:startIcon", "startWindowBackground": "$color:start_window_background", "exported": true, "skills": [ { "entities": [ "entity.system.home" ], "actions": [ "action.system.home" ] } ] } ] } }
-
4.2 导入模块
import { media } from '@kit.MediaKit'
import { common, WantAgent, wantAgent } from '@kit.AbilityKit'
import { backgroundTaskManager } from '@kit.BackgroundTasksKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { avSession } from '@kit.AVSessionKit'
4.3 音频播放
// 创建变量
AVPlayer: media.AVPlayer = Object()
async audioPlay() {
const avplayer = await media.createAVPlayer()
this.setStateEventHandler(avplayer)
// 传递 音频 url 地址
avplayer.url = ''
// 复制给私有变量
this.AVPlayer = avplayer
// 音乐在后台播放需要有音乐控制器 AVSession
// const session = await avSession.createAVSession(上下文, 描述, 类型)
const session = await avSession.createAVSession(this.context, '音乐播放测试', 'audio')
// 给 session 注册一些事件来完成不同的动作
// 如果你想让他完整的使用, 那么你的 AVPlayer 的状态机( 注册机需要调用完整 ) ,通过方法 setStateEventHandler()
session.on('play', () => {
this.AVPlayer.play()
})
session.on('pause', () => {
this.AVPlayer.pause()
})
// 让当前 session 执行起来
session.activate()
}
4.4 状态机
// 状态机实际上就是监听 AVPlayer 的状态变化, 然后做对应的动作
// 给当前 AVPlayer 绑定各种事件
setStateEventHandler(avplayer: media.AVPlayer) {
avplayer.on('stateChange', (state: string) => {
if (state === 'idle') {
// 注销当前实例( 把当前播放器注销掉, 不管将来发生什么, 你如果不主动播放, 都不会播放了 )
// Care : 你切换下一首歌的时候, 也会进入一次 idle
this.player.release()
//
// // 取消长时任务( 因为一个应用的一个Ability 只能同时申请一个长时任务, 所以不需要 id , 我们直接取消任务即可 )
backgroundTaskManager.stopBackgroundRunning(this.context)
}
if (state === 'initialized') {
// 表示音频播放器初始化成功
// 在这来开始准备音频播放
// avplayer.prepare()
}
if (state === 'prepared') {
}
if (state === 'playing') {
}
if (state === 'paused') {
}
})
}
4.5 开启长时任务
// 点击事件-启动长时任务-开启音频播放
clickHandler() {
// 需要申请一个长时任务
// 准备一个 want 对象
const wantAgentInfo: wantAgent.WantAgentInfo = {
wants: [
{
bundleName: 'com.example.mytask',
abilityName: 'EntryAbility'
}
],
// 表示点击通知栏的时候的动作( 我这里选择的事 拉起 Ability )
actionType: wantAgent.OperationType.START_ABILITY,
// 自己定义的一个私有值
requestCode: 10086,
// 点击以后执行的动作
actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
}
// 生成通知内容
wantAgent
.getWantAgent(wantAgentInfo)
.then((data: WantAgent) => {
// 申请长时任务即可
// backgroundTaskManager.startBackgroundRunning(当前的上下文, 后台任务类型, want 对象)
backgroundTaskManager
.startBackgroundRunning(
this.context,
backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
data
)
.then(() => {
// 在这里面表示长时任务申请成功
console.log('DeepCode => 长时任务申请成功')
// 可以执行你需要的长时任务了( 目前: 播放音乐 )
this.AVPlayer.play()
.then((data)=>{
console.log('wuwuwu play success =>', JSON.stringify(data));
})
.catch((err: Error) => {
console.log('wuwuwu play =>', JSON.stringify(err));
})
})
.catch((err: BusinessError) => {
// 表示长时任务申请失败
console.log('wuwuwu => 长时任务申请失败, 失败原因 ' + JSON.stringify(err))
})
})
.catch((err: BusinessError) => {
console.log('wuwuwu => 创建 want 信息对象失败, 失败原因 : ' + JSON.stringify(err))
})
}