0

我目前在我的 Android 应用程序中使用后台 IntentService 连接到我的服务器以获取一些数据并仅在连接可用时更新应用程序。如果设备连接到移动网络数据或经过身份验证的 wifi 连接或打开的 wifi 连接,它可以完美运行。

当设备无法访问移动数据网络并连接到需要身份验证的 Wifi 源并且连接尚未经过身份验证时,会出现问题,服务强制关闭,因为它无法通过未经身份验证的连接传输任何数据。

我对入口点的检查以连接到服务器并执行后台任务是下面的检查。

ConnectivityManager conMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        if((conMgr.getActiveNetworkInfo() != null &&
                conMgr.getActiveNetworkInfo().isAvailable() &&
                conMgr.getActiveNetworkInfo().isConnected()) || WifiConnected() == true){

//做后台处理 }

WifiConnected() 方法如下所示。

private boolean WifiConnected() {
            ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                    NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 
                    SupplicantState supState; 
                    WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
                    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                    supState = wifiInfo.getSupplicantState();
                    return (networkInfo != null && networkInfo.isConnected() && supState.toString().contentEquals("COMPLETED"));
        }

所以基本上我在执行后台任务之前检查的是设备是否具有活动的网络连接并已连接,或者连接是否为 wifi,如果该连接已完成身份验证,以便可以进行数据传输。

这似乎不起作用,也失败了,使服务仍然强制关闭。

当涉及wifi身份验证然后进行后台处理时,检查网络连接的正确方法是什么?

谢谢。

这个问题的一个很好的例子是,当您在全国任何一家星巴克时,您的 android 设备将自动连接到 attwifi 并且 wifi 状态更改为已连接,因为我检查 isConnected 返回 true 但您会注意到星巴克的 attwifi 不会让您传输任何数据,直到您通过导航到浏览器页面并接受他们的使用条款和协议来伪登录

4

3 回答 3

0

方法conMgr.getActiveNetworkInfo()调用 ConnectivityService 并且此调用的结果可以是null. 在声明中(conMgr.getActiveNetworkInfo() != null && conMgr.getActiveNetworkInfo().isAvailable() && conMgr.getActiveNetworkInfo().isConnected()),您调用了 3 次。我怀疑这里可能存在 NPE,因为null如果当时网络从 3g 更改为 WiFi,其中一个调用可能会返回。如果您首先获得 NetworkInfo 实例,然后他们调用isAvailable()isConnected()在其上调用(类似于您在 中的做法WifiConnected())怎么办?

于 2013-08-29T20:41:51.500 回答
0

您可以在您的活动(或您拥有上下文的任何其他地方)中移动连接检查并从那里启动服务。

因此,您不会有 intentService 的强制关闭约束,它应该可以正常工作。

编辑:

好的,我知道了!您可以执行以下操作来确保用户可以访问 Internet:

private boolean hasInternetAccess() {
    boolean hasInternetAccess = false;
    try {
            //I set google but you can try anything "reliable"...
            //isReachable(1) the timeout in seconds
        hasInternetAccess = InetAddress.getByName("www.google.com").isReachable(1);                         

    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return hasInternetAccess;
}

所以你的支票变成:

If(WifiConnected() && hasInternetAccess()){
  //Do background Work...
}

这是做某种 ping 以确保用户有互联网。不要忘记此方法需要在单独的线程中执行,否则会抛出 NetworkOnMainthreadException。在这里你是安全的,因为你在一个有自己的线程的 IntentService 中。但我对那些可能会看到这个线程的人来说是精确的。顺便说一句,我建议您更改此线程的标题,因为实际问题与服务无关,而是与互联网的访问有关。

这是参考:测试 Internet 连接 Android

我希望这有帮助。

于 2013-08-29T19:33:56.833 回答
0

或者您可以为连接更改编写接收器。在你的情况下这将是最好的。

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
于 2015-04-14T11:03:53.660 回答