在 Android 应用的后台处理 GoogleFit

Handle GoogleFit in background in Android App

我正在尝试将我的应用连接到 Google Fit。我正在使用需要执行以下操作的 IntentService。当我有关于步骤的信息时开始。此时我正在尝试通过调用以下代码来创建 GoogleApiClient:

mClient = new GoogleApiClient.Builder(this)
      .addApi(Fitness.HISTORY_API)
      .addScope(new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE))
      .addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
      .addConnectionCallbacks(
            new GoogleApiClient.ConnectionCallbacks() {
               @Override
               public void onConnected(Bundle bundle) {
                  log.info("FITNESS_API: Connected!!!");
                  Thread thread = new Thread(new Runnable() {
                     @Override
                     public void run() {
                        insertOrUpdateDataPoints();
                     }
                  });

                  thread.start();
               }

               @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.info("FITNESS_API: Connection lost.  Cause: Network Lost.");
                  } else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
                     log.info("FITNESS_API: Connection lost.  Reason: Service Disconnected");
                  }
               }
            }
      ).build();

mClient.connect();

创建 DataSet 并将步骤详细信息添加为 DataPoint 元素后,我将信息同步到 Google 安装并关闭 GoogleApiClient 并使用:

com.google.android.gms.common.api.Status insertStatus =
  Fitness.HistoryApi.insertData(mClient, dataSet).await(1, TimeUnit.MINUTES);

  // Before querying the data, check to see if the insertion succeeded.
  if (!insertStatus.isSuccess()) {
     log.info("FITNESS_API: There was a problem inserting the dataset. Status = " + insertStatus.getStatusCode());
  }

  mClient.disconnect();
  mClient = null;

问题是,通过尝试自行管理 GoogleApiClient(没有启用自动管理),我没有收到允许应用程序 post 数据到 Google 合身。如果我在创建 GoogleApiClient 时使用 enableAutoManage,此行为会发生变化。但是,为了为客户端启用AutoManage,由于enableAutoManage 所需的参数,我需要有一个ActivityFragment。我无权访问 IntentyService 中的 ActivityFragment,我确实希望将客户端的管理和插入操作保留在单独的服务中,该服务可以在后台 运行。

此外,当我不使用 enableAutoManage 时,即使我已经为 GoogleApiClient 注册了连接回调,也没有任何反应。

如何确保我的应用程序提示用户允许应用程序 post 到 Google Fit?如果用户打开应用程序时应用程序没有 Google Fit 中的 post 权限,我需要发生这种情况。有任何想法吗?谢谢。

我找到了解决方案。

如果你不想使用"enableAutoManage",你需要像这样注册onConnectionFailed方法:

    @Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    if( !authInProgress ) {
        try {
            authInProgress = true;
            connectionResult.startResolutionForResult( MainActivity.this, REQUEST_OAUTH );
        } catch(IntentSender.SendIntentException e ) {

        }
    } else {
        Log.e( "GoogleFit", "authInProgress" );
    }
}

这将显示对话框。

在您的意图服务中使用@Vlad 提到的上述方法。创建一个通知(粘性或其他取决于您的重要性),要求用户在遇到 onconnection 失败时授予您权限。该通知会将用户重定向到 activity,您在其中要求用户再次为您提供 fitaccess。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQUEST_OAUTH:
            if (resultCode != Activity.RESULT_OK) {
                return;
            }

            if (!googleApiClient.isConnected()) {
                googleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
            } else {
                readDataTask();
            }
            return;
        case RC_SIGN_IN:
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                GoogleSignInAccount account = result.getSignInAccount();
                String email = account.getEmail();//you can get OAuth user's email AT THIS POINT.

                if (GoogleFitService.googleApiClient.isConnected()) {
                    readDataTask();
                }
            }
    }
}

第一次您需要做的是 Oauth Google 帐户,然后获取您的电子邮件。

 gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .setAccountName("user's email")
                .requestScopes(
                        new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE),
                        new Scope(Scopes.FITNESS_BODY_READ_WRITE),
                        new Scope(Scopes.FITNESS_NUTRITION_READ_WRITE),
                        new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
                .build();

后台获取Google拟合数据后,需要设置Email。