Google Fitness:处理TransactionTooLargeException而没有反馈

时间:2019-04-19 08:10:53

标签: android google-fit google-fit-sdk

我正在构建通过本地(而非REST)Google Fit API与Google Fit集成的应用程序。我正在使用Flutter 1.2.1,Kotlin 1.3.21,com.google.android.gms:play-services-fitness:16.0.1,并在带有Google Play服务16.0.89的Android 8.1.0上运行该应用程序。

一些HistoryClient.readData()请求消失而没有任何反馈(没有调用onSuccessListener,onCancelledListener,onFailureListener,onCompleteListener回调),这些时候我可以在日志中看到:

   W/Fitness: Error delivering batch 0. Attempt #2
    android.os.TransactionTooLargeException: data parcel size 572360 bytes
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(Binder.java:777)
        at crb.c(:com.google.android.gms@16089017@16.0.89 (040306-239467275):1)
        at yek.a(Unknown Source:8)
        at yta.a(:com.google.android.gms@16089017@16.0.89 (040306-239467275):52)
        at yta.a(:com.google.android.gms@16089017@16.0.89 (040306-239467275):31)
        at ytc.run(:com.google.android.gms@16089017@16.0.89 (040306-239467275):44)
        at rrt.b(:com.google.android.gms@16089017@16.0.89 (040306-239467275):32)
        at rrt.run(:com.google.android.gms@16089017@16.0.89 (040306-239467275):21)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
        at rxx.run(Unknown Source:7)
        at java.lang.Thread.run(Thread.java:764)

我的理解是,本地Fitness服务(属于Google Play服务的一部分)未能发送有关失败的通知,或者我正在使用的客户端库向Google Fit传递失败。 这是正确的吗?

其他人如何使用此API解决此问题? 请问有多大的时间跨度才能合理确定它会在所有手机上成功完成?

注意:我曾尝试将其发布为https://issuetracker.google.com/issues/130402455上的错误,但没有得到回应,甚至不确定是不是正确的地方。

1 个答案:

答案 0 :(得分:1)

class Account { private $user_name = NULL; private $cxn; // database connection object private $table_name; private $message; function __construct( mysqli $cxn,$table) { $this->cxn = $cxn; if(is_string($table)) #17 { $sql = "SHOW TABLES LIKE '$table'"; #19 $result = $this->cxn->query($sql); if($result->num_rows > 0) #21 { $this->table_name = $table; } else #25 { throw new Exception("$table is not a table in the database"); return FALSE; } } else #32 { throw new Exception("Second parameter is not a valid table name"); return FALSE; } } function selectAccount($user_name) { $user_name = trim($user_name); #42 $sql = "SELECT user_name FROM $this->table_name WHERE user_name ='$user_name'"; #44 if(!$result = $this->cxn->query($sql)) { throw new Exception("Couldn't execute query: " .$this->cxn->error()); return FALSE; } if($result->num_rows < 1 ) #51 { $this->message = "Account $user_name does not exist!"; return FALSE; } else #57 { $this->user_name = $user_name; return TRUE; } } function comparePassword($password) { if(!isset($this->user_name)) #66 { throw new Exception("No account currently selected"); exit(); } #70 $sql = "SELECT user_name FROM $this->table_name WHERE user_name ='$this->user_name' AND password = md5('$password')"; if(!$result = $this->cxn->query($sql)) #74 { throw new Exception("Couldn't execute query: " .mysql_error()); exit(); } if($result->num_rows < 1 ) #80 { $this->message = "Incorrect password for account $this->user_name!"; return FALSE; } else #86 return TRUE; } 表示任何类型的服务/应用之间的数据交换都超过了Android允许的数据上限。通常,大小限制为200KB左右,但可能会有所不同(我不确定100%)。

解决方案是通过Google Fit API拆分您请求的数据,我认为您可以尝试通过在TransactionTooLargeException中设置较短的时间范围来一次获取较少的数据。对于您而言,该错误表明您正在请求大约500KB的数据,这意味着您可以尝试将请求的时间跨度缩短到一半左右。

但是即使如此,实际的数据大小仍可能根据用户的活动而有很大的不同,并且一次多次请求太少也不理想,因此我认为您可以尝试在请求后设置计时器,并且如果过了一段时间仍未返回数据,请减少请求的时间跨度,然后重试(因为无法捕获错误)。

捕获错误的另一种方法是在单独的线程中读取日志,如果捕获了DataRequest,它将回调并通知您减少请求的时间跨度。您可以像这样捕获日志:

TransactionTooLargeException

毫无疑问,这是Google的一个bug,因为他们没有考虑这种情况并捕获到该异常,这将是一个有效的bug报告。