Google Фитнес: работа с TransactionTooLargeException без обратной связи

#android #google-fit #google-fit-sdk

#Android #google-fit #google-fit-sdk

Вопрос:

Я создаю приложение, интегрирующееся с Google Fit через локальный (не REST) API Google Fit. Я использую Flutter 1.2.1, Kotlin 1.3.21, com.google.android.gms: play-services-fitness: 16.0.1 и запускаю приложение на Android 8.1.0 с Google Play Services 16.0.89.

Некоторые запросы HistoryClient.ReadData() исчезают без какой-либо обратной связи (нет вызовов onsucclistener, 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)
  

Насколько я понимаю, либо локальная служба фитнеса (часть сервисов Google Play) не отправляет уведомление о сбое, либо клиентская библиотека в Google Fit, которую я использую, не передает его.
Правильно ли это?

Как другие используют этот API для решения этой проблемы? Какой хороший промежуток времени следует запросить, чтобы быть достаточно уверенным в том, что он будет успешно завершен на всех телефонах?

Примечание: я попытался опубликовать это как ошибку на https://issuetracker.google.com/issues/130402455 , но я не получил ответа, и я даже не уверен, что это было подходящее место для этого.

Комментарии:

1. Я предполагаю HistoryClient.readData() , что запрашивается слишком много информации, что приведет к тому TransactionTooLargeException , сможете ли вы случайно разделить информацию?

2. @jackz314 Конечно, но насколько точно мне нужно его разделить? Я хотел, чтобы данные за месяц и однодневные части казались разумными, но иногда это исключение случается. Возможно, на моем телефоне он будет работать с шагом в полдня, но как насчет более медленных телефонов или учетных записей с большим количеством данных?

3. обычно, если объем данных превышает 200 TransactionTooLargeException кб, выдается ошибка, поэтому я бы сказал, что сейчас запрашивается менее половины данных

4. Я придумал способ записи журналов ошибок, это взлом, но, вероятно, это единственный возможный способ на данный момент, и он должен сработать, ознакомьтесь с моим ответом.

Ответ №1:

TransactionTooLargeException означает, что обмен данными между службами / приложениями любого типа превысил допустимый верхний предел данных Android. Обычно ограничение по размеру составляет около 200 КБ, но оно может варьироваться (и я не уверен на 100%).

Решением было бы разделить запрашиваемые вами данные, просматривая API Google Fit, я думаю, вы можете попробовать получать меньше данных за раз, установив более короткий временной диапазон в DataRequest . В вашем случае ошибка говорит о том, что вы запрашиваете около 500 КБ данных, что означает, что вы можете попытаться сократить временной интервал вашего запроса примерно до половины.

Но даже тогда фактический размер данных может сильно варьироваться в зависимости от действий пользователя, и не идеально запрашивать слишком мало за раз много раз, поэтому я думаю, вы могли бы попробовать настроить таймер после вашего запроса, и если через некоторое время данные не возвращаются, сократите временной интервал запроса и повторите попытку (поскольку зафиксировать ошибку невозможно).

Другим подходом к обнаружению ошибки было бы чтение журналов в отдельном потоке, и если он поймает TransactionTooLargeException , он выполнит обратный вызов и уведомит вас об уменьшении временного интервала запроса. Вы можете записывать журналы следующим образом:

 try {
  Process process = Runtime.getRuntime().exec("logcat *:S Fitness:W");//only show Google Fitness related logs
  BufferedReader bufferedReader = new BufferedReader(
  new InputStreamReader(process.getInputStream()));
  String line = "";
  while ((line = bufferedReader.readLine()) != null) {
     if(line.contains("Error delivering batch")){
        //do your callback here
     }
  }
  } 
catch (IOException e) {}
  

И поскольку исключение не генерируется, я бы сказал, что это ошибка со стороны Google, поскольку они не рассматривали эту ситуацию и не перехватывали это исключение, и это был бы действительный отчет об ошибке.