在module.json5配置文件中abilities下的backgroundModes字段里,为需要使用长时任务的UIAbility声明相应的长时任务类型,配置文件中填写长时任务类型的配置项。
"backgroundModes": [
"location"
], import { geoLocationManager } from '@kit.LocationKit';
import { abilityAccessCtrl, common, PermissionRequestResult, Permissions, WantAgent, wantAgent } from '@kit.AbilityKit';
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
@State workingState: boolean = false;
@State locationInfos: Array<LocationInfo> = [];
// Start solution1
aboutToAppear() {
// 申请定位权限
let permissions: Array<Permissions> = ['ohos.permission.LOCATION', 'ohos.permission.APPROXIMATELY_LOCATION'];
this.reqPermissionsFromUser(permissions);
}
reqPermissionsFromUser(permissions: Array<Permissions>): void {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗
atManager.requestPermissionsFromUser(this.context, permissions).then((data: PermissionRequestResult) => {
console.info(`requestPermissionsFromUser success, result: ${JSON.stringify(data)}`);
}).catch((err: BusinessError) => {
console.error(`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}`);
});
}
// End solution1
build() {
Column({ space: 16 }) {
Row() {
Column({ space: 20 }) {
Row({ space: 15 }) {
Image($r('sys.media.person_shield'))
.width(30)
.height(30)
Text('张三')
}
Text('外出场所:大运广场')
}
.alignItems(HorizontalAlign.Start)
.width('70%')
Blank().width(2).backgroundColor(Color.Gray)
Column() {
Column() {
if (this.workingState) {
Text('结束')
} else {
Text('开始')
}
Text('工作')
}
.padding(5)
.backgroundColor(this.workingState ? '#E84026' : '#64BB5C')
.borderRadius($r('sys.float.corner_radius_level4'))
.onClick(() => {
if (this.workingState) {
this.offLocationListen();
this.stopContinuousTask();
} else {
this.getLocation();
this.startContinuousTask();
}
});
}
.width('29%')
}
.width('100%')
.padding(14)
.borderRadius(8)
.backgroundColor(Color.White)
Column() {
Row() {
Text('位置信息列表')
Text(`Total: ${this.locationInfos.length}`)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
Scroll() {
List({ space: 5 }) {
ForEach(this.locationInfos, (item: LocationInfo) => {
ListItem() {
Column() {
Text(`时间:${item.time}`)
Text(`坐标:[${item.latitude}, ${item.longitude}]`)
Text(`地址:${item.address}`)
}
.width('100%')
.padding(5)
.borderRadius(5)
.alignItems(HorizontalAlign.Start)
.backgroundColor('#0C0A59F7')
}
})
}
}
.scrollBar(BarState.Off)
.padding({ top: 5, bottom: 10 })
}
.width('100%')
.height('100%')
.padding(14)
.borderRadius(8)
.flexShrink(999)
.backgroundColor(Color.White)
}
.height('100%')
.width('100%')
.padding(12)
.backgroundColor('#f1f3f5')
}
locationChange = async (location: geoLocationManager.Location) => {
if (location) {
this.workingState = true;
if (this.locationInfos.length >= 50) {
this.locationInfos.pop();
}
let info = new LocationInfo();
info.location = location;
info.latitude = location?.latitude.toFixed(5);
info.longitude = location?.longitude.toFixed(5);
info.time = new Date(location?.timeStamp).toLocaleString('zh-CN', { hour12: false });
let address = await this.getAddressFromLocation(location.latitude, location.longitude);
info.address = address;
this.locationInfos.push(info);
}
};
/**
* 每隔2秒上报一次位置
*/
getLocation() {
let requestInfo: geoLocationManager.LocationRequest = {
'priority': geoLocationManager.LocationRequestPriority.FIRST_FIX,
'scenario': geoLocationManager.LocationRequestScenario.UNSET,
'timeInterval': 2,
'distanceInterval': 0,
'maxAccuracy': 0
};
try {
geoLocationManager.on('locationChange', requestInfo, this.locationChange);
} catch (err) {
console.error(`getLocation errCode: ${err?.code},errMessage: ${err?.message}`);
}
}
/**
* 坐标转化为地址
*/
async getAddressFromLocation(lati: number, long: number): Promise<string> {
let address: string | undefined = '';
let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest = {
'latitude': lati,
'longitude': long,
'maxItems': 1
};
let locationResult = await geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest);
console.log(`locationResult => ${JSON.stringify(locationResult)}`);
if (locationResult && locationResult.length > 0) {
address = locationResult[0].placeName;
}
return address ? address : '';
}
/**
* 关闭位置上报
*/
offLocationListen() {
try {
// 需要取消订阅的回调函数。该回调函数需要与on接口传入的回调函数保持一致。若无此参数,则取消当前类型的所有订阅。
geoLocationManager.off('locationChange', this.locationChange);
this.workingState = false;
this.locationInfos = [];
} catch (err) {
console.error(`offLocationListen errCode: ${err?.code},errMessage: ${err?.message}`);
}
}
startContinuousTask() {
let wantAgentInfo: wantAgent.WantAgentInfo = {
// 点击通知后,将要执行的动作列表
// 添加需要被拉起应用的bundleName和abilityName
wants: [
{
bundleName: this.context.abilityInfo.bundleName,
abilityName: 'EntryAbility'
}
],
// 指定点击通知栏消息后的动作是拉起ability
actionType: wantAgent.OperationType.START_ABILITY,
// 使用者自定义的一个私有值
requestCode: 0,
// 点击通知后,动作执行属性
actionFlags: [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 operating startBackgroundRunning.`);
}).catch((err: BusinessError) => {
console.error(`Failed to operation startBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
});
});
}
stopContinuousTask() {
backgroundTaskManager.stopBackgroundRunning(this.context).then(() => {
console.info(`Succeeded in operating stopBackgroundRunning.`);
}).catch((err: BusinessError) => {
console.error(`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}`);
});
}
}
class LocationInfo {
public location: geoLocationManager.Location | undefined;
public latitude: string = '';
public longitude: string = '';
public address: string = '';
public time: string = '';
}