当前位置:网站首页>运动App如何实现端侧后台保活,让运动记录更完整?
运动App如何实现端侧后台保活,让运动记录更完整?
2022-06-28 15:48:00 【51CTO】
你在锻炼健身时,有没有遇到这样的情况?辛辛苦苦锻炼了几小时,却发现App停止了运行,本次运动并没有被记录到App上,从而失去了一个查看完整运动数据的机会?
运动类App是通过手机或者穿戴设备的传感器,来识别运动状态并反馈给用户的,App能否在手机后台时刻保持运行是影响运动数据完整性的关键因素。为了满足用户查看完整运动数据的需求,运动类App都希望在设备后台保活,并通过传感器实时记录用户的运动数据。但大部分手机厂商为了节省电量,一旦应用处于后台就会被系统限制甚至强制关闭,导致最终呈现给用户的运动记录不完整。 运动类App要想实现端侧后台保活,目前通常有两种解决办法:
- 引导用户在手机上手动设置保活,如关闭电池优化,允许App后台运行。这种方法缺点在于操作步骤较复杂,用户学习成本较高。
- 可以通过集成华为运动健康服务来解决此问题,运动健康服务提供支持后台保活的运动记录API,集成该能力后应用能够在用户的锻炼过程中在华为手机后台保持运行,从而实现用户锻炼过程中的运动记录不间断。
那如何实现后台保活功能呢?以下是详细的集成步骤。
集成步骤
- 请参考开发准备完成申请Health Kit服务,勾选产品必需申请的数据权限并集成SDK。
- 调用后台保活功能需申请运动记录读取权限,再获取用户授权完成权限申请。
- 为保证您的应用不被系统冻结,需要开启一个前台服务Foreground services,在前台服务中调用ActivityRecordsController方法创建允许后台运行的运动记录;
- 调用ActivityRecordsController的beginActivityRecord接口开始允许后台运行的运动记录,默认会申请允许应用后台运行时长10分钟;
// 请注意此处的this为Activity对象
ActivityRecordsController activityRecordsController = HuaweiHiHealth.getActivityRecordsController(this);
// 1.构造新运动记录开始时间
long startTime = Calendar.getInstance().getTimeInMillis();
// 2.构造ActivityRecord对象,设置运动记录开始时间
ActivityRecord activityRecord = new ActivityRecord.Builder()
.setId("MyBeginActivityRecordId")
.setName("BeginActivityRecord")
.setDesc("This is ActivityRecord begin test!")
.setActivityTypeId(HiHealthActivities.RUNNING)
.setStartTime(startTime, TimeUnit.MILLISECONDS)
.build();
// 3.构建应用运动记录运行中展示的页面, MyActivity需替换成自身的Activity类
ComponentName componentName = new ComponentName(this, MyActivity.class);
// 4.构建运动记录后台运行状态变化监听器
OnActivityRecordListener activityRecordListener = new OnActivityRecordListener() {
@Override
public void onStatusChange(int statusCode) {
Log.i("ActivityRecords", "onStatusChange statusCode:" + statusCode);
}
};
// 5.调用启动新运动记录API接口beginActivityRecord
Task<Void> task1 = activityRecordsController.beginActivityRecord(activityRecord, componentName, activityRecordListener);
// 6.添加启动ActivityRecord成功
task1.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i("ActivityRecords", "MyActivityRecord begin success");
}
// 7.添加启动ActivityRecord失败
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
String errorCode = e.getMessage();
String errorMsg = HiHealthStatusCodes.getStatusCodeMessage(Integer.parseInt(errorCode));
Log.i("ActivityRecords", errorCode + ": " + errorMsg);
}
});
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 若用户运动时间较长,每临近10分钟(小于10分钟)需调用ActivityRecordsController的continueActivityRecord接口续申请后台保活10分钟;
// 请注意此处的this为Activity对象
ActivityRecordsController activityRecordsController = HuaweiHiHealth.getActivityRecordsController(this);
// 调用continueActivityRecord方法为指定运动记录续申请允许后台运行,入参为ActivityRecord的ID字符串
Task<Void> endTask = activityRecordsController.continueActivityRecord("MyBeginActivityRecordId");
endTask.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i("ActivityRecords", "continue backgroundActivityRecord was successful!");
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
Log.i("ActivityRecords", "continue backgroundActivityRecord error");
}
});
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 当用户运动结束时,调用ActivityRecordsController的endActivityRecord接口停止该运动记录,同时取消应用后台保活;
// 请注意此处的this为Activity对象
final ActivityRecordsController activityRecordsController = HuaweiHiHealth.getActivityRecordsController(this);
// 调用endActivityRecord接口停止运动记录,入参为ActivityRecord的ID字符串或者null
// 入参为ID字符串时,停止当前应用指定ID的运动记录
// 入参为null时,停止该应用当前所有的未停止运动记录
Task<List<ActivityRecord>> endTask = activityRecordsController.endActivityRecord("MyBeginActivityRecordId");
endTask.addOnSuccessListener(new OnSuccessListener<List<ActivityRecord>>() {
@Override
public void onSuccess(List<ActivityRecord> activityRecords) {
Log.i("ActivityRecords","MyActivityRecord End success");
// 返回停止成功的运动记录列表
if (activityRecords.size() > 0) {
for (ActivityRecord activityRecord : activityRecords) {
DateFormat dateFormat = DateFormat.getDateInstance();
DateFormat timeFormat = DateFormat.getTimeInstance();
Log.i("ActivityRecords", "Returned for ActivityRecord: " + activityRecord.getName() + "\n\tActivityRecord Identifier is "
+ activityRecord.getId() + "\n\tActivityRecord created by app is " + activityRecord.getPackageName()
+ "\n\tDescription: " + activityRecord.getDesc() + "\n\tStart: "
+ dateFormat.format(activityRecord.getStartTime(TimeUnit.MILLISECONDS)) + " "
+ timeFormat.format(activityRecord.getStartTime(TimeUnit.MILLISECONDS)) + "\n\tEnd: "
+ dateFormat.format(activityRecord.getEndTime(TimeUnit.MILLISECONDS)) + " "
+ timeFormat.format(activityRecord.getEndTime(TimeUnit.MILLISECONDS)) + "\n\tActivity:"
+ activityRecord.getActivityType());
}
} else {
// 没有停止成功返回null
Log.i("ActivityRecords","MyActivityRecord End response is null");
}
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
String errorCode = e.getMessage();
String errorMsg = HiHealthStatusCodes.getStatusCodeMessage(Integer.parseInt(errorCode));
Log.i("ActivityRecords",errorCode + ": " + errorMsg);
}
});
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
需要注意的是,由于端侧后台保活API属于敏感权限,运动类应用接入时需进行人工审核,确保数据安全、流程合规才能上架。
了解更多详情>>
获取 开发指导文档
华为移动服务开源仓库地址: GitHub
关注我们,第一时间了解 HMS Core 最新技术资讯~
边栏推荐
- MIPS assembly language learning-01-sum of two numbers, environment configuration and how to run
- CODING DevOps 助力中化信息打造新一代研效平台,驱动“线上中化”新未来
- Android和eclipse和MySQL上传图片并获取
- Technical secrets of ByteDance data platform: implementation and optimization of complex query based on Clickhouse
- NAACL 2022 | 机器翻译SOTA模型的蒸馏
- tablestore中可以使用sql查询可以查出表中所有的数据吗?
- go-zero 微服务实战系列(七、请求量这么高该如何优化)
- Application of mongodb in Tencent retail premium code
- 信创操作系统--麒麟Kylin桌面操作系统 (项目十 安全中心)
- Fleet |「后台探秘」第 3 期:状态管理
猜你喜欢

among us私服搭建

3. caller service call - dapr

看界面控件DevExpress WinForms如何创建一个虚拟键盘

The Web3.0 era is coming. See how Tianyi cloud storage resources invigorate the system to enable new infrastructure (Part 1)

What are the most powerful small and medium-sized companies in Beijing?

S2b2c system website solution for kitchen and bathroom electrical appliance industry: create s2b2c platform Omni channel commercial system

一种跳板机的实现思路

Flutter simply implements multilingual internationalization

CODING DevOps 助力中化信息打造新一代研效平台,驱动“线上中化”新未来

【高并发基础】MySQL 不同事务隔离级别下的并发隐患及解决方案
随机推荐
Lecturer solicitation order | Apache dolphin scheduler meetup sharing guests, looking forward to your topic and voice!
What useful supplier management systems are available
VS2013 帮助文档中没有 win32/com
【初学者必看】vlc实现的rtsp服务器及转储H264文件
A new 25K byte from the Department showed me what the ceiling is
Coding Devops helps Sinochem information to build a new generation of research efficiency platform and drive the new future of "online Sinochem"
Operating excel with openpyxl
【高并发基础】MySQL 不同事务隔离级别下的并发隐患及解决方案
Opengauss kernel: analysis of SQL parsing process
机器学习之深度学习简介
经典模型——Transformer
Realization of a springboard machine
Experiment 6 8255 parallel interface experiment [microcomputer principle] [experiment]
Qt 界面库
抖音实战~我关注的博主列表、关注、取关
In depth learning foundation summary
Talking about open source - Linus and Jim talk about open source in China
如何根据多元索引查询最后一条数据,达到 sql order by desc limit 1的效果呢?
[leetcode] 13. Roman numeral to integer
ROS knowledge points - ROS create workspace