你在锻炼健身时,有没有遇到这样的情况?辛辛苦苦锻炼了几小时,却发现App停止了运行,本次运动并没有被记录到App上,从而失去了一个查看完整运动数据的机会?

运动类App是通过手机或者穿戴设备的传感器,来识别运动状态并反馈给用户的,App能否在手机后台时刻保持运行是影响运动数据完整性的关键因素。为了满足用户查看完整运动数据的需求,运动类App都希望在设备后台保活,并通过传感器实时记录用户的运动数据。但大部分手机厂商为了节省电量,一旦应用处于后台就会被系统限制甚至强制关闭,导致最终呈现给用户的运动记录不完整。

运动类App要想实现端侧后台保活,目前通常有两种解决办法:

  1. 引导用户在手机上手动设置保活,如关闭电池优化,允许App后台运行。这种方法缺点在于操作步骤较复杂,用户学习成本较高。

  2. 可以通过集成华为运动健康服务来解决此问题,运动健康服务提供支持后台保活的运动记录API,集成该能力后应用能够在用户的锻炼过程中在华为手机后台保持运行,从而实现用户锻炼过程中的运动记录不间断。

那如何实现后台保活功能呢?以下是详细的集成步骤。

集成步骤

  1. 请参考开发准备完成申请Health Kit服务,勾选产品必需申请的数据权限并集成SDK。

  2. 调用后台保活功能需申请运动记录读取权限,再获取用户授权完成权限申请。

  3. 为保证您的应用不被系统冻结,需要开启一个前台服务Foreground services,在前台服务中调用ActivityRecordsController方法创建允许后台运行的运动记录;

  4. 调用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. 若用户运动时间较长,每临近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. 当用户运动结束时,调用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属于敏感权限,运动类应用接入时需进行人工审核,确保数据安全、流程合规才能上架。

获取端侧后台保活能力开发文档

华为运动健康场景解决方案

了解更多详情>>

访问华为开发者联盟官网

获取开发指导文档

华为移动服务开源仓库地址:GitHubGitee

关注我们,第一时间了解 HMS Core 最新技术资讯~

运动App如何实现端侧后台保活,让运动记录更完整?的更多相关文章

  1. 美图App的移动端DNS优化实践:HTTPS请求耗时减小近半

    本文引用了颜向群发表于高可用架构公众号上的文章<聊聊HTTPS环境DNS优化:美图App请求耗时节约近半案例>的部分内容,感谢原作者. 1.引言 移动互联网时代,APP 厂商之间的竞争非常 ...

  2. 网站的优化----首页优化---app调取服务端数据

    高并发经常会发生在有大活跃用户量来访问网站的某个点,例如用户高聚集的业务场景中,如:抢购,促销等.为了让用户流畅的访问网站,来根据自己的业务设计适合系统的处理方案. //对于APP网站首页数据,通常是 ...

  3. 记一次爬虫经历(友话APP的Web端)

    背景:学校为迎接新生举办了一个活动,在友话APP的校园圈子内发布动态即可参与活动,最终抽取数名同学赠送福利. 分析:动态的数量会随着迎新的开始逐渐增加,人工统计显然不现实,因此可以使用爬虫脚本在友话A ...

  4. 无框架完整搭建安卓app及其服务端(一)

    技术背景: 我的一个项目做的的是图片处理,用 python 实现图片处理的核心功能后,想部署到安卓app中,但是对于一个对安卓和服务器都一知半解的小白来说要现学的东西太多了. 而实际上,我们的项目要求 ...

  5. PC/APP/H5三端测试的相同与不同

    随着手机应用的不断状态,同一款产品的移动端应用市场占相较PC端也越来越大,那么app与PC端针对这些产品的测试有什么相同与不同之处呢?总结如下: 首先谈一谈相同之处: 一,针对同一个系统功能的测试,三 ...

  6. H5 APP 页面移动端适配方案

    H5 APP 页面移动端适配方案 https://segmentfault.com/a/1190000011586301 https://juejin.im/post/5cbdee71f265da03 ...

  7. 原生JavaScript运动功能系列(五):定时定点运动

    原生JavaScript运动功能系列(一):运动功能剖析与匀速运动实现 原生JavaScript运动功能系列(二):缓冲运动 原生JavaScript运动功能系列(三):多物体多值运动 原生JavaS ...

  8. APP和服务端-架构设计(一)

    架构因人而异,不同的架构师大多会有不同的看法:架构也因项目而异,不同的项目需求不同,相应的架构也会不同.然而,有些东西还是通用的,是所有架构师都需要考虑的,也是所有项目都会有的需求,比如API如何设计 ...

  9. 微信app支付(android端+java后台)

    本文讲解使用微信支付接口完成在android开发的原生态app中完成微信支付功能, 文章具体讲解了前端android如何集成微信支付功能以及后台如何组装前端需要支付信息, 话不多话, 具体看文章内容吧 ...

  10. 支付宝app支付服务端流程

    支付宝APP支付服务端详解 前面接了微信支付,相比微信支付,支付宝APP支付提供了支付封装类,下面将实现支付宝APP支付.订单查询.支付结果异步通知.APP支付申请参数说明,以及服务端返回APP端发起 ...

随机推荐

  1. 03、Etcd 客户端常用命令

    上一讲我们安装 etcd 服务端,这一讲我们来一起学学如何使用 etcd 客户端常见的命令.文章内容来源于参考资料,如若侵权,请联系删除,谢谢. etcd可通过客户端命令行工具 etcdctl 对et ...

  2. 【Azure 应用服务】PHP项目部署到App Service for Linux环境中,如何修改上传文件大小的限制呢?

    问题描述 PHP项目部署到App Service for Linux环境中,如何修改上传文件大小的限制呢? 问题解答 经过查询Azure App Service官方文档,可能通过在项目根目录下添加.h ...

  3. 如何当个优秀的文档工程师?从 TC China 看技术文档工程师的自我修养

    本文系 NebulaGraph Community Academic 技术文档工程师 Abby 的参会观感,讲述了她在中国技术传播大会分享的收获以及感悟. 据说,技术内容领域.传播领域的专家和决策者们 ...

  4. 黑马python基础课的一些题

    1, 打印5行小星星 思路: 可以用1个星星乘以行数:还可以循环嵌套,外层循环控制行数,内层循环控制每一行应该输出多少个小星星,比如,第一行输出1个,第二行输出2个,内层循环可以当成列,只不过这个列要 ...

  5. [Python] 协程学习过程

    开始 ​ 之前一直在做那个rProxy的项目,后来发现,服务端不用协程或者异步编程这样的手段是不行的,最主要的问题就是对于每个http请求都对应一个线程,这个开销非常大.对于一个网页而言,四五十个ht ...

  6. Redis项目常见解决方案

    ## 1. 缓存预热 在项目启动,或者服务器重启后, 因为请求量较大, 此时对关系型数据库的访问量就有可能超标,导致服务卡顿,宕机, 所以在启动前应该对缓存进行预热: 前置准备工作: 日常例行统计数据 ...

  7. c语言四则运算小程序

    本文源程序代码来源于csdn一位博主: 文章链接:http://t.csdnimg.cn/L29fs 原程序简洁凝练,以简短的代码写出了一个加法运算器. 以下是运行结果(本文全程用visual stu ...

  8. C 语言字符串操作总结

    C 语言字符串操作总结 一.字符串操作 size_t 是一个无符号整型. 1.1 strcpy 函数原型:char *strcpy(char *dest, const char *src). 功 能: ...

  9. nowrap - table td 列 宽度 不被挤 - 大表格制作

    nowrap - table td 列 宽度 不被挤 - 大表格制作 表格前几列 设置完宽度,会被右侧动态数据挤没有宽度,加上nowrap,就保证宽度了

  10. 基于R语言的raster包读取遥感影像

      本文介绍基于R语言中的raster包,读取单张或批量读取多张栅格图像,并对栅格图像数据加以基本处理的方法. 1 包的安装与导入   首先,我们需要配置好对应的R语言包:前面也提到,我们这里选择基于 ...