diff --git a/README.md b/README.md index d3ee02056bf0041440c7cd5107edbef65a373503..1e31784494466e57056f954db882c3c496d82030 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # 基于后台任务实现应用流畅体验 ### 简介 -基于后台任务开发服务实现应用后台保活,本示例分为短时与长时任务模式。短时任务模式使用onApplicationForeground()/onApplicationBackground()监听前后台切换,转后台时申请短时任务。长时模式以位置服务为例,申请长时任务并订阅位置变化,应用切后台时系统仍能自动获取位置信息。 +本示例基于后台任务开发服务实现应用后台保活,短时模式监听前后台切换,转后台即申请短时任务;长时模式以位置服务为例,申请长时任务并订阅位置变化,确保应用后台也能自动获取位置信息。 + ### 效果预览 | **主页面** | **后台申请短时任务页面** | **后台申请长时任务页面** | |:-----------------------------------------------:|:------------------------------------------------------:|:-----------------------------------------------:| | ![](screenshots/device/Home.png) | ![](screenshots/device/ShortTermTaskPage.png) | ![](screenshots/device/LongTermTaskPage.png) | -### 工程目录 + +### 工程目录 ``` ├──entry/src/main/ets // 代码区 │ ├──entryability @@ -37,9 +39,8 @@ 7. 点击“开启定位服务”,日志控制台会周期性地打印出当前的位置信息数据; 8. 在当前页面,把应用最小化之后,日志控制台会周期性地打印出当前的位置信息数据; 9. 注:由于长时模式以位置服务为例,手机需要打开网络/连接有网络的热点且打开手机需要打开“位置”。 - -### 相关权限 +### 相关权限 - 允许应用获取设备位置信息:ohos.permission.LOCATION - 允许应用在后台运行时获取设备位置信息:ohos.permission.LOCATION_IN_BACKGROUND - 允许应用获取设备模糊位置信息:ohos.permission.APPROXIMATELY_LOCATION diff --git a/entry/src/main/ets/utils/SuspendTaskUtils.ets b/entry/src/main/ets/utils/SuspendTaskUtils.ets index ec3fa8b784b4c9547b92d8915a294c2760c43cf7..d8bcc0d3af1c3ebdd6e0b0b86a6bc9ff86d55fd3 100644 --- a/entry/src/main/ets/utils/SuspendTaskUtils.ets +++ b/entry/src/main/ets/utils/SuspendTaskUtils.ets @@ -21,6 +21,8 @@ import { SuspendTaskInfo } from '../viewModel/SuspendTaskInfo'; const TAG: string = '[SuspendTaskUtils]'; class SuspendTaskUtils { + // DocsDode 1 + // BackTaskImplement/entry/src/main/ets/utils/SuspendTaskUtils.ets /** * * @param reason Set the delay task suspension reason @@ -51,7 +53,10 @@ class SuspendTaskUtils { return taskInfo; } } + // DocsDode 1 + // DocsDode 2 + // BackTaskImplement/entry/src/main/ets/utils/SuspendTaskUtils.ets async getRemainingDelayTime(id: number): Promise { let delayTime: number = -1; await backgroundTaskManager.getRemainingDelayTime(id).then((res: number) => { @@ -62,7 +67,10 @@ class SuspendTaskUtils { }); return delayTime; } + // DocsDode 2 + // DocsDode 3 + // BackTaskImplement/entry/src/main/ets/utils/SuspendTaskUtils.ets cancelSuspendDelay(id: number): boolean { try { backgroundTaskManager.cancelSuspendDelay(id); @@ -73,6 +81,7 @@ class SuspendTaskUtils { } return true; } + // DocsDode 3 } let suspendTaskUtils = new SuspendTaskUtils(); diff --git a/entry/src/main/ets/view/LongTermTaskPage.ets b/entry/src/main/ets/view/LongTermTaskPage.ets index 9d3ea107ec7ca5450c6be3fac20e35e8db7a0c84..0f2879fcf3f7a30442c3c15cab89169cbe6efc64 100644 --- a/entry/src/main/ets/view/LongTermTaskPage.ets +++ b/entry/src/main/ets/view/LongTermTaskPage.ets @@ -55,7 +55,10 @@ export struct LongTermTaskPage { Button($r('app.string.turn_off_location_services')) .buttonStyles() .onClick(async () => { + // DocsDode 1 + // BackTaskImplement/entry/src/main/ets/view/LongTermTaskPage.ets geoLocationManager.off('locationChange'); + // DocsDode 1 this.longTermTaskModel.stopLongTask(); }) } diff --git a/entry/src/main/ets/view/ShortTermTaskPage.ets b/entry/src/main/ets/view/ShortTermTaskPage.ets index 74368618984c995bb393eb4c2b573dc04dff2f75..222eb6f1068896421fc641cf873c9bb7953cb74e 100644 --- a/entry/src/main/ets/view/ShortTermTaskPage.ets +++ b/entry/src/main/ets/view/ShortTermTaskPage.ets @@ -50,7 +50,10 @@ export struct ShortTermTaskPage { } build() { + // DocsDode 1 + // BackTaskImplement/entry/src/main/ets/view/ShortTermTaskPage.ets NavDestination() { + // DocsDot Column() { Button($r('app.string.get_remaining_time')) .buttonStyles() @@ -83,6 +86,7 @@ export struct ShortTermTaskPage { .justifyContent(FlexAlign.End) .height('100%') .width('100%') + // DocsDot } .title(this.builderTitle()) .onAppear(() => { @@ -92,6 +96,7 @@ export struct ShortTermTaskPage { hilog.info(0x0000, TAG, `already sent :${this.messageCount} messages`); }, 2000); }) + // DocsDode 1 .onDisAppear(() => { clearInterval(this.taskTimer); SuspendTaskUtils.cancelSuspendDelay(this.shortTermTaskModel.suspendTaskInfo.id); diff --git a/entry/src/main/ets/viewModel/LongTermTaskModel.ets b/entry/src/main/ets/viewModel/LongTermTaskModel.ets index 45aaff295e7ee74c2bcd2048c2c6afc14d07a028..5d3ff6faa1a7b2092ccf4e1e5dcdf82696cb50d7 100644 --- a/entry/src/main/ets/viewModel/LongTermTaskModel.ets +++ b/entry/src/main/ets/viewModel/LongTermTaskModel.ets @@ -24,6 +24,8 @@ const TAG: string = '[LongTermTaskModel]'; export class LongTermTaskModel { private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; + // DocsDode 1 + // BackTaskImplement/entry/src/main/ets/viewModel/LongTermTaskModel.ets // Apply for location-related permissions requestPermissionsFromUser(): void { let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager(); @@ -40,7 +42,10 @@ export class LongTermTaskModel { hilog.error(0x0000, TAG, `requestPermissionsFromUser fail: ${JSON.stringify(err)}`); }); } + // DocsDode 1 + // DocsDode 2 + // BackTaskImplement/entry/src/main/ets/viewModel/LongTermTaskModel.ets locationCallback = async (location: geoLocationManager.Location) => { hilog.info(0x0000, TAG, `locationCallback: data: ${JSON.stringify(location)}`); }; @@ -60,7 +65,10 @@ export class LongTermTaskModel { hilog.error(0x0000, TAG, `errCode: ${JSON.stringify(err)}`); } } + // DocsDode 2 + // DocsDode 3 + // BackTaskImplement/entry/src/main/ets/viewModel/LongTermTaskModel.ets // Start a long task startLongTask(): void { let wantAgentInfo: wantAgent.WantAgentInfo = { @@ -92,7 +100,10 @@ export class LongTermTaskModel { hilog.error(0x0000, TAG, `Operation getWantAgent failed. error is ${JSON.stringify(error)} `); } } + // DocsDode 3 + // DocsDode 4 + // BackTaskImplement/entry/src/main/ets/viewModel/LongTermTaskModel.ets // Stop a long task stopLongTask(): void { backgroundTaskManager.stopBackgroundRunning(this.context).then(() => { @@ -101,4 +112,5 @@ export class LongTermTaskModel { hilog.error(0x0000, TAG, `Operation stopBackgroundRunning failed. error is ${JSON.stringify(error)} `); }); } + // DocsDode 4 } \ No newline at end of file diff --git a/entry/src/main/ets/viewModel/ShortTermTaskModel.ets b/entry/src/main/ets/viewModel/ShortTermTaskModel.ets index 42b254a839d65328da4a04f33bda16a750b31dc4..5d458e046bf27a97508715e98d84ac2a988b7554 100644 --- a/entry/src/main/ets/viewModel/ShortTermTaskModel.ets +++ b/entry/src/main/ets/viewModel/ShortTermTaskModel.ets @@ -24,6 +24,8 @@ export class ShortTermTaskModel { public suspendTaskInfo: SuspendTaskInfo = { id: 0, delayTime: 0 }; private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; + // DocsDode 1 + // BackTaskImplement/entry/src/main/ets/viewModel/ShortTermTaskModel.ets // Apply front - and back-end status monitoring subscribeStateChange() { let that = this; @@ -49,6 +51,7 @@ export class ShortTermTaskModel { `error: ${(paramError as BusinessError).code}, ${(paramError as BusinessError).message}`); } } + // DocsDode 1 offAppStateChange(): void { let applicationContext = this.context.getApplicationContext(); diff --git a/entry/src/main/ets/viewModel/SuspendTaskInfo.ets b/entry/src/main/ets/viewModel/SuspendTaskInfo.ets index 4fa82d00243a3f00712757c0d97ec59902ca0542..c9da70fbe550cfca1fb7ec07080157a789f5cec1 100644 --- a/entry/src/main/ets/viewModel/SuspendTaskInfo.ets +++ b/entry/src/main/ets/viewModel/SuspendTaskInfo.ets @@ -13,7 +13,10 @@ * limitations under the License. */ +// DocsDode 1 +// BackTaskImplement/entry/src/main/ets/viewModel/SuspendTaskInfo.ets export interface SuspendTaskInfo { id: number; // Short-time task ID delayTime: number; // The remaining time of this request short assignment -} \ No newline at end of file +} +// DocsDode 1 \ No newline at end of file diff --git a/entry/src/main/module.json5 b/entry/src/main/module.json5 index 29434c09e837c7c689cc518ff1949c58dd4199e0..60829e540d3b44e1bef604da022299e6b465f60a 100644 --- a/entry/src/main/module.json5 +++ b/entry/src/main/module.json5 @@ -1,5 +1,8 @@ +// DocsDode 1 +// BackTaskImplement/entry/src/main/module.json5 { "module": { + // DocsDot "name": "entry", "type": "entry", "description": "$string:module_desc", @@ -10,10 +13,12 @@ "deliveryWithInstall": true, "installationFree": false, "pages": "$profile:main_pages", + // DocsDot "abilities": [ { "name": "EntryAbility", "srcEntry": "./ets/entryability/EntryAbility.ets", + // DocsDot "description": "$string:EntryAbility_desc", "icon": "$media:layered_image", "label": "$string:EntryAbility_label", @@ -30,11 +35,13 @@ ] } ], + // DocsDot "backgroundModes": [ 'location' ] } ], + // DocsDot "extensionAbilities": [ { "name": "EntryBackupAbility", @@ -49,9 +56,11 @@ ] } ], + // DocsDot "requestPermissions": [ { "name": "ohos.permission.LOCATION", + // DocsDot "reason": "$string:permission_location_desc", "usedScene": { "abilities": [ @@ -59,9 +68,11 @@ ], "when": "inuse" } + // DocsDot }, { "name": "ohos.permission.LOCATION_IN_BACKGROUND", + // DocsDot "reason": "$string:permission_location_background_desc", "usedScene": { "abilities": [ @@ -69,9 +80,11 @@ ], "when": "inuse" } + // DocsDot }, { "name": "ohos.permission.APPROXIMATELY_LOCATION", + // DocsDot "reason": "$string:permission_approximately_location_desc", "usedScene": { "abilities": [ @@ -79,9 +92,11 @@ ], "when": "inuse" } + // DocsDot }, { "name": "ohos.permission.KEEP_BACKGROUND_RUNNING", + // DocsDot "reason": "$string:permission_keep_background_running_desc", "usedScene": { "abilities": [ @@ -89,7 +104,9 @@ ], "when": "inuse" } + // DocsDot } ] } -} \ No newline at end of file +} +// DocsDode 1 \ No newline at end of file