运动App如何实现端侧后台保活,让运动记录更完整?
你在锻炼健身时,有没有遇到这样的情况?辛辛苦苦锻炼了几小时,却发现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);
}
});
- 若用户运动时间较长,每临近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");
}
});
- 当用户运动结束时,调用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);
}
});
需要注意的是,由于端侧后台保活API属于敏感权限,运动类应用接入时需进行人工审核,确保数据安全、流程合规才能上架。
了解更多详情>>
访问华为开发者联盟官网
获取开发指导文档
华为移动服务开源仓库地址:GitHub、Gitee
关注我们,第一时间了解 HMS Core 最新技术资讯~
运动App如何实现端侧后台保活,让运动记录更完整?的更多相关文章
- 美图App的移动端DNS优化实践:HTTPS请求耗时减小近半
本文引用了颜向群发表于高可用架构公众号上的文章<聊聊HTTPS环境DNS优化:美图App请求耗时节约近半案例>的部分内容,感谢原作者. 1.引言 移动互联网时代,APP 厂商之间的竞争非常 ...
- 网站的优化----首页优化---app调取服务端数据
高并发经常会发生在有大活跃用户量来访问网站的某个点,例如用户高聚集的业务场景中,如:抢购,促销等.为了让用户流畅的访问网站,来根据自己的业务设计适合系统的处理方案. //对于APP网站首页数据,通常是 ...
- 记一次爬虫经历(友话APP的Web端)
背景:学校为迎接新生举办了一个活动,在友话APP的校园圈子内发布动态即可参与活动,最终抽取数名同学赠送福利. 分析:动态的数量会随着迎新的开始逐渐增加,人工统计显然不现实,因此可以使用爬虫脚本在友话A ...
- 无框架完整搭建安卓app及其服务端(一)
技术背景: 我的一个项目做的的是图片处理,用 python 实现图片处理的核心功能后,想部署到安卓app中,但是对于一个对安卓和服务器都一知半解的小白来说要现学的东西太多了. 而实际上,我们的项目要求 ...
- PC/APP/H5三端测试的相同与不同
随着手机应用的不断状态,同一款产品的移动端应用市场占相较PC端也越来越大,那么app与PC端针对这些产品的测试有什么相同与不同之处呢?总结如下: 首先谈一谈相同之处: 一,针对同一个系统功能的测试,三 ...
- H5 APP 页面移动端适配方案
H5 APP 页面移动端适配方案 https://segmentfault.com/a/1190000011586301 https://juejin.im/post/5cbdee71f265da03 ...
- 原生JavaScript运动功能系列(五):定时定点运动
原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现 原生JavaScript运动功能系列(二):缓冲运动 原生JavaScript运动功能系列(三):多物体多值运动 原生JavaS ...
- APP和服务端-架构设计(一)
架构因人而异,不同的架构师大多会有不同的看法:架构也因项目而异,不同的项目需求不同,相应的架构也会不同.然而,有些东西还是通用的,是所有架构师都需要考虑的,也是所有项目都会有的需求,比如API如何设计 ...
- 微信app支付(android端+java后台)
本文讲解使用微信支付接口完成在android开发的原生态app中完成微信支付功能, 文章具体讲解了前端android如何集成微信支付功能以及后台如何组装前端需要支付信息, 话不多话, 具体看文章内容吧 ...
- 支付宝app支付服务端流程
支付宝APP支付服务端详解 前面接了微信支付,相比微信支付,支付宝APP支付提供了支付封装类,下面将实现支付宝APP支付.订单查询.支付结果异步通知.APP支付申请参数说明,以及服务端返回APP端发起 ...
随机推荐
- github.com/mitchellh/mapstructure 教程
官网链接: github.com/mitchellh/mapstructure 本文只是简单的记录下 mapstructure 库的简单使用,想更加详细的学习,点击 Godoc 学习吧. 文中内容基本 ...
- [杂项] 抢单可能需要的API
淘宝时间戳 http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp 京东库存查询 http://c0.3.cn/stock? ...
- 为什么(++a)+(++a)=14
目录 概述 验证 反编译大法 Java 测试 概述 今天有学妹问我,下面这个代码为啥结果是14 int a=5; printf("%d\n",(++a)+(++a)); 我一看,第 ...
- mysql-对应删除 dict 脚本
-- 1. 此 dict 是在不同租户下的数据字典,查询时需要根据 departid 进行分类查询 -- 2. 删除dict, dict分类主表类型与挂载的子表数据 -- 3. 通过查询到的主表的 g ...
- 适用于AbpBoilerplate的阿里云腾讯云Sms短信服务
Sms 适用于AbpBoilerplate的短信服务(Short Message Service,SMS)模块,通过简单配置即可使用,仅更改一处代码即可切换短信服务提供商. Aliyun.Sms由阿里 ...
- linux文件管理(补充)
linux文件管理 vim编辑器 vi概述 vi 编辑器 他是linux和unix系统上最基本的文本编辑器,类似于windows系统下的记事本编辑器 vim编辑器 vim是vi的加强版,比vi更容易使 ...
- C++学习笔记之基础语法
目录 基础语法 switch和if区别 枚举定义及作用域 结构体数据耐齐--缺省对齐原则 函数重载overload与C++Name Mangling 指向函数的指针与返回指针的函数 基础语法 swit ...
- pod的拉取和重启策略
在Kubernetes中,Pod的拉取策略和重启策略可以通过YAML配置文件来定义. Pod的拉取策略 Pod的拉取策略指的是Kubernetes在创建或重启Pod时,如何获取Pod所需的容器镜像.这 ...
- Windows10 Linux 子系统的骚操作之 Ctrl+Alt+T shell启动终端
巨硬的 WSL(Windows Subsystem for Linux)是真的好用 但是,由于本人比较喜欢按快捷键.所以一直想着找到Windows上安装的ubuntu.exe文件,搞个快捷方式,然后再 ...
- -Dmaven.multiModuleProjectDirectory system propery is not set解决方案
myeclipse中使用maven插件的时候,运行run as maven build的时候报错 -Dmaven.multiModuleProjectDirectory system propery ...