你在鍛煉健身時,有沒有遇到這樣的情況?辛辛苦苦鍛煉了幾小時,卻發現App停止了運行,本次運動並沒有被記錄到App上,從而失去了一個查看完整運動數據的機會? 運動類App是通過手機或者穿戴設備的感測器,來識別運動狀態並反饋給用戶的,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 最新技術資訊~