【问题标题】:Android: How to get Google Fit data from Wearable device?Android:如何从可穿戴设备获取 Google Fit 数据?
【发布时间】:2015-09-10 09:53:26
【问题描述】:

我正在执行here 中描述的相同步骤(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 应用程序连接到 Android Wear 智能手表 Gear Live。两者都安装了 Google Fit,但我想从智能手表获取数据。

在我阅读的官方指南中

传感器 API 提供对原始传感器数据流的访问,来自 Android 设备上可用的传感器以及 配套设备,例如可穿戴设备

此代码在智能手机上运行,​​因此我认为期望来自配套智能手表的数据源也是正确的。但这对我的手机应用程序来说是不可见的。难道我做错了什么?

编辑:

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

【问题讨论】:

  • 您是否需要在手表端运行一些东西?当你说如果你添加一个监听器你会得到数据时,我也有点困惑。听起来您的程序正在运行?还是从手机而不是手表获取数据?能否请您澄清一下,以便我可以帮助您解决问题。
  • 是的,没错。我只能通过电话获取数据。我想获取连接到 Google Fit、智能手机和智能手表的传感器列表。该指南说它也显示了配套设备。如果我在手表上输入相同的代码,我会得到它的传感器列表,而手机上什么也没有。
  • 我正在阅读类似的问题,但至少他可以从配套设备中看到其他传感器。 stackoverflow.com/questions/26822432/…
  • 请问您可以发布您的活动来源吗?
  • 是的,我已经对上述问题进行了修改

标签: android wear-os android-sensors google-fit google-fit-sdk


【解决方案1】:

我没有尝试过。

三星 Gear Live 传感器似乎不支持开箱即用,但您可以通过 software sensors 使其工作:

你的装备直播

this SO answer中所说,

Samsung Gear Live 手表不会将自己宣传为BLE heart rate monitor,因此不会生成心率数据 可通过普通的Bluetooth Low Energy API 或 Google Fit API 是基于它构建的。

支持的传感器

the official docs中所说,

Google Fit 支持移动设备上的传感器和 与设备配对的低功耗蓝牙传感器。谷歌健身让 开发人员实现对其他传感器的支持并将它们公开为 Android 应用程序中的软件传感器。 Google Fit 支持的传感器有 可作为数据源对象供 Android 应用使用。

可能的解决方案

好像可以implement additional software sensors

(复制的模板在帖子底部,因为它很长)。

您将在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 充实起来:

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
    }

}

【讨论】:

  • 如果考虑框架所承诺的内容,工作量很大。这可能是一个解决方案...谢谢
  • 不客气。这看起来像是一个特殊情况,因为 Gear Live 没有实现蓝牙低功耗。
  • 可能。在 stackoverflow.com/6864712/android-alarmmanager-not-waking-phone-up 中说它工作的人是 @ianhanniballake,他“全职在 Google 担任 Android 开发倡导者” .这使得它三个(你,另一个 OP 和 @ian...)对抗一个。
  • ...支持不受支持的设备的库可能会对社区有所帮助...(提示 ;-))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多