后台IntentService Force关闭,因为设备已连接到WiFi但未经过身份验证

时间:2013-08-29 18:31:01

标签: android android-wifi wifimanager

我目前在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在您通过导航到浏览器页面并接受其使用条款和协议来伪登录之前,不会让您传输任何数据

3 个答案:

答案 0 :(得分:0)

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

因此,您不会拥有intentService的force close约束,它应该可以正常工作。

编辑:

好的,明白了!以下是您可以做的事情,以确保用户可以访问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中。但我确切地说可能会看到这个帖子。顺便提一下,我建议你改变这个帖子的标题,因为实际问题与服务没有关系,而是与互联网的访问权限有关。

以下是参考:Test Internet Connection Android

我希望这会有所帮助。

答案 1 :(得分:0)

方法conMgr.getActiveNetworkInfo()调用ConnectivityService,此调用的结果可以是null。在(conMgr.getActiveNetworkInfo() != null && conMgr.getActiveNetworkInfo().isAvailable() && conMgr.getActiveNetworkInfo().isConnected())声明中,您拨打了三次电话。我怀疑这里可以有NPE,因为当时网络从3g变为WiFi,这些呼叫之一可以返回null。如果您首先获得NetworkInfo实例,并且在其上调用isAvailable()isConnected()(类似于您在WifiConnected()中的操作方式),该怎么办?

答案 2 :(得分:0)

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

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />