Android Crashlytics - ограничение доступа к сети

Некоторое время я работал над отсутствием возможности ограничить использование сети Crashlytics при определенных условиях. Например - в роуминге, на дозированных сетях и т.д.

Согласно документации SDK, только два варианта, которые я нашел, обратились к этому так:

  • "Отключить" во время выполнения просто не инициализировать Crashlytics

  • встроенного диалога согласия пользователя перед отправкой отчета о сбое

Этот API очень ограничен, потому что:

  • Не инициализировать Crashlytics не только предотвращает доступ к сети, но и предотвращает любые шансы Crashlytics будет локально сохранять отчет о сбое, чтобы в итоге событие было отправлено. Не говоря уже о том, что нет хорошего способа отказаться от времени выполнения, помимо жестокого обращения с Thread.setUncaughtExceptionHandler

  • диалог согласия не имеет никакого смысла для пользователя, если авария происходит в фоновом режиме.

Мой вопрос в основном: я что-то упускаю? Есть ли способ ограничить доступ к сети Crashlytics?

Моя мотивация связана с необходимостью предотвращения ситуации, когда мое приложение использует пропускную способность сети, потенциально может стоить деньги пользователю при определенных условиях, хотя включены настройки "сотовая сеть" или "использование данных через роуминг".

Ответ 1

Я бывший сопровождающий SDK Crashlytics для iOS/macOS. Я относительно незнакома с Android-версией SDK и определенно не знаком с Android в целом. Но я сделаю это.

То, что вы хотите сделать, это то, что было запрошено на стороне iOS несколько раз. Я бы любил делать это на самом деле, потому что кажется довольно ужасным заставить конечных пользователей нести эти затраты. Тем не менее, сеть IOS SDK и запуск программы являются очень сложными и очень деликатными. Очень сложно гарантировать доставку аварий и отсутствие нужных возможностей для несогласованных состояний. Я считаю, что Android здесь проще, но я не могу сказать это с полномочиями.

Однако у IOS SDK есть несколько перехватов для дополнительных функций на уровне клиента. Ознакомьтесь с предупреждением об одном из этих API:

 *  @warning Just implementing this delegate method will disable all forms of synchronous report submission. This can
 *           impact the reliability of reporting crashes very early in application launch.

В принципе, чтобы удовлетворить контракт этого конкретного API, некоторые методы повышения надежности отчетов должны быть отключены. Дело в том, иногда оно того стоит. Многие приложения решают сделать этот компромисс. Многие приложения также задерживают инициализацию Crashlytics для повышения производительности. Это оказывает огромное влияние на надежность отчетности, но это нужно сделать другим разработчикам приложений.

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

Вы даже можете сделать что-то совершенно безумное, например, переопределить Thread.setUncaughtExceptionHandler самостоятельно и буферизовать исключения во время этой ситуации на диск. И затем, переиграйте их в Crashlytics, когда все будет лучше. Включите его в библиотеку с открытым исходным кодом. Бьюсь об заклад, люди будут любить его! Возможно, это не команда Android Crashlytics, хотя;) (Привет!)

Это также та же самая рекомендация, предложенная Gastón выше, с каким-то дополнительным контекстом вокруг того, что я видел на стороне iOS. Также стреляйте в людей Crashlytics по электронной почте с просьбой об этом. Я думаю, это отличная идея.

Ответ 2

Не существует способа ограничить использование Интернета для Crashlytics в приложении. Но как я исправит это, либо предоставить информацию о пользователе, которую Crashlytics использует в роуминге, либо просто сохранить отчет о сбое локально и отправить его после подключения пользователя к сети Wi-Fi. Также вы можете дать пользователю выбор, предпочитая ли он сохранять отчеты о сбоях локально или отправлять их сразу же через роуминг.

  1. Сохраните ErrorLog локально на устройстве
  2. Загрузите ErrorLog после установления соединения с Wi-Fi

Вы должны иметь возможность использовать ConnectivityManager для получения состояния адаптера Wi-Fi. Оттуда вы можете проверить, подключен ли он или даже доступен.

ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

if (mWifi.isConnected()) {
    // post error logs
}

Ответ 3

Существует два этапа, которые мы используем в нашем приложении, это не использование Mobile Network а также not related to roaming.

  1. Сохранение журналов сбоев для записи в разделе данных приложения, то есть на устройстве:

    См. Эту ссылку

  2. Загружать данные о сбоях на сервер при подключении сети WiFi:

    public class ConnectivityStatusReceiver extends BroadcastReceiver {
    
      @Override
      public void onReceive(Context context, Intent intent) {
    
        final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    
        NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();
    
        if (activeNetworkInfo != null && activeNetworkInfo.getTypeName() == "WIFI") {
          // post your crash logs to server
        }
      }
    }
    

Ответ 4

Я читал документы на ткани, и я нашел что-то интересное

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

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

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

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

Чтобы убедиться, что отправка отчетов о сбоях имеет минимальное влияние на ваши пользовательские устройства, максимальный размер журналов Crashlytics составляет 64 КБ. Когда размер журнала превышает 64 КБ, самые ранние зарегистрированные значения будут сброшены для поддержания этого порога.

В заключение, после прочтения документов невозможно отключить сбои для постоянной отправки отчетов, вы можете управлять сетевым подключением пользователя только тогда, когда вы хотите, чтобы он отправлял или не отправлял отчеты. Это как подключение - это включение и выключение аварийных систем в данный момент.

это просто говорит об "Сокращении сетевого трафика", но вовсе не об отключении сети.

Еще один способ, который приходит мне в голову, это сделать флаг для запуска crashlytics, а затем использовать внутри условия Crashlytics.start()

Если вы хотите отключить его, просто сделайте следующее

CrashlyticsCore core = new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build();
Fabric.with(this, new Crashlytics.Builder().core(core).build());

игра с этими двумя вещами - единственный способ, которым я считаю возможным сократить использование сбоев в сети на данный момент

Ответ 5

Вы можете ограничить использование сети Crashlytics статическим полем.

Определите статическую глобальную переменную в соответствии со своей логикой записи значения для вашей Crashlytics.

private static boolean INROAMING = false;

Теперь вы можете использовать ниже логику для своей цели. Например, не предоставляйте co

if(isInternetIsConnected(this).equals("MOBILE")){
        if(INROAMING){
            //write your logic for context here, when phone is in roaming
            //restrict logic for crashlytics
        }else{
            //write your logic for context herem, when phone is not in roaming
            //un-restrict logic for crashlytics
        }
    }

public boolean checkForRoaming() {
        final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        PhoneStateListener phoneStateListener = new PhoneStateListener() {
            @Override
            public void onServiceStateChanged(ServiceState serviceState) {
                super.onServiceStateChanged(serviceState);
                if (telephonyManager.isNetworkRoaming()) {
                    // In Roaming
                    INROAMING = true;
                } else {
                    // Not in Roaming
                    INROAMING = false;
                }
                // You can also check roaming state using this
                if (serviceState.getRoaming()) {
                    // In Roaming
                    INROAMING = true;
                } else {
                    // Not in Roaming
                    INROAMING = false;
                }
            }
        };
    }

    public String isInternetIsConnected(Context context) {
        try {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            assert cm != null;
            @SuppressLint("MissingPermission") NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (activeNetwork != null) { // connected to the internet
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    // connected to wifi
                    return "WIFI";

                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    // connected to the mobile provider data plan
                    checkForRoaming();
                    return "MOBILE";
                }
            } else {
                // not connected to the internet
                return "NO CONNECTION";
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
        return "NO CONNECTION";
    }
}

Ответ 6

Не существует способа ограничить использование Интернета для Crashlytics в приложении. Вы можете дать выбор пользователю, если он предпочитает сохранять отчеты о сбоях локально или отправлять их сразу же через роуминг.

Сохраните ErrorLog локально на устройстве

Загрузите ErrorLog после установления соединения с Wi-Fi.

Вы можете использовать ConnectivityManager для получения состояния сети. Вы можете проверить, подключен ли он или даже доступен.

ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

if (mWifi.isConnected()) {
    // send error logs
}

Выше кода вы можете добавить в broadcastreceiver который будет уведомлять соединение

Пример:

 public class ConnectivityStatusReceiver extends BroadcastReceiver {

 @Override
 public void onReceive(Context context, Intent intent) {

  ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);

  if (mWifi.isConnected()) {
   // send error logs
  }
 }
}