首页 文章

Android Crashlytics - 限制网络访问

提问于
浏览
19

我一直在努力解决在某些条件下限制Crashlytics网络使用的问题 . 例如 - 漫游,计量网络等等 .

根据SDK文档,我发现只有两个选项可以解决这个问题:

只需不初始化Crashlytics就可以在运行时“退出”

发送崩溃报告之前

  • 内置用户同意对话框

这个API非常有限,因为:

  • 未初始化Crashlytics不仅会阻止网络访问,还会阻止Crashlytics在本地保存崩溃报告,以便最终发送事件 . 更不用说除了粗暴地重写Thread.setUncaughtExceptionHandler之外没有好的方法可以在运行时选择退出

如果在后台发生崩溃,

  • 同意对话框对用户没有任何意义 .

我的问题基本上是:我错过了什么?有没有办法限制Crashlytics网络访问?

我的动机来自需要防止我的应用程序使用网络带宽可能会在某些条件下花费给用户的钱,尽管“蜂窝网络”或“使用漫游时使用数据”设备设置已启用 .

6 回答

  • 7

    我是iOS / macOS的Crashlytics SDK的前维护者 . 我对Android的Android版本比较陌生,一般不熟悉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的 Contract ,必须禁用一些提高报告可靠性的技术 . 问题是,有时值得 . 许多应用决定做出这种权衡 . 许多应用程序还会延迟初始化Crashlytics以获得额外的性能 . 这对报告可靠性有一定的影响,但这是开发人员必须做出的另一个权衡应用 .

    我认为你应该认真考虑在这些情况下不启用Crashlytics,如果你能轻易检测到它们 . 也许Android甚至允许最终用户在每个应用程序的基础上执行此操作?在这种情况下,你永远不会得到任何报告 . 我想你的用户群足够多,在这些情况下丢失一些报告并不会那么糟糕 . 或者,您可能希望将其表现为面向用户的选项 .

    你甚至可以做一些完全疯狂的事情,比如自己覆盖 Thread.setUncaughtExceptionHandler ,并在这种情况下将异常缓冲到磁盘 . 然后,当事情变得更好时,将它们重播到Crashlytics . 把它变成一个开源的lib . 我打赌人们会喜欢它!可能不是Crashlytics的Android团队;)(嗨!)

    这也与上面提到的Gastón提出的建议基本相同,仅仅是我在iOS方面看到的一些额外背景 . 还要向Crashlytics人员发送电子邮件,询问此事 . 我认为这是一个好主意 .

  • 6

    没有办法在应用程序中限制Crashlytics的互联网使用 . 但我如何解决这个问题的方法是向用户提供Crashlytics正在使用漫游的信息,或者只是在本地保存崩溃报告,并在用户连接到wifi网络后发送它们 . 如果他喜欢在本地保存崩溃报告或者通过漫游立即发送它们,您也可以给用户选择 .

    您应该能够使用ConnectivityManager来获取Wi-Fi适配器的状态 . 从那里你可以check if it is connected or even available .

    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 .

    • Saving crash logs to file in app data partition i.e. on device

    请参阅link

    • Upload crash data to server when WiFi network is connected
    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
        }
      }
    }
    
  • 6

    我正在阅读面料的文档,我发现了一些有趣的东西

    Crashlytics在专用背景上处理异常线程,因此对您的应用程序的性能影响很小 . 为了减少用户的网络流量,Crashlytics将记录的异常一起批处理,并在下次启动应用程序时发送 .

    所以我正在考虑一种解决方法,因为在初始化应用程序时发送没有网络的崩溃,你可以在启动时向用户提示任何对话框,告诉用户是否要连接到互联网以发送崩溃报告以解决当前问题 . 应用程序 . (所以你在用户同意的情况下使用他们的网络数据)

    这里的事情是我们不知道如何阻止crashlytics发送此报告,如果设备处于脱机状态,它们会将其存储在设备上,并在设备刚刚再次连接后将其发回,因为它声明here

    另一种方法可能只是通过他们提供的自定义登录来记录重要的致命问题并发送它们,你可以找到更多关于它here

    为确保发送崩溃报告对用户设备的影响最小,Crashlytics日志的最大大小为64 KB . 当日志超过64 KB时,将删除最早记录的值以保持此阈值 .

    总之,在阅读文档后,没有办法禁用崩解剂来不断发送报告,您只能管理用户发送或不发送报告时的网络连接 . 它的连接就像是目前崩溃关闭的开关

    它只谈到“减少网络流量”,而不是关于禁用崩溃网络 .

    我想到的另一种方法是制作一个开始碰撞的旗帜,然后在一个条件内使用 Crashlytics.start()

    如果要禁用它,请执行以下操作

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

    玩这两件事是我认为现在可以减少崩溃的网络使用的唯一方法

  • 3

    您可以通过静态字段限制Crashlytics网络使用 .

    根据Crashlytics的值写入逻辑,定义静态全局变量 .

    private static boolean INROAMING = false;
    

    现在您可以使用以下逻辑来实现您的目的 . 喜欢不提供合作

    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's data plan
                        checkForRoaming();
                        return "MOBILE";
                    }
                } else {
                    // not connected to the internet
                    return "NO CONNECTION";
                }
            } catch (Exception e) {
                e.printStackTrace();
    
            }
            return "NO CONNECTION";
        }
    }
    
  • 5

    没有办法在应用程序中限制Crashlytics的互联网使用 . 如果用户希望在本地保存崩溃报告或立即通过漫游将其发送,您可以选择用户 .

    Save the ErrorLog locally on the device

    一旦 Build 了与wifi的连接,就上传ErrorLog .

    您可以使用 ConnectivityManager 来获取网络状态 . 您可以检查它是否已连接或甚至可用 .

    ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    
    if (mWifi.isConnected()) {
        // send error logs
    }
    

    Above code you can add in broadcastreceiver which will notify connection

    例:

    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
      }
     }
    }
    

相关问题