0

私は、ブルートゥースセンサーに接続して心拍数を読み取るGoogle適合アプリを開発中です。私はGitHubでgoogleの基本的なセンサーのデモをたどったが、私はGoogleに合うようにサインインした。ここでは、コードは次のようになります。Google Fit APIサインインが必要です

import android.Manifest; 
import android.content.Intent; 
import android.content.pm.PackageManager; 
import android.net.Uri; 
import android.os.Bundle; 
import android.provider.Settings; 
import android.support.annotation.NonNull; 
import android.support.v4.app.ActivityCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 

import java.util.concurrent.BlockingDeque; 
import java.util.concurrent.LinkedBlockingDeque; 
import java.util.concurrent.TimeUnit; 

import android.support.design.widget.Snackbar; 

import com.google.android.gms.auth.api.Auth; 
import com.google.android.gms.auth.api.signin.GoogleSignInOptions; 
import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.Scopes; 
import com.google.android.gms.common.api.GoogleApiClient; 
import com.google.android.gms.common.api.PendingResult; 
import com.google.android.gms.common.api.ResultCallback; 
import com.google.android.gms.common.api.Scope; 
import com.google.android.gms.common.api.Status; 
import com.google.android.gms.fitness.Fitness; 
import com.google.android.gms.fitness.data.BleDevice; 
import com.google.android.gms.fitness.data.DataPoint; 
import com.google.android.gms.fitness.data.DataSource; 
import com.google.android.gms.fitness.data.DataType; 
import com.google.android.gms.fitness.data.Field; 
import com.google.android.gms.fitness.data.Value; 
import com.google.android.gms.fitness.request.BleScanCallback; 
import com.google.android.gms.fitness.request.DataSourcesRequest; 
import com.google.android.gms.fitness.request.OnDataPointListener; 
import com.google.android.gms.fitness.request.SensorRequest; 
import com.google.android.gms.fitness.request.StartBleScanRequest; 
import com.google.android.gms.fitness.result.DataSourcesResult; 

public class MainActivity extends AppCompatActivity { 

    public static final String TAG = "GoogleFitSensorCode"; 
    // [START auth_variable_references] 
    private GoogleApiClient mClient = null; 
    private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34; 

    // [START mListener_variable_reference] 
    // Need to hold a reference to this listener, as it's passed into the "unregister" 
    // method in order to stop all sensors from sending data to this listener. 
    private OnDataPointListener mListener; 
// [END mListener_variable_reference] 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     setContentView(R.layout.activity_main); 


     // Now we want to check if persmissions are given to the app 
     // When permissions are revoked the app is restarted so onCreate is sufficient to check for 
     // permissions core to the Activity's functionality. 
     if (!checkPermissions()) { 
      requestPermissions(); 
     } 

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


    } 

    @Override 
    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(); 


     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 
      } 

     }; 


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

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

      // Search for the data sources 
      findFitnessDataSources(); 
     } else { 
      Log.d(TAG,"API client is null"); 
     } 

    } 

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

    // Now we need to build the API client 
    // [START auth_build_googleapiclient_beginning] 
    /** 
    * Build a {@link GoogleApiClient} that will authenticate the user and allow the application 
    * to connect to Fitness APIs. The scopes included should match the scopes your app needs 
    * (see documentation for details). Authentication will occasionally fail intentionally, 
    * and in those cases, there will be a known resolution, which the OnConnectionFailedListener() 
    * can address. Examples of this include the user never having signed in before, or having 
    * multiple accounts on the device and needing to specify which account to use, etc. 
    */ 
    private void buildFitnessClient() { 
     if (mClient == null && checkPermissions() && checkPermissionsBody()) { 

      GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
        .requestEmail() 
        .requestScopes(new Scope(Scopes.FITNESS_BODY_READ)) 
        .build(); 

      mClient = new GoogleApiClient.Builder(this) 
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso) 
        .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. 
            //findFitnessDataSources(); 
           } 

           @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(); 
     } 
    } 
// [END auth_build_googleapiclient_beginning] 

    /** 
    * Find available data sources and attempt to register on a specific {@link DataType}. 
    * If the application cares about a data type but doesn't care about the source of the data, 
    * this can be skipped entirely, instead calling 
    *  {@link com.google.android.gms.fitness.SensorsApi 
    *  #register(GoogleApiClient, SensorRequest, DataSourceListener)}, 
    * where the {@link SensorRequest} contains the desired data type. 
    */ 
    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_LOCATION_SAMPLE) 
            && mListener == null) { 
           Log.i(TAG, "Data source for LOCATION_SAMPLE found! Registering."); 
           registerFitnessDataListener(dataSource, 
             DataType.TYPE_LOCATION_SAMPLE); 
          } 
         } 
        } 
       }); 
     // [END find_data_sources] 
    } 

    /** 
    * Register a listener with the Sensors API for the provided {@link DataSource} and 
    * {@link DataType} combo. 
    */ 
    private void registerFitnessDataListener(DataSource dataSource, DataType dataType) { 
     // [START register_data_listener] 
     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] 
    } 

    /** 
    * Callback received when a permissions request has been completed. 
    */ 
    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 
              @NonNull int[] grantResults) { 
     Log.i(TAG, "onRequestPermissionResult"); 
     Log.i(TAG,String.valueOf(PackageManager.PERMISSION_GRANTED)); 
     if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) { 
      if (grantResults.length <= 0) { 
       // If user interaction was interrupted, the permission request is cancelled and you 
       // receive empty arrays. 
       Log.i(TAG, "User interaction was cancelled."); 
      } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       // Permission was granted. 
       buildFitnessClient(); 
      } else { 
       // Permission denied. 

       // In this Activity we've chosen to notify the user that they 
       // have rejected a core permission for the app since it makes the Activity useless. 
       // We're communicating this message in a Snackbar since this is a sample app, but 
       // core permissions would typically be best requested during a welcome-screen flow. 

       // Additionally, it is important to remember that a permission might have been 
       // rejected without asking the user for permission (device policy or "Never ask 
       // again" prompts). Therefore, a user interface affordance is typically implemented 
       // when permissions are denied. Otherwise, your app could appear unresponsive to 
       // touches or interactions which have required permissions. 
       Snackbar.make(
         findViewById(R.id.activity_main), 
         R.string.permission_denied_explanation, 
         Snackbar.LENGTH_INDEFINITE) 
         .setAction(R.string.settings, new View.OnClickListener() { 
          @Override 
          public void onClick(View view) { 
           // Build intent that displays the App settings screen. 
           Intent intent = new Intent(); 
           intent.setAction(
             Settings.ACTION_APPLICATION_DETAILS_SETTINGS); 
           Uri uri = Uri.fromParts("package", 
             BuildConfig.APPLICATION_ID, null); 
           intent.setData(uri); 
           intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
           startActivity(intent); 
          } 
         }) 
         .show(); 
      } 
     } 
    } 
} 

===============編集:出力================= を追加しますこのコードは、エミュレータでアプリケーションを作成し、本体の権限と場所のアクセス権を求めます。それは次のような出力を持っているgoogleapiclientを接続しようとすると:

I/GoogleFitSensorCode: Connected!!! 
I/GoogleFitSensorCode: Result: Status{statusCode=SIGN_IN_REQUIRED, resolution=PendingIntent{7a2c07b: [email protected]}} 
アイブ氏は2日のために今、この問題を回避しようとしてき

、任意の提案ですか?

+0

だから何が起こるのですか? – Ifor

+0

@Ifor、出力を追加しました。だからあなたが見ることができるように、APIクライアントはonConnected()メソッドを起動します。しかし、onResume()でfindFitnessDataSources()を呼び出すと、サインインが必要であることが示されます。 – MadProgrammer

+0

私はオプションで、Googleの記号を削除した場合: GoogleSignInOptions GSO =新しいGoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestEmail() .requestScopes(新しいスコープ(Scopes.FITNESS_BODY_READ)) .buildを(); その後、GoogleアカウントにログインしてConnectionのキャンセルを促します。 – MadProgrammer

答えて

0

上記のこれらの行を削除します。

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) 
        .requestEmail() 
        .requestScopes(new Scope(Scopes.FITNESS_BODY_READ)) 
        .build(); 

をこれがグーグルにサインインするためのダイアログが表示されます。

Google開発者アカウントを作成し、認証資格情報を割り当てます。あなたの個人的なセキュリティ資格情報が認証を妨げる可能性があります。

関連する問題