Android: Как получить данные Google Fit с носимого устройства?

Я следую тем же шагам, описанным здесь (часть подключения клиента Google Fit работает нормально).

    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());
                    }
                }
            });

когда я прошу источники данных, я получаю только один результат, который является смартфоном. Если я добавляю слушателя, я действительно получаю данные, поэтому он работает.

однако он также подключен к Android Wear smartwatch Gear Live с приложением Android Wear на телефоне. Google Fit установлен в обоих из них, но я хотел бы получить данные из умные часы.

в официальном руководстве я прочитал

API датчиков обеспечивает доступ к сырцовым потокам данных датчика от доступные датчики на устройстве Android и с датчиков доступных в сопутствующие устройства, такие как носимые.

этот код работает на смартфоне, поэтому я думаю, что было бы правильно ожидать источников данных от companion smartwatch тоже. Но это как невидимый для моего приложения телефона. Я делаю что-то не так?

EDIT:

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: nt" + dataSource.toString() + "ntType: " + 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);
            }
        }
    }
};
}

1 ответов


Я не пробовал ничего из этого.

похоже, что датчики Samsung Gear Live не поддерживаются из коробки, но вы можете заставить его работать через датчики программного обеспечения:

Ваш Gear Live

как говорится в это так ответ,

Samsung Gear Live watch не рекламирует себя как BLE сердце монитор скорости и поэтому не делает сердце данные по тарифа доступно через обычный Bluetooth API низкой энергии или Google Fit API, который построен на нем.

Поддерживаемые Датчики

как говорится в официальные документы,

Google Fit включает в себя поддержку датчиков на мобильном устройстве и Bluetooth датчики низкой энергии в паре с устройством. Google Fit позволяет разработчики реализуют поддержку других датчиков и выставляют их как программное обеспечение датчики в Приложения для Android. Датчики, поддерживаемые Google Fit доступно для приложений Android в качестве объектов источника данных.

возможно решение

представляется возможным внедрение дополнительных программных датчиков.

(скопированный шаблон для этого находится в нижней части сообщения, потому что он длинный).

вы получите данные о носимом следующем get-heart-rate-from-sensor-samsung-gear-live.

шаблон (от https://developers.google.com/fit/android/new-sensors)

добавьте это в ваш файл манифеста:

<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>

и плоть этого Service out:

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
    }

}