2017-02-15 80 views
2

我正在编写一个Android应用程序,该应用程序使用Google Fit API连接到蓝牙腕带,目的是从传感器收集心率信息。下面是我使用的功能:Google Fit API未接收蓝牙腕带数据(SWR12)

在应用程序中的主要活动:建立API

protected void onResume() { 
     super.onResume(); 
// This ensures that if the user denies the permissions then uses Settings to re-enable 
     // them, the app will start working. 
     buildFitnessClient(); 

     // now find the bluetooth devices 
     buildBLE(); 

     // Connect to the Client 
     mClient.connect(); 

     // Search for the data sources 
     findFitnessDataSources(); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
if (!checkPermissions()) { 
      requestPermissions(); 
     } 

     if (!checkPermissionsBody()) { 
      requestPermissionsBody(); 

许可请求的功能:

// Now we need a function to check permissions 
    private boolean checkPermissions() { 
     int permissionState = ActivityCompat.checkSelfPermission(this, 
       Manifest.permission.ACCESS_FINE_LOCATION); 
     return permissionState == PackageManager.PERMISSION_GRANTED; 
    } 

    // Now we need a function to check permissions body sensors 
    private boolean checkPermissionsBody() { 
     int permissionState = ActivityCompat.checkSelfPermission(this, 
       Manifest.permission.BODY_SENSORS); 
     return permissionState == PackageManager.PERMISSION_GRANTED; 
    } 


    // If permissions are not given, we need to request permissions 
    private void requestPermissions() { 
     Log.d(TAG,"getting permissions"); 
     boolean shouldProvideRationale = 
       ActivityCompat.shouldShowRequestPermissionRationale(this, 
         Manifest.permission.ACCESS_FINE_LOCATION); 
     Log.d(TAG,String.valueOf(Manifest.permission.ACCESS_FINE_LOCATION)); 
     // Provide an additional rationale to the user. This would happen if the user denied the 
     // request previously, but didn't check the "Don't ask again" checkbox. 
     if (shouldProvideRationale) { 
      Log.i(TAG, "Displaying permission rationale to provide additional context."); 
      Snackbar.make(
        findViewById(R.id.activity_main), 
        R.string.permission_rationale, 
        Snackbar.LENGTH_INDEFINITE) 
        .setAction(R.string.ok, new View.OnClickListener() { 
         @Override 
         public void onClick(View view) { 
          // Request permission 
          ActivityCompat.requestPermissions(MainActivity.this, 
            new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
            REQUEST_PERMISSIONS_REQUEST_CODE); 
         } 
        }) 
        .show(); 
     } else { 
      Log.i(TAG, "Requesting permission"); 
      // Request permission. It's possible this can be auto answered if device policy 
      // sets the permission in a given state or the user denied the permission 
      // previously and checked "Never ask again". 
      ActivityCompat.requestPermissions(MainActivity.this, 
        new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 
        REQUEST_PERMISSIONS_REQUEST_CODE); 
     } 
    } 

    // If permissions are not given, we need to request permissions 
    private void requestPermissionsBody() { 
     Log.d(TAG,"getting permissions"); 
     boolean shouldProvideRationale = 
       ActivityCompat.shouldShowRequestPermissionRationale(this, 
         Manifest.permission.BODY_SENSORS); 
     Log.d(TAG,String.valueOf(Manifest.permission.BODY_SENSORS)); 
     // Provide an additional rationale to the user. This would happen if the user denied the 
     // request previously, but didn't check the "Don't ask again" checkbox. 
     if (shouldProvideRationale) { 
      Log.i(TAG, "Displaying permission rationale to provide additional context."); 
      Snackbar.make(
        findViewById(R.id.activity_main), 
        R.string.permission_rationale, 
        Snackbar.LENGTH_INDEFINITE) 
        .setAction(R.string.ok, new View.OnClickListener() { 
         @Override 
         public void onClick(View view) { 
          // Request permission 
          ActivityCompat.requestPermissions(MainActivity.this, 
            new String[]{Manifest.permission.BODY_SENSORS}, 
            REQUEST_PERMISSIONS_REQUEST_CODE); 
         } 
        }) 
        .show(); 
     } else { 
      Log.i(TAG, "Requesting permission"); 
      // Request permission. It's possible this can be auto answered if device policy 
      // sets the permission in a given state or the user denied the permission 
      // previously and checked "Never ask again". 
      ActivityCompat.requestPermissions(MainActivity.this, 
        new String[]{Manifest.permission.BODY_SENSORS}, 
        REQUEST_PERMISSIONS_REQUEST_CODE); 
     } 
    } 

的onResume功能客户:

private void buildFitnessClient() { 
     if (mClient == null && checkPermissions()&& checkPermissionsBody()) { 

      mClient = new GoogleApiClient.Builder(this) 
        .addScope(new Scope(Scopes.FITNESS_BODY_READ)) 
        .addApi(Fitness.SENSORS_API) 
        .addApi(Fitness.BLE_API) 
        .addConnectionCallbacks(
          new GoogleApiClient.ConnectionCallbacks() { 
           @Override 
           public void onConnected(Bundle bundle) { 
            Log.i(TAG, "Connected!!!"); 
            // Now you can make calls to the Fitness APIs. 

           } 

           @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"); 
            } 
           } 
          } 
        ) 
        .enableAutoManage(this, 0, new GoogleApiClient.OnConnectionFailedListener() { 
         @Override 
         public void onConnectionFailed(ConnectionResult result) { 
          Log.i(TAG, "Google Play services connection failed. Cause: " + 
            result.toString()); 
          Snackbar.make(
            MainActivity.this.findViewById(R.id.activity_main), 
            "Exception while connecting to Google Play services: " + 
              result.getErrorMessage(), 
            Snackbar.LENGTH_INDEFINITE).show(); 
         } 
        }) 
        .build(); 
     } 
    } 

     } 

现在找到健身来源:

private void findFitnessDataSources() { 
     // [START find_data_sources] 
     // Note: Fitness.SensorsApi.findDataSources() requires the ACCESS_FINE_LOCATION permission. 
     Fitness.SensorsApi.findDataSources(mClient, new DataSourcesRequest.Builder() 
       // At least one datatype must be specified. 
       .setDataTypes(DataType.TYPE_HEART_RATE_BPM) 
       // Can specify whether data type is raw or derived. 
       //.setDataSourceTypes(DataSource.TYPE_RAW) 
       .build()) 
       .setResultCallback(new ResultCallback<DataSourcesResult>() { 
        @Override 
        public void onResult(DataSourcesResult dataSourcesResult) { 
         Log.i(TAG, "Result: " + 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()); 

          //Let's register a listener to receive Activity data! 
          if (dataSource.getDataType().equals(DataType.TYPE_HEART_RATE_BPM) 
            && mListener == null) { 
           Log.i(TAG, "Data source for Heart Rate found! Registering."); 
           registerFitnessDataListener(dataSource, 
             DataType.TYPE_HEART_RATE_BPM); 
          } 
         } 
        } 
       }); 

建立BLE功能 - 这就是你找到的蓝牙设备:

private void buildBLE(){ 
     BleScanCallback callback = new BleScanCallback() { 
      @Override 
      public void onDeviceFound(BleDevice device) { 
       Log.d(TAG,"Found bluetooth Device"); 
       // A device that provides the requested data types is available 
       PendingResult<Status> pendingResult = 
         Fitness.BleApi.claimBleDevice(mClient, device); 
       Log.d(TAG,"Claimed bluetooth Device"); 
      } 
      @Override 
      public void onScanStopped() { 
       // The scan timed out or was interrupted 
       Log.d(TAG,"Scan was interruped"); 
      } 

     }; 


     StartBleScanRequest request = new StartBleScanRequest.Builder() 
       .setDataTypes(DataType.TYPE_HEART_RATE_BPM) 
       .setBleScanCallback(callback) 
       .build(); 

     if (mClient != null){ 
      PendingResult<Status> pendingResult = 
        Fitness.BleApi.startBleScan(mClient, request); 
      Log.d(TAG,"Find Sources"); 
      Log.d(TAG,"Pending result: "+pendingResult.toString()); 


     } else { 
      Log.d(TAG,"API client is null"); 
     } 
    } 

最后注册监听器:

private void registerFitnessDataListener(DataSource dataSource, DataType dataType) { 
     // [START register_data_listener] 
     Log.i(TAG,"Listener Started"); 
     mListener = new OnDataPointListener() { 
      @Override 
      public void onDataPoint(DataPoint dataPoint) { 
       for (Field field : dataPoint.getDataType().getFields()) { 
        Value val = dataPoint.getValue(field); 
        Log.i(TAG, "Detected DataPoint field: " + field.getName()); 
        Log.i(TAG, "Detected DataPoint value: " + val); 
       } 
      } 
     }; 

     Fitness.SensorsApi.add(
       mClient, 
       new SensorRequest.Builder() 
         .setDataSource(dataSource) // Optional but recommended for custom data sets. 
         .setDataType(dataType) // Can't be omitted. 
         .setSamplingRate(10, TimeUnit.SECONDS) 
         .build(), 
       mListener) 
       .setResultCallback(new ResultCallback<Status>() { 
        @Override 
        public void onResult(Status status) { 
         if (status.isSuccess()) { 
          Log.i(TAG, "Listener registered!"); 
         } else { 
          Log.i(TAG, "Listener not registered."); 
         } 
        } 
       }); 
     // [END register_data_listener] 
    } 

最这些功能是直接从谷歌适合指南在这里:https://developers.google.com/fit/

问题是,当我使用这些功能时,蓝牙设备被发现,并被重复循环声明。所以调试输出如下所示:

Log.d(TAG,"Found bluetooth Device"); 
Log.d(TAG,"Claimed bluetooth Device"); 
Log.d(TAG,"Found bluetooth Device"); 
Log.d(TAG,"Claimed bluetooth Device"); 
Log.d(TAG,"Found bluetooth Device"); 
Log.d(TAG,"Claimed bluetooth Device"); 
Log.d(TAG,"Found bluetooth Device"); 
Log.d(TAG,"Claimed bluetooth Device"); 
Log.d(TAG,"Found bluetooth Device"); 
Log.d(TAG,"Claimed bluetooth Device"); 
Log.d(TAG,"Found bluetooth Device"); 
Log.d(TAG,"Claimed bluetooth Device"); 
Log.d(TAG,"Found bluetooth Device"); 
Log.d(TAG,"Claimed bluetooth Device"); 
Log.d(TAG,"Scan cancelled"); 

尽管设备声明了很多次,但仍有数据传出。即使听众注册了,也是如此。我知道,因为我看到调试线: Log.i(TAG,“Listener Started”);

所以我的问题是,在这段代码中有什么不合适的地方?有没有人使用过这个?

回答

1

对于任何对Google Fit使用BLE设备感兴趣的人,此问题的答案是您一次只能注册一个设备。当你重置你的蓝牙适配器时,你必须重新声明应用程序中的BLE设备。因此,正确的程序是取消声明BLE设备,然后回收它。多次声明设备会导致奇怪的错误。