pasos - Android: ¿Cómo obtener los datos de Google Fit desde un dispositivo portátil?
google fit no cuenta kilometros (1)
Estoy siguiendo los mismos pasos que se describen here (la parte de conexión del cliente de Google Fit está funcionando bien).
final DataType dataType=TYPE_STEP_COUNT_DELTA;
DataSourcesRequest requestData = new DataSourcesRequest.Builder()
.setDataTypes(dataType) // At least one datatype must be specified.
.build();
Fitness.SensorsApi.findDataSources(mClient, requestData)
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " + dataSourcesResult.getDataSources().size() + " sources "
+ dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "Data source found: " + dataSource.toString());
Log.i(TAG, "Data Source type: " + dataSource.getDataType().getName());
}
}
});
Cuando solicito fuentes de datos, solo obtengo un resultado: el teléfono inteligente. Si agrego un oyente, realmente obtengo datos, así que está funcionando.
Sin embargo, también está conectado a un dispositivo SmartWatch Gear Live de Android con la aplicación Android Wear en el teléfono. Google Fit está instalado en ambos, pero me gustaría obtener datos del reloj inteligente.
En la guía oficial leo
La API de Sensores proporciona acceso a flujos de datos de sensores sin procesar de sensores disponibles en el dispositivo Android y de sensores disponibles en dispositivos complementarios, como dispositivos portátiles .
Este código se está ejecutando en el teléfono inteligente, así que creo que sería correcto esperar también las fuentes de datos del reloj inteligente complementario. Pero es como invisible para mi aplicación de teléfono. ¿Estoy haciendo algo mal?
EDITAR:
public class MainActivity extends AppCompatActivity {
private final static String TAG = "main_mobile";
private static final int REQUEST_OAUTH = 1;
private final static String DATE_FORMAT = "yyyy.MM.dd HH:mm:ss";
private static final String AUTH_PENDING = "auth_state_pending";
private boolean authInProgress = false;
private GoogleApiClient mClient = null;
private final static DataType dataType = TYPE_STEP_COUNT_DELTA;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
authInProgress = savedInstanceState.getBoolean(AUTH_PENDING);
}
mClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.SENSORS_API)
.addApi(Fitness.RECORDING_API)
.addApi(Fitness.HISTORY_API)
.addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
.addConnectionCallbacks(connectionCallbacks)
.addOnConnectionFailedListener(connectionFailCallbacks)
.build();
}
private void initFitness() {
DataSourcesRequest requestData = new DataSourcesRequest.Builder()
.setDataTypes(dataType)
.build();
Fitness.SensorsApi.findDataSources(mClient, requestData)
.setResultCallback(new ResultCallback<DataSourcesResult>() {
@Override
public void onResult(DataSourcesResult dataSourcesResult) {
Log.i(TAG, "Result: " + dataSourcesResult.getDataSources().size() + " sources " + dataSourcesResult.getStatus().toString());
for (DataSource dataSource : dataSourcesResult.getDataSources()) {
Log.i(TAG, "/nData source found: /n/t" + dataSource.toString() + "/n/tType: " + dataSource.getDataType().getName());
}
}
});
}
@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "Connecting...");
mClient.connect();
}
@Override
protected void onStop() {
super.onStop();
if (mClient.isConnected()) {
mClient.disconnect();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_OAUTH) {
authInProgress = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mClient.isConnecting() && !mClient.isConnected()) {
mClient.connect();
}
}
}
}
GoogleApiClient.ConnectionCallbacks connectionCallbacks = new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
initFitness();
}
@Override
public void onConnectionSuspended(int i) {
// If your connection to the sensor gets lost at some point,
// you''ll be able to determine the reason and react to it here.
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
};
GoogleApiClient.OnConnectionFailedListener connectionFailCallbacks = new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
@Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), MainActivity.this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization dialog is displayed to the user.
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(MainActivity.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
}
};
}
No he probado nada de esto.
Parece que los sensores Samsung Gear Live no son compatibles de fábrica, pero es posible que pueda funcionar a través de sensores de software :
Su equipo en vivo
Como se dijo en esta respuesta ,
El reloj Samsung Gear Live no se anuncia a sí mismo como un monitor de frecuencia cardíaca BLE y, por lo tanto, no hace que los datos de frecuencia cardíaca estén disponibles a través de la API normal de bajo consumo de Bluetooth o la API de Google Fit, que se basa en ellos.
Sensores soportados
Como se dice en los documentos oficiales ,
Google Fit incluye soporte para sensores en el dispositivo móvil y sensores de baja energía Bluetooth emparejados con el dispositivo. Google Fit permite a los desarrolladores implementar el soporte para otros sensores y exponerlos como sensores de software en aplicaciones de Android. Los sensores compatibles con Google Fit están disponibles para las aplicaciones de Android como objetos de origen de datos.
Posible solución
Parece posible implementar sensores de software adicionales .
(La plantilla copiada para esto está en la parte inferior de la publicación, porque es larga).
Obtendría los datos en el wearable que sigue a get-heart-rate-from-sensor-samsung-gear-live .
Plantilla (de https://developers.google.com/fit/android/new-sensors )
Agregue esto a su archivo de manifiesto:
<service android:name="com.example.MySensorService" android:process=":sensor"> <intent-filter> <action android:name="com.google.android.gms.fitness.service.FitnessSensorService"/> <!-- include at least one mimeType filter for the supported data types --> <data android:mimeType="vnd.google.fitness.data_type/com.google.heart_rate.bpm"/> </intent-filter> </service>
y hacer realidad este Service
:
import com.google.android.gms.common.*; import com.google.android.gms.common.api.*; import com.google.android.gms.fitness.*; import com.google.android.gms.fitness.data.*; import com.google.android.gms.fitness.service.*; ... public class MySensorService extends FitnessSensorService { @Override public void onCreate() { super.onCreate(); // 1. Initialize your software sensor(s). // 2. Create DataSource representations of your software sensor(s). // 3. Initialize some data structure to keep track of a registration for each sensor. } @Override protected List<DataSource> onFindDataSources(List<DataType> dataTypes) { // 1. Find which of your software sensors provide the data types requested. // 2. Return those as a list of DataSource objects. } @Override protected boolean onRegister(FitnessSensorServiceRequest request) { // 1. Determine which sensor to register with request.getDataSource(). // 2. If a registration for this sensor already exists, replace it with this one. // 3. Keep (or update) a reference to the request object. // 4. Configure your sensor according to the request parameters. // 5. When the sensor has new data, deliver it to the platform by calling // request.getDispatcher().publish(List<DataPoint> dataPoints) } @Override protected boolean onUnregister(DataSource dataSource) { // 1. Configure this sensor to stop delivering data to the platform // 2. Discard the reference to the registration request object } }