HarmonyOS 鸿蒙Next backgroundTaskManager 无法实现后台任务

发布于 1周前 作者 gougou168 来自 鸿蒙OS

HarmonyOS 鸿蒙Next backgroundTaskManager 无法实现后台任务

先上主页代码:

import backgroundTaskManager from ‘@ohos.resourceschedule.backgroundTaskManager’;
import wantAgent, { WantAgent } from ‘@ohos.app.ability.wantAgent’;
@Entry
@Component
struct Maphou {
//路径显示相关
@State @Watch(‘guijimoshiXiangying’) lujingMoshi: number = 0; //显示轨迹路径的模式,1-定位路径,2–定位保存,3–绘制路径
//应用上下文
private context: Context = getContext(this);

startContinuousTask() {
let wantAgentInfo: wantAgent.WantAgentInfo = {
// 点击通知后,将要执行的动作列表
// 添加需要被拉起应用的bundleName和abilityName
wants: [
{
bundleName: “com.example.weixingditust”,
abilityName: “com.example.weixingditust.EntryAbility”
}
],
// 指定点击通知栏消息后的动作是拉起ability
operationType: wantAgent.OperationType.START_ABILITY,
// 使用者自定义的一个私有值
requestCode: 0,
// 点击通知后,动作执行属性
wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
};

// 通过wantAgent模块下getWantAgent方法获取WantAgent对象
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
backgroundTaskManager.startBackgroundRunning(this.context,
backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj).then(() => {
console.info(Succeeded in operationing startBackgroundRunning.);
}).catch((err) => {
console.error(Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message});
});
});
}
stopContinuousTask() {
backgroundTaskManager.stopBackgroundRunning(this.context).then(() => {
console.info(Succeeded in operationing stopBackgroundRunning.);
}).catch((err) => {
console.error(Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message});
});
}
aboutToAppear() {
//申请后台定位权限
let atManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
try {
atManager.requestPermissionsFromUser(this.context, [“ohos.permission.LOCATION_IN_BACKGROUND”]).then((data) => {
let grantStatus: Array<number> = data.authResults;
// 授权成功
hilog.info(0x0000, ‘maphou’, ‘%{public}s’, ‘后台定位授权ok!’ );
//tishiXianshi(‘后台定位授权ok!’)
}).catch((err) => {
hilog.error(0x0000, ‘maphou’, ‘授权失败!信息: %{public}s’, JSON.stringify(err) );
})
}catch (cuowu){
hilog.error(0x0000, ‘maphou’, ‘拉起授权失败!信息: %{public}s’, JSON.stringify(cuowu) );
}

}

build() {
Stack({ alignContent: Alignment.TopStart }) {

    …

//路径轨迹功能图标
Image(this.lianxuDingweiTupian)
.height(45)
.width(45)
.onClick(() => {
if (!this.shifouXuanzhongGuijiTubiao) {
this.lianxuDingweiTupian = $r(‘app.media.guijiLujingTubiao’);
this.guijiMoshiXuanzetankuang.open();
} else {
this.lianxuDingweiTupian = $r(‘app.media.guijiLujingTubiao_heibai’);
this.shifouXianshiLujing = false;
this.shifouXianshiDangqianWeizhi = false;
this.dingdianGongnengXianshiShuxing = Visibility.Hidden;
this.quxiaoLianxuDingwei();
}
this.shifouXuanzhongGuijiTubiao = !this.shifouXuanzhongGuijiTubiao;
})

}

/
* 轨迹模式选择对话框实例
*/
guijiMoshiXuanzetankuang: CustomDialogController = new CustomDialogController({
builder: guijiMoshiXuanze({
guijimoshi: $lujingMoshi,
shijianJiange: $dingweiShijianPinlv,
juliJiange: $dingweiJuliPinlv
}),
customStyle: true, //启用自定义样式
autoCancel: true, //是否允许点击遮障层退出
alignment: DialogAlignment.Center,
offset: { dx: 0, dy: 0 }
})
/
* 轨迹模式选择响应
*/
guijimoshiXiangying() {
switch (this.lujingMoshi) {
case 1:
//实时定位显示
this.shifouXianshiLujing = true;
this.shifouXianshiWeixingXinxi = true;
this.shifouBaocunLujing = false;
this.lujingQingling();
this.lianxuDingweiTupian = $r(“app.media.guijiLujingTubiao”);
this.startContinuousTask();
this.lianxuDingwei(this.dingweiShijianPinlv, this.dingweiJuliPinlv);
this.weixingZhuangtai();
break;
case 2:
//实时定位保存
this.shifouXianshiLujing = true;
this.shifouXianshiWeixingXinxi = true;
this.shifouBaocunLujing = true;
this.lujingQingling();
this.lianxuDingweiTupian = $r(“app.media.guijiLujingTubiao”);
this.startContinuousTask();
this.lianxuDingwei(this.dingweiShijianPinlv, this.dingweiJuliPinlv);
this.weixingZhuangtai();
break;
case 3:
//绘制路径
this.shifouXianshiLujing = true;
this.shifouXianshiWeixingXinxi = false;
this.lujingQingling();
this.shujuCaozuoXinxi = ‘绘制路径’;
this.dingdianGongnengXianshiShuxing = Visibility.Visible;
this.lianxuDingweiTupian = $r(“app.media.guijiLujingTubiao”);
break;
}
}
/
* 连续定位
* @param shijian 时间间隔,秒
* @param juli 距离间隔,米
*/
lianxuDingwei(shijian: number, juli: number) {
try {
geoLocationManager.on(‘locationChange’, {
‘priority’: 0x203,
‘scenario’: 0x301,
‘timeInterval’: shijian,
‘distanceInterval’: juli,
‘maxAccuracy’: 0
}, this.dingweiHuitiaoLX);
} catch (err) {
tishiXianshi(“连续定位错误:” + JSON.stringify(err));
}
}

/

* 取消连续定位
*/
quxiaoLianxuDingwei() {
this.weixingShuliang = ‘’;
try {
geoLocationManager.off(‘locationChange’, this.dingweiHuitiaoLX);
} catch (err) {
tishiXianshi(“取消连续定位错误:” + JSON.stringify(err));
}
if (this.lujingMoshi == 2) {
//保存绘制路径
this.lujingMinglinshi = ‘DWLJ’ + getTimeStr();
this.baocunLujingDuihuakaung.open();
} else {
this.shifouBaocunLujing = false;
this.lujingQingling();
}
this.lujingMoshi = 0;
}
/**
* 连续定位回调
*/
dingweiHuitiaoLX = (weizhi) => {
let chaoquyu: boolean = false;
if (weizhi) {
//更新当前位置
this.dangqiandianGPS = weizhi;
///altitude 高度单位米。,speed速度单位米每秒,direction航向单位是“度”,取值范围为0到360。
//添加轨迹点
let dian: lujingDian = {
xuhao: this.lujingDianJihe.length,
mingcheng: ‘’,
jingdu: weizhi.longitude,
weidu: weizhi.latitude,
sudu: weizhi.speed,
gaodu: weizhi.altitude,
fangxiang: weizhi.direction
}
this.lujingDianJihe.push(dian);
tishiXianshi(‘轨迹点:’ + this.lujingDianJihe.length + ‘个’)
hilog.info(0x0000, BIAOJI, ’ %{public}s’,‘轨迹点:’ + this.lujingDianJihe.length + ‘个’);
//更新画布中心
if (this.shifouChuciDingwei) {
//初次定位
this.lujingDianJihe.length = 0; //初始化轨迹点组
this.shifouChuciDingwei = false;
this.dituZhongxindian = weizhi;
} else {
//当前位置超出画布区域
if (weizhi.longitude >= this.jingweiduFanweiHuabu[1] || weizhi.longitude <= this.jingweiduFanweiHuabu[0] ||
weizhi.latitude >= this.jingweiduFanweiHuabu[3] || weizhi.latitude <= this.jingweiduFanweiHuabu[2]) {
chaoquyu = true;
let zhongxin: geoLocationManager.Location = weizhi;
let jingducha = this.jingweiduFanweiHuabu[1] - this.jingweiduFanweiHuabu[0];
let weiducha = this.jingweiduFanweiHuabu[3] - this.jingweiduFanweiHuabu[2];
//更新画布中心
if (weizhi.longitude >= this.jingweiduFanweiHuabu[1]) {
zhongxin.longitude += jingducha * 0.5;
}
if (weizhi.longitude <= this.jingweiduFanweiHuabu[0]) {
zhongxin.longitude -= jingducha * 0.5;
}
if (weizhi.latitude >= this.jingweiduFanweiHuabu[3]) {
zhongxin.latitude += weiducha * 0.5;
}
if (weizhi.latitude <= this.jingweiduFanweiHuabu[2]) {
zhongxin.latitude -= weiducha * 0.5;
}
this.dituZhongxindian = zhongxin;
}
}
//更新路径数组
this.lujingXiashiGengxin();
this.xianshiShujuGengxin();
}
}

EntryAbility代码:

export default class EntryAbility extends UIAbility {
//需申请的权限集合
private quanxianJihe: Array<Permissions> = [
“ohos.permission.INTERNET”,
“ohos.permission.APPROXIMATELY_LOCATION”,
“ohos.permission.LOCATION”,
“ohos.permission.READ_MEDIA”,
“ohos.permission.WRITE_MEDIA”,
“ohos.permission.KEEP_BACKGROUND_RUNNING”];

onCreate(want, launchParam) {
hilog.info(0x0000, ‘testTag’, ‘%{public}s’, ‘Ability onCreate’);
globalThis.shangxiawen = this.context;
globalThis.wenjianshaxiang = this.context.filesDir;
}

onDestroy() {
hilog.info(0x0000, ‘testTag’, ‘%{public}s’, ‘Ability onDestroy’);
}

async onWindowStageCreate(windowStage: window.WindowStage) {
// Main window is created, set main page for this ability

//申请权限
let atManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
try {
await atManager.requestPermissionsFromUser(this.context, this.quanxianJihe).then((data) => {
let grantStatus: Array<number> = data.authResults;
let length: number = grantStatus.length;
for (let i = 0; i < length; i++) {
if (grantStatus[i] === 0) {
// 用户授权,可以继续访问目标操作
hilog.info(0x0000, “maphou”, “%{public}s”, “权限申请成功!” + this.quanxianJihe[i])
} else {
// 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限
hilog.info(0x0000, “maphou”, “%{public}s”, “用户拒绝授权!” + this.quanxianJihe[i])
return;
}
}
// 授权成功
}).catch((err) => {
hilog.error(0x0000, ‘maphou’, ‘授权失败!信息: %{public}s’, JSON.stringify(err) );
})
}catch (cuowu){
hilog.error(0x0000, ‘maphou’, ‘拉起授权失败!信息: %{public}s’, JSON.stringify(cuowu) );
}
hilog.info(0x0000, ‘testTag’, ‘%{public}s’, ‘Ability onWindowStageCreate’);
windowStage.loadContent(‘pages/Maphou’, (err, data) => {
if (err.code) {
hilog.error(0x0000, ‘testTag’, ‘Failed to load the content. Cause: %{public}s’, JSON.stringify(err) ?? ‘’);
return;
}
hilog.info(0x0000, ‘testTag’, ‘Succeeded in loading the content. Data: %{public}s’, JSON.stringify(data) ?? ‘’);
});
}

onWindowStageDestroy() {
// Main window is destroyed, release UI related resources
hilog.info(0x0000, ‘testTag’, ‘%{public}s’, ‘Ability onWindowStageDestroy’);
}

onForeground() {
// Ability has brought to foreground
hilog.info(0x0000, ‘testTag’, ‘%{public}s’, ‘Ability onForeground’);
}

onBackground() {
// Ability has back to background
hilog.info(0x0000, ‘testTag’, ‘%{public}s’, ‘Ability onBackground’);
}
}

代码:

“abilities”: [
{

“backgroundModes”: [
// 长时任务类型的配置项
“location”
]
}
],
“requestPermissions”: [
{
“name”: “ohos.permission.INTERNET”
},
{
“name”: “ohos.permission.APPROXIMATELY_LOCATION”
},
{
“name”: “ohos.permission.LOCATION”
},
{
“name”: “ohos.permission.LOCATION_IN_BACKGROUND”
},
{
“name”: “ohos.permission.READ_MEDIA”
},
{
“name”: “ohos.permission.WRITE_MEDIA”
},
{
“name”: “ohos.permission.KEEP_BACKGROUND_RUNNING”
}
]

无法拉起后台任务,锁屏或转入后台以后,状态栏显示定位图标,

但是连续定位回调无法连续定位,也无法记录位置变化。

请哪位大侠帮忙,指点迷津!!!


3 回复

太长了 看不下去。。。。。。

针对您提到的HarmonyOS鸿蒙Next系统中的backgroundTaskManager无法实现后台任务的问题,这通常与系统的后台任务管理策略、应用权限设置以及任务本身的合规性有关。

在HarmonyOS中,为了优化用户体验和系统资源,后台任务的执行受到一定的限制。如果backgroundTaskManager无法正常工作,可能是因为:

  1. 应用权限不足:请确保您的应用已获取必要的后台运行权限,如自启动权限、后台任务权限等。

  2. 系统策略限制:HarmonyOS可能根据系统资源、电池状态等因素动态调整后台任务的执行。在电量低或资源紧张时,后台任务可能被限制或终止。

  3. 任务合规性问题:后台任务需要符合系统的合规性要求,如不得进行恶意行为、不得滥用系统资源等。

  4. API使用错误:请检查您的代码是否正确使用了backgroundTaskManager相关的API,包括任务的创建、注册、启动等步骤。

建议您仔细检查上述方面,并参考HarmonyOS的官方文档进行调试。

回到顶部