WatchFace,WatchConfig和随播应用上的Google Fit授权错误(5005,5000和5015错误) [英] Google Fit authorization bugs (with 5005, 5000, and 5015 errors) on WatchFace, WatchConfig, and companion app

查看:241
本文介绍了WatchFace,WatchConfig和随播应用上的Google Fit授权错误(5005,5000和5015错误)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一些关于可怕5005错误的新想法:状态代码表示尝试获取OAuth令牌时发生未知错误。当我的Watch Face尝试连接使用各种Fitness API构建的Google API时。这一切都在我的本地测试和我下载并运行我的RELEASE(测试版)版本时起作用。但是,当我的第一个测试人员尝试使用它时,他在尝试连接API时得到了错误代码。



UPDATE2:我现在已经跟踪了发生了什么,所以我我将在此列出我的最终工作代码,然后在答案中谈谈我发现的内容。

我有3种不同的连接Google API的场合:Watch Face(裁判计时器: https://play.google.com/store/apps/details?id=com.pipperpublishing.soccerrefpro ),关联的Watch Config以及Mobile(手机)上的伴侣应用。

表盘:

  private GoogleApiClient buildGoogleClient(){
final GoogleApiClient googleApiClient;
final GoogleApiClient.Builder googleApiClientBuilder = new GoogleApiClient.Builder(RefWatchFaceService.this);

// GoogleClient的通用组件
googleApiClientBuilder
.addApi(Wearable.API)
.addApi(Fitness.SESSIONS_API)//设置每个期间的Session)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.useDefaultAccount(); (RefWatchUtil.isRefWatchPro()){
googleApiClientBuilder
.addApi(Fitness.RECORDING_API)//记录低功耗信息
.addApiIfAvailable(Fitness.HISTORY_API $)

if新的作用域(Scopes.FITNESS_ACTIVITY_READ)
,新的作用域(Scopes.FITNESS_LOCATION_READ)

.addApiIfAvailable(Fitness.SENSORS_API
,新的作用域(Scopes.FITNESS_ACTIVITY_READ)
,新的范围(Scopes.FITNESS_LOCATION_READ)

;
}
googleApiClient = googleApiClientBuilder.build();
返回googleApiClient;
}

请注意,我没有要求HISTORY_API的WRITE权限。当我以后尝试在Google健身店中插入SPEED和LOCATION健身数据时,我使用以下代码:

  private void insertFitnessDataSetBatch(最终的DataSet batchDataSet){
final long batchStartTimeMillis = batchDataSet.getDataPoints()。get(0).getTimestamp(TimeUnit.MILLISECONDS);
final long batchEndTimeMillis;
long tempEndTimeMillis = batchDataSet.getDataPoints()。get(batchDataSet.getDataPoints()。size() - 1).getTimestamp(TimeUnit.MILLISECONDS);
//这可能是由一个数据点调用的,在这种情况下,Fitness插入将在相同的开始和结束时间遏制
if(tempEndTimeMillis> batchStartTimeMillis){
batchEndTimeMillis = tempEndTimeMillis ;
} else {
batchEndTimeMillis = batchStartTimeMillis + 1;



尝试{
Fitness.HistoryApi.insertData(mGoogleApiClient,batchDataSet)
.setResultCallback(new ResultCallback< Status>(){
@Override
public void onResult(@NonNull Status status){
//有时会出现错误,但插入数据
readInsertedFitnessData(batchStartTimeMillis,batchEndTimeMillis,batchDataSet.getDataType() );
if(!status.isSuccess()){
Log.d(TAG,String.format(插入数据类型%s返回状态代码%d(%s),
)batchDataSet.getDataType()。getName(),status.getStatusCode(),status.getStatusMessage()));
}
}
});
} catch(RuntimeException e){
Log.e(TAG,String.format(有一个运行时异常插入类型为%s的数据集批处理:%s,
batchDataSet .getDataType()。getName(),e.​​getLocalizedMessage()));
}

}

记住这个回读代码,因为我会在我的答案中引用结果。



监视配置
这里的区别在于Watch Config扩展了FragmentActivity:

 私有GoogleApiClient buildGoogleClient(){
最终GoogleApiClient googleApiClient;
final GoogleApiClient.Builder googleApiClientBuilder = new GoogleApiClient.Builder(this);

// GoogleClient的通用组件
googleApiClientBuilder
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.useDefaultAccount();

if(RefWatchUtil.isRefWatchPro()){
googleApiClientBuilder
.addApiIfAvailable(Fitness.HISTORY_API
,新范围(Scopes.FITNESS_ACTIVITY_READ_WRITE)
,新范围(Scopes.FITNESS_LOCATION_READ_WRITE)
);
}
googleApiClient = googleApiClientBuilder.build();
返回googleApiClient;
}

注意这里我要求READ_WRITE范围,尽管实际上我没有参考配置中的HISTORY_API(或任何Fitness Api)。但是,用户必须进入Watch COnfig才能打开我的设置( KEY_FITNESS _?),该设置控制着在Watch Face中读取Sensor数据。



最后,
手机

 私人GoogleApiClient buildGoogleClient (){
final GoogleApiClient.Builder googleApiClientBuilder;
googleApiClientBuilder = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApiIfAvailable(Wearable.API); //只是为了防止使用Wear而不使用
if(RefWatchUtil.isRefWatchPro()){
googleApiClientBuilder
//.addApiIfAvailable(Fitness.SESSIONS_API)
.addApiIfAvailable (Fitness.HISTORY_API,//读取每场比赛的位置和其他数据
新的作用域(Scopes.FITNESS_ACTIVITY_READ),
新的作用域(Scopes.FITNESS_LOCATION_READ))
.useDefaultAccount();
}
返回googleApiClientBuilder.build();
}


解决方案

谷歌在useDefaultAccount如何在幕后工作,这会影响上面正在编写/读取哪个Fit帐户。以下是我提出的问题:



我真的需要一个关于以下问题的答案,这个问题一直在困扰我的测试数月。我正在使用我的磨损表面上的Fitness Apis。我在Google客户端构建器中使用useDefaultAccount。但在这种情况下哪个帐户是默认帐户?
- 用于下载应用程序的帐户(在这种情况下,从开发机器安装应用程序时使用的帐户)
- 它为空/未设置
- 这是您选择的帐户伴侣应用程序,当你连接。
- 这是Google Fit中选择的当前帐户
- 您无法在Wear faces / apps中使用useDefaultAccount



来自Google的答复(感谢Gustavo Moura):
以下是我对逻辑的理解(它没有很好的记录,我们打算在不久的将来进行清理):
1.如果有伴侣应用,用户已登录Fit并选择了一个帐户,我们会将该帐户同步到Wear设备并使用它。
2.如果没有配套应用程序(或者用户尚未登录),但用户已安装并启用Google健身并已选择Fit的帐户,我们会将该帐户同步到Wear设备并使用它。
3.如果没有伴侣应用程序且没有Google健身,但Wear设备有另一个具有类似行为的内置应用程序(如摩托罗拉手表上的Moto Body),我们将使用该应用程序中的帐户。
4.如果以上都不是真的,那么即使没有帐户,也有一些API可以工作(如步骤计数器记录和查询)。这是特别的,因为在这种模式下访问的任何数据都只是手表的本地数据,并且它永远不会同步到任何其他设备或服务器。


I am looking for some fresh ideas on the dreaded 5005 error: "Status code denotes that an unknown error occurred while trying to obtain an OAuth token." when my Watch Face tries to connect a Google API built with various Fitness APIs. This all works in my local testing AND when I download and run my RELEASE (beta) version. However, when my first tester tried it, he gets that error code when trying to connect the API.

UPDATE2: I have now tracked down what is going on, so I'm going to list my final working code here and then talk in the answer about what I discovered.

There are 3 different occasions where I connect to the Google API: the Watch Face (a referee timer: https://play.google.com/store/apps/details?id=com.pipperpublishing.soccerrefpro), the associated Watch Config, and the companion app on the Mobile (phone).

Watch Face:

    private GoogleApiClient buildGoogleClient() {
        final GoogleApiClient googleApiClient;
        final GoogleApiClient.Builder googleApiClientBuilder = new GoogleApiClient.Builder(RefWatchFaceService.this);

        //Common components of the GoogleClient
        googleApiClientBuilder
                .addApi(Wearable.API)
                .addApi(Fitness.SESSIONS_API)    //set Session for each period)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .useDefaultAccount();

        if (RefWatchUtil.isRefWatchPro()) {
            googleApiClientBuilder
                    .addApi(Fitness.RECORDING_API)  //records low power information
                    .addApiIfAvailable(Fitness.HISTORY_API
                        ,new Scope(Scopes.FITNESS_ACTIVITY_READ)
                        ,new Scope(Scopes.FITNESS_LOCATION_READ)
                    )
                    .addApiIfAvailable(Fitness.SENSORS_API
                        ,new Scope(Scopes.FITNESS_ACTIVITY_READ)
                        ,new Scope(Scopes.FITNESS_LOCATION_READ)
                    )
                    ;
        }
        googleApiClient = googleApiClientBuilder.build();
        return googleApiClient;
    }

Notice that I don't ask for WRITE permission for the HISTORY_API. When I later try to insert SPEED and LOCATION fitness data in the Google Fit store, I use this code:

private void insertFitnessDataSetBatch(final DataSet batchDataSet) {
    final long batchStartTimeMillis = batchDataSet.getDataPoints().get(0).getTimestamp(TimeUnit.MILLISECONDS);
    final long batchEndTimeMillis;
    long tempEndTimeMillis = batchDataSet.getDataPoints().get(batchDataSet.getDataPoints().size()-1).getTimestamp(TimeUnit.MILLISECONDS);
    //It's possible that this is called with one data point, in which case the Fitness insert will choke on same start and end time
    if (tempEndTimeMillis > batchStartTimeMillis) {
        batchEndTimeMillis = tempEndTimeMillis;
    } else {
        batchEndTimeMillis = batchStartTimeMillis + 1;
    }


    try {
        Fitness.HistoryApi.insertData(mGoogleApiClient, batchDataSet)
                .setResultCallback(new ResultCallback<Status>() {
                    @Override
                    public void onResult(@NonNull Status status) {
                        //Sometimes there is an error but the data was inserted anyway
                        readInsertedFitnessData(batchStartTimeMillis, batchEndTimeMillis, batchDataSet.getDataType());
                        if (!status.isSuccess()) {
                            Log.d(TAG, String.format("Inserting data type %s returned status Code %d (%s)",
                                    batchDataSet.getDataType().getName(), status.getStatusCode(), status.getStatusMessage()));
                        }
                    }
                });
    } catch (RuntimeException e) {
        Log.e(TAG, String.format("There was a runtime exception inserting the data set batch for type %s: %s",
                batchDataSet.getDataType().getName(), e.getLocalizedMessage()));
    }

}

Remember this read-back code, because I'll reference the results in my answer.

Watch Config The difference here is that the Watch Config extends FragmentActivity:

private GoogleApiClient buildGoogleClient() {
    final GoogleApiClient googleApiClient;
    final GoogleApiClient.Builder googleApiClientBuilder = new GoogleApiClient.Builder(this);

    //Common components of the GoogleClient
    googleApiClientBuilder
            .addApi(Wearable.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .useDefaultAccount();

    if (RefWatchUtil.isRefWatchPro()) {
        googleApiClientBuilder
                .addApiIfAvailable(Fitness.HISTORY_API
                ,new Scope(Scopes.FITNESS_ACTIVITY_READ_WRITE)
                ,new Scope(Scopes.FITNESS_LOCATION_READ_WRITE)
                );
    }
    googleApiClient = googleApiClientBuilder.build();
    return googleApiClient;
}

Notice here I ask for READ_WRITE scopes, although in reality I don't reference the HISTORY_API (or any Fitness Api) in the Config. However, the user has to go into the Watch COnfig to turn on my setting (KEY_FITNESS_? below) which controls reading Sensor data in the Watch Face.

Finally, Mobile

private GoogleApiClient buildGoogleClient() {
    final GoogleApiClient.Builder googleApiClientBuilder;
    googleApiClientBuilder = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApiIfAvailable(Wearable.API); //just in case you are using this without a Wear device
    if (RefWatchUtil.isRefWatchPro()) {
        googleApiClientBuilder
            //.addApiIfAvailable(Fitness.SESSIONS_API)
            .addApiIfAvailable(Fitness.HISTORY_API,    //to read Location and other data per game
                    new Scope(Scopes.FITNESS_ACTIVITY_READ),
                    new Scope(Scopes.FITNESS_LOCATION_READ))
            .useDefaultAccount();
    }
    return googleApiClientBuilder.build();
}

解决方案

I finally got an answer from Google on how useDefaultAccount works behind the scenes and this affects which Fit account is being written/read above. Here's the question I posed:

I really need an answer on the following question which has been messing my testing up for months. I am using the Fitness Apis from my Wear watch face. I use "useDefaultAccount" in the Google client builder. But which account is the default in this case? - the account used to download the app (in which case what account is used when you install the app from your dev machine) - it's null/unset - it's the account you pick your companion app when you connect. - it's the current account selected in Google Fit - you can't use useDefaultAccount in Wear faces/apps

And the answer from Google (thanks Gustavo Moura): Here's how I understand the logic (it's not very well documented and we intend to clean it up in the near future): 1. if there's a companion app and the user has signed into Fit and picked an account there, we'll sync that account to the Wear device and use it. 2. if there's no companion app (or the user hasn't signed into it), but the user has Google Fit installed and enabled, and has selected an account with Fit, we'll sync that account to the Wear device and use it. 3. if there's no companion app and no Google Fit, but the Wear device has another built-in app that has similar behavior (like Moto Body on Motorola watches), we'll use the account from that app. 4. if none of the above is true, there are still some APIs that will work even without an account (like step counter recording and querying). This is special in that any data accessed in this mode will be data local to the watch only and it will never be synced to any other devices or servers.

这篇关于WatchFace,WatchConfig和随播应用上的Google Fit授权错误(5005,5000和5015错误)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆