我想做的是开发一个应用程序,该应用程序读取Samsung手表收集的健康数据,因此我尝试使用Samsung android health SDK。而且,阅读步骤非常容易,因为有一个示例应用程序在做同样的事情。当我尝试读取心率值时出现该问题:
这是我的代码,请帮助我解决该问题:
维护:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smaunghealth">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.step_count;com.samsung.health.heart_rate"/>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivity
package com.example.smaunghealth;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.samsung.android.sdk.healthdata.*;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class MainActivity extends AppCompatActivity {
public static final String APP_TAG = "SimpleHealth";
private static MainActivity mInstance = null;
private HealthDataStore mStore;
private HealthConnectionErrorResult mConnError;
private Set<HealthPermissionManager.PermissionKey> mKeySet;
private StepCountReporter mReporter;
private HeartRateReporter mHeartReporter;
TextView stepCount ;
TextView heartRate ;
private final HealthResultHolder.ResultListener<HealthPermissionManager.PermissionResult> mPermissionListener =
new HealthResultHolder.ResultListener<HealthPermissionManager.PermissionResult>() {
@Override
public void onResult(HealthPermissionManager.PermissionResult result) {
Log.d(APP_TAG, "Permission callback is received.");
Map<HealthPermissionManager.PermissionKey, Boolean> resultMap = result.getResultMap();
if (resultMap.containsValue(Boolean.FALSE)) {
// Requesting permission fails
} else {
// Get the current step count and display it
}
}
};
private final HealthDataStore.ConnectionListener mConnectionListener = new HealthDataStore.ConnectionListener() {
@Override
public void onConnected() {
Log.d(APP_TAG, "Health data service is connected.");
HealthPermissionManager pmsManager = new HealthPermissionManager(mStore);
try {
// Check whether the permissions that this application needs are acquired
Map<HealthPermissionManager.PermissionKey, Boolean> resultMap = pmsManager.isPermissionAcquired(mKeySet);
if (resultMap.containsValue(Boolean.FALSE)) {
// Request the permission for reading step counts if it is not acquired
pmsManager.requestPermissions(mKeySet, MainActivity.this).setResultListener(mPermissionListener);
} else {
// Get the current step count and display it
// ...
mReporter = new StepCountReporter(mStore);
mReporter.start(mStepCountObserver);
mHeartReporter = new HeartRateReporter(mStore);
mHeartReporter.start(heartRateObserver);
}
} catch (Exception e) {
Log.e(APP_TAG, e.getClass().getName() + " - " + e.getMessage());
Log.e(APP_TAG, "Permission setting fails.");
}
}
@Override
public void onConnectionFailed(HealthConnectionErrorResult error) {
Log.d(APP_TAG, "Health data service is not available.");
showConnectionFailureDialog(error);
}
@Override
public void onDisconnected() {
Log.d(APP_TAG, "Health data service is disconnected.");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInstance = this;
stepCount= (TextView) findViewById(R.id.step_count);
heartRate= (TextView) findViewById(R.id.heart_rate);
mKeySet = new HashSet<HealthPermissionManager.PermissionKey>();
// mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEART_RATE, HealthPermissionManager.PermissionType.READ));
HealthDataService healthDataService = new HealthDataService();
try {
healthDataService.initialize(this);
} catch (Exception e) {
e.printStackTrace();}
mStore = new HealthDataStore(this, mConnectionListener);
// Request the connection to the health data store
mStore.connectService();
}
@Override
public void onDestroy() {
mStore.disconnectService();
super.onDestroy();
}
private StepCountReporter.StepCountObserver mStepCountObserver = count -> {
Log.d(APP_TAG, "Step reported : " + count);
updateStepCountView(String.valueOf(count));
};
private HeartRateReporter.HeartRateObserver heartRateObserver = count -> {
Log.d(APP_TAG, "Step reported : " + count);
updateHeartRateView(String.valueOf(count));
};
private void updateHeartRateView(String valueOf) {
Log.d(APP_TAG, "heart rate reported : " + valueOf);
updateHeartRateView(String.valueOf(valueOf));
}
private void updateStepCountView(String count) {
stepCount.setText(count);
}
private void showConnectionFailureDialog(HealthConnectionErrorResult error) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
mConnError = error;
String message = "Connection with Samsung Health is not available";
if (mConnError.hasResolution()) {
switch(error.getErrorCode()) {
case HealthConnectionErrorResult.PLATFORM_NOT_INSTALLED:
message = "Please install Samsung Health";
break;
case HealthConnectionErrorResult.OLD_VERSION_PLATFORM:
message = "Please upgrade Samsung Health";
break;
case HealthConnectionErrorResult.PLATFORM_DISABLED:
message = "Please enable Samsung Health";
break;
case HealthConnectionErrorResult.USER_AGREEMENT_NEEDED:
message = "Please agree with Samsung Health policy";
break;
default:
message = "Please make Samsung Health available";
break;
}
}
alert.setMessage(message);
alert.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
if (mConnError.hasResolution()) {
mConnError.resolve(mInstance);
}
}
});
if (error.hasResolution()) {
alert.setNegativeButton("Cancel", null);
}
alert.show();
}
}
HeartRateReporter
package com.example.smaunghealth;
import android.util.Log;
import com.samsung.android.sdk.healthdata.*;
import java.util.Calendar;
import java.util.TimeZone;
public class HeartRateReporter {
private final HealthDataStore mStore;
private HeartRateObserver mHeartRateObserver;
private static final long ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000L;
public HeartRateReporter(HealthDataStore store) {
mStore = store;
}
public void start(HeartRateObserver listener) {
mHeartRateObserver = listener;
HealthDataObserver.addObserver(mStore, HealthConstants.HeartRate.HEART_RATE, mObserver);
readHeartRate();
}
private void readHeartRate() {
HealthDataResolver resolver = new HealthDataResolver(mStore, null);
// Set time range from start time of today to the current time
long startTime = getStartTimeOfToday();
long endTime = startTime + ONE_DAY_IN_MILLIS;
HealthDataResolver.ReadRequest request = new HealthDataResolver.ReadRequest.Builder()
.setDataType(HealthConstants.HeartRate.HEART_RATE)
.setProperties(new String[] {HealthConstants.HeartRate.HEART_RATE})
.setLocalTimeRange(HealthConstants.HeartRate.START_TIME, HealthConstants.HeartRate.TIME_OFFSET,
startTime, endTime)
.build();
try {
resolver.read(request).setResultListener(mListener);
} catch (Exception e) {
Log.e("*&*&*&", "Getting Heart fails.", e);
}
}
private long getStartTimeOfToday() {
Calendar today = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
return today.getTimeInMillis();
}
private final HealthResultHolder.ResultListener<HealthDataResolver.ReadResult> mListener = result -> {
int count = 0;
try {
for (HealthData data : result) {
count += data.getInt(HealthConstants.HeartRate.HEART_RATE);
}
} finally {
result.close();
}
if (mHeartRateObserver != null) {
mHeartRateObserver.onChanged(count);
}
};
private final HealthDataObserver mObserver = new HealthDataObserver(null) {
@Override
public void onChange(String dataTypeName) {
Log.d("*&*&*&", "Observer receives a data changed event");
readHeartRate();
}
};
public interface HeartRateObserver {
void onChanged(int count);
}
}
StepCountReporter
/**
* Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
*
* Mobile Communication Division,
* Digital Media & Communications Business, Samsung Electronics Co., Ltd.
*
* This software and its documentation are confidential and proprietary
* information of Samsung Electronics Co., Ltd. No part of the software and
* documents may be copied, reproduced, transmitted, translated, or reduced to
* any electronic medium or machine-readable form without the prior written
* consent of Samsung Electronics.
*
* Samsung Electronics makes no representations with respect to the contents,
* and assumes no responsibility for any errors that might appear in the
* software and documents. This publication and the contents hereof are subject
* to change without notice.
*/
package com.example.smaunghealth;
import android.util.Log;
import com.samsung.android.sdk.healthdata.*;
import com.samsung.android.sdk.healthdata.HealthDataResolver.ReadRequest;
import com.samsung.android.sdk.healthdata.HealthDataResolver.ReadResult;
import java.util.Calendar;
import java.util.TimeZone;
public class StepCountReporter {
private final HealthDataStore mStore;
private StepCountObserver mStepCountObserver;
private static final long ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1000L;
public StepCountReporter(HealthDataStore store) {
mStore = store;
}
public void start(StepCountObserver listener) {
mStepCountObserver = listener;
// Register an observer to listen changes of step count and get today step count
HealthDataObserver.addObserver(mStore, HealthConstants.StepCount.HEALTH_DATA_TYPE, mObserver);
readTodayStepCount();
}
// Read the today's step count on demand
private void readTodayStepCount() {
HealthDataResolver resolver = new HealthDataResolver(mStore, null);
// Set time range from start time of today to the current time
long startTime = getStartTimeOfToday();
long endTime = startTime + ONE_DAY_IN_MILLIS;
HealthDataResolver.ReadRequest request = new ReadRequest.Builder()
.setDataType(HealthConstants.StepCount.HEALTH_DATA_TYPE)
.setProperties(new String[] {HealthConstants.StepCount.COUNT})
.setLocalTimeRange(HealthConstants.StepCount.START_TIME, HealthConstants.StepCount.TIME_OFFSET,
startTime, endTime)
.build();
try {
resolver.read(request).setResultListener(mListener);
} catch (Exception e) {
Log.e(MainActivity.APP_TAG, "Getting step count fails.", e);
}
}
private long getStartTimeOfToday() {
Calendar today = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
return today.getTimeInMillis();
}
private final HealthResultHolder.ResultListener<ReadResult> mListener = result -> {
int count = 0;
try {
for (HealthData data : result) {
count += data.getInt(HealthConstants.StepCount.COUNT);
}
} finally {
result.close();
}
if (mStepCountObserver != null) {
mStepCountObserver.onChanged(count);
}
};
private final HealthDataObserver mObserver = new HealthDataObserver(null) {
// Update the step count when a change event is received
@Override
public void onChange(String dataTypeName) {
Log.d(MainActivity.APP_TAG, "Observer receives a data changed event");
readTodayStepCount();
}
};
public interface StepCountObserver {
void onChanged(int count);
}
}
这是异常日志:
答案 0 :(得分:0)
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.step_count;com.samsung.health.heart_rate"/>
我认为您应该将此许可分为两个,而不是一个。
喜欢:
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.step_count"/>
<meta-data android:name="com.samsung.android.health.permission.read"
android:value="com.samsung.health.heart_rate"/>
答案 1 :(得分:0)
经过很长一段时间终于可以解决这个问题了:
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEART_RATE, HealthPermissionManager.PermissionType.READ));
这是写入权限密钥:
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));
mKeySet.add(new HealthPermissionManager.PermissionKey(HealthConstants.HeartRate.HEALTH_DATA_TYPE, HealthPermissionManager.PermissionType.READ));