如何检查Android上的互联网访问?InetAddress永远不会超时

Vid*_*nes 637 networking android asynchronous

我有一个AsyncTask应该检查网络访问主机名.但是doInBackground()永远不会超时.有人有线索吗?

public class HostAvailabilityTask extends AsyncTask<String, Void, Boolean> {

    private Main main;

    public HostAvailabilityTask(Main main) {
        this.main = main;
    }

    protected Boolean doInBackground(String... params) {
        Main.Log("doInBackground() isHostAvailable():"+params[0]);

        try {
            return InetAddress.getByName(params[0]).isReachable(30); 
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;       
    }

    protected void onPostExecute(Boolean... result) {
        Main.Log("onPostExecute()");

        if(result[0] == false) {
            main.setContentView(R.layout.splash);
            return;
        }

        main.continueAfterHostCheck();
    }   
}
Run Code Online (Sandbox Code Playgroud)

gar*_*gar 1029

如果设备处于飞行模式(或者可能是在没有可用网络的其他情况下),cm.getActiveNetworkInfo()null需要添加null支票.

修改过(Eddie的解决方案)如下:

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}
Run Code Online (Sandbox Code Playgroud)

还要将以下权限添加到AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

另一个小问题,如果你在给定的时间点绝对需要网络连接,那么最好使用netInfo.isConnected()而不是netInfo.isConnectedOrConnecting.我想这取决于个人用例.

  • 你仍然应该并且需要检查http超时异常,因为可能存在网络连接但没有实际的互联网连接的情况,因为访问它的唯一方法是通过VPN,这样你就有了,例如,WI-FI连接但没有实际的互联网流量.另一种情况是服务器挂起.这是我最近运行的两个问题,连接管理器不会帮助那里. (108认同)
  • 我同意午夜和Pintu,这个答案不应该是接受的答案,它与检查你在互联网上没有任何关系.例如,如果电话连接到具有强制门户的WiFi网络(如在酒店),则此功能将错误地返回true.正确的答案是在公共互联网上ping服务器. (21认同)
  • 当我的路由器没有可用的互联网时,如果我通过wifi连接到路由器,那么上面的代码返回true.但是,它不应该是,对吧?你能帮助我吗 (9认同)
  • 我不得不在`context.getSystemService`中添加Context,否则它不起作用.我在这里得到了线索http://www.androidhive.info/2012/07/android-detect-internet-connection-status/ (5认同)

Lev*_*ite 517

网络连接/互联网访问

  • isConnectedOrConnecting()(在大多数答案中使用)检查任何网络连接
  • 要了解这些网络是否具有Internet访问权限,请使用以下方法之一

A)Ping服务器(简单)

// ICMP 
public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    }
    catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

+ 可以在主线程上运行

- 在某些旧设备(Galays S3等)上不起作用,如果没有可用的互联网,它会阻塞一段时间.

B)连接到Internet上的套接字(高级)

// TCP/HTTP/DNS (depending on the port, 53=DNS, 80=HTTP, etc.)
public boolean isOnline() {
    try {
        int timeoutMs = 1500;
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);

        sock.connect(sockaddr, timeoutMs);
        sock.close();

        return true;
    } catch (IOException e) { return false; }
}
Run Code Online (Sandbox Code Playgroud)

+非常快(无论哪种方式),适用于所有设备,非常可靠

- 无法在UI线程上运行

这在每台设备上都非常可靠,而且速度非常快.它需要在单独的任务中运行(例如ScheduledExecutorServiceAsyncTask).

可能的问题

  • 真的够快吗?

    是的,非常快;-)

  • 没有可靠的方法来检查互联网,除了在互联网上测试一些东西?

    不是我所知,但请告诉我,我会编辑我的答案.

  • 如果DNS关闭怎么办?

    Google DNS(例如8.8.8.8)是世界上最大的公共DNS.截至2013年,它每天为1300亿个请求提供服务.我们只是说,你的应用可能不是当天的话题.

  • 需要哪些权限?

    <uses-permission android:name="android.permission.INTERNET" />
    
    Run Code Online (Sandbox Code Playgroud)

    只是互联网访问 - 惊喜^^(顺便说一句,你有没有想过,如果没有这个许可,这里建议的一些方法甚至可能有一个关于互联网访问的远程胶水?)

 

额外:一次性AsyncTask示例

class InternetCheck extends AsyncTask<Void,Void,Boolean> {

    private Consumer mConsumer;
    public  interface Consumer { void accept(Boolean internet); }

    public  InternetCheck(Consumer consumer) { mConsumer = consumer; execute(); }

    @Override protected Boolean doInBackground(Void... voids) { try {
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();
        return true;
    } catch (IOException e) { return false; } }

    @Override protected void onPostExecute(Boolean internet) { mConsumer.accept(internet); }
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    new InternetCheck(internet -> { /* do something with boolean response */ });
Run Code Online (Sandbox Code Playgroud)

额外:一次性RxJava/RxAndroid示例(Kotlin)

fun hasInternetConnection(): Single<Boolean> {
  return Single.fromCallable {
    try {
      // Connect to Google DNS to check for connection
      val timeoutMs = 1500
      val socket = Socket()
      val socketAddress = InetSocketAddress("8.8.8.8", 53)

      socket.connect(socketAddress, timeoutMs)
      socket.close()

      true
    } catch (e: IOException) {
      false
    }
  }
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
}

///////////////////////////////////////////////////////////////////////////////////
    // Usage

    hasInternetConnection().subscribe { hasInternet -> /* do something */}
Run Code Online (Sandbox Code Playgroud)

  • @Levit这应该是公认的答案.上面的答案只是检查网络n**不是互联网连接**.是的,这是非常快的.谢谢.因此,upvote. (35认同)
  • 这是伟大的代码和平!我发现它在使用预付卡的设备上非常有用!当他们没钱时,他们可以上网,但没有互联网.所以只检查连接是不行的.谢谢! (22认同)
  • 请记住,这种方法是阻塞的,所以你不应该在UI therad中执行它 (10认同)
  • 此解决方案不适用于所有设备.@Salmaan表示,有些设备总是返回2.我测试的设备有互联网连接,ping目标是谷歌DNS服务器 - 它响应ping请求.我认为一些供应商不允许ping请求.例如,我使用三星10.1平板电脑(4.3)进行了测试,解决方案无效.当我通过命令行实用程序运行ping命令时,我收到权限错误.该命令也不适用于模拟器.小心使用此解决方案. (9认同)
  • 这种方法不适用于所有手机.例如在三星Galaxy S3上它失败了.请参阅此处:[为什么ping可以在某些设备上运行而不在其他设备上运行?](http://stackoverflow.com/questions/32749462/why-does-ping-works-on-some-devices-and-not-others) (8认同)
  • @MohammadAfrashteh:正如答案中所述:“据我所知,但让我知道......”互联网“只是”一个相互关联的网络系统,没有单一的最佳方式可以 100% 确定。测试其中一个如此依赖且具有如此强大故障转移能力的 ips 似乎非常接近。这也是一种常见的方式;你有没有访问过 google.com 或类似的网站,看看你是否有互联网? (3认同)
  • @Salmaan:http://www.manpagez.com/man/8/ping/指出:ping实用程序以以下值之一退出:(0)至少从指定主机收到一个响应。(2)传输成功,但是未收到响应。(其他任何值)发生错误。这些值在&lt;sysexits.h&gt;中定义。...简而言之,它意味着ping正常,但是服务器没有响应,或者换句话说:*无Internet连接*(如果设备正在尝试此操作,已连接到互联网:您是否设置了android.permission.INTERNET权限?) (2认同)
  • 这导致我的应用程序在某些设备上出现 ANR (2认同)
  • @Tiago(&Sergii):是的,你是对的!最好的做法是在UI线程上没有任何网络内容(即使在大多数情况下(!)这应该没问题).这个答案只是关于"怎么做",而不是"在哪里" - 只是给那些寻找最佳方法的人起点.我也会建议使用不同的线程!我只是想让这个答案变得简单并专注于主要问题...因为解决方案实际上非常简单. (2认同)
  • @AdilHussain:好点!据我所知,这主要涉及较旧的(!)设备.即便是三星的S4和Note2,也能正常使用这种方法!但是如果你/其他人知道任何有问题的设备,请告诉我,我会在答案中添加一份清单.特别是如果它们比S3更新! (2认同)
  • @ 0xAliHn:您可以尝试**i**nterval开关`/ system/bin/ping -i 0.2 -c 1 8.8.8.8`,现在在请求后等待0.2秒,而不是默认的1秒(更低)值超过200毫秒只允许超级用户使用).除此之外,您还可以构建自己的超时例程.将它放在不同的线程上通常是第一步.例如,从那里您可以在指定时间后发送反馈,以防ping请求尚未完成. (2认同)
  • @mykolaj:大声笑,我希望你在开玩笑^^案例1:如果你到达互联网8.8.8.8也应该可以访问;-)案例2和3:连接检查也是如此.在许多场景中确定检查任何连接都足够了,但是如果你真的想知道是否有互联网...... (2认同)

Edd*_*die 293

不需要复杂.最简单的框架方式是使用ACCESS_NETWORK_STATE权限并只创建一个连接的方法

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    return cm.getActiveNetworkInfo() != null && 
       cm.getActiveNetworkInfo().isConnectedOrConnecting();
}
Run Code Online (Sandbox Code Playgroud)

requestRouteToHost如果您有特定的主机和连接类型(wifi /移动),您也可以使用.

您还需要:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

在你的Android清单中.

  • 最好在cm.getActiveNetworkInfo()级别进行空检查,如果没有可用的活动网络则抛出null. (82认同)
  • 如果您连接到WiFi热点,即使此热点没有互联网连接,此解决方案也会返回true. (8认同)
  • [`getAllNetworkInfo()` 在 API 级别 29 中已弃用](/sf/answers/3747271951/) (2认同)

aze*_*lez 63

要开始getActiveNetworkInfo()工作,您需要将以下内容添加到清单中.

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

  • 你的答案目前不是一个真正的答案,它只是对其他答案的一个相对较小的补充.如果所有其他答案都不在这里,你的回答会有意义吗?并不是的.因为如果最好使用代码扩展你的答案如何使用它,或删除你的答案并在另一个答案中添加信息(你不会失去任何声誉) (3认同)
  • 这不需要INTERNET权限,只需ACCESS_NETWORK_STATE.只有在实际连接到远程位置时才需要INTERNET,而不是查询设备无线电的状态. (2认同)

Chi*_*chi 46

看一下ConnectivityManager类.您可以使用此类来获取有关主机上活动连接的信息.http://developer.android.com/reference/android/net/ConnectivityManager.html

编辑:你可以使用

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) 
Run Code Online (Sandbox Code Playgroud)

要么

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI) 
Run Code Online (Sandbox Code Playgroud)

并解析返回的NetworkInfo对象的DetailedState枚举

编辑编辑:要了解您是否可以访问主机,您可以使用

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .requestRouteToHost(TYPE_WIFI, int hostAddress)
Run Code Online (Sandbox Code Playgroud)

显然,我使用Context.getSystemService(Context.CONNECTIVITY_SERVICE)作为代理来说

ConnectivityManager cm = Context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.yourMethodCallHere();
Run Code Online (Sandbox Code Playgroud)


Gil*_*bou 46

检查这段代码......它对我有用:)

public static void isNetworkAvailable(final Handler handler, final int timeout) {
    // ask fo message '0' (not connected) or '1' (connected) on 'handler'
    // the answer must be send before before within the 'timeout' (in milliseconds)

    new Thread() {
        private boolean responded = false;   
        @Override
        public void run() { 
            // set 'responded' to TRUE if is able to connect with google mobile (responds fast) 
            new Thread() {      
                @Override
                public void run() {
                    HttpGet requestForTest = new HttpGet("http://m.google.com");
                    try {
                        new DefaultHttpClient().execute(requestForTest); // can last...
                        responded = true;
                    } 
                    catch (Exception e) {
                    }
                } 
            }.start();

            try {
                int waited = 0;
                while(!responded && (waited < timeout)) {
                    sleep(100);
                    if(!responded ) { 
                        waited += 100;
                    }
                }
            } 
            catch(InterruptedException e) {} // do nothing 
            finally { 
                if (!responded) { handler.sendEmptyMessage(0); } 
                else { handler.sendEmptyMessage(1); }
            }
        }
    }.start();
}
Run Code Online (Sandbox Code Playgroud)

然后,我定义处理程序:

Handler h = new Handler() {
    @Override
    public void handleMessage(Message msg) {

        if (msg.what != 1) { // code if not connected

        } else { // code if connected

        }   
    }
};
Run Code Online (Sandbox Code Playgroud)

...并启动测试:

isNetworkAvailable(h,2000); // get the answser within 2000 ms
Run Code Online (Sandbox Code Playgroud)

  • @Tom公平,这可能是唯一正确的答案.其他示例仅显示网络连接是否_available_和/或是否存在与该网络的连接,但如果该网络实际上也可以进行_remote连接_(例如,到网站),则不回答该问题.所以这回答了海报Q,其他答案没有 (28认同)
  • 在中国谷歌被封杀!! (16认同)
  • 这项检查毫无意义.如果您要花费系统时间和网络资源来连接到Google,那么您可以将它们用于连接到您真正关心的资源. (10认同)
  • 什么是谷歌?这也需要INTERNET权限,这对于给定的任务是不必要的.最后,这会消耗数据(即使是微不足道的).这看起来就像是一块混合物. (3认同)
  • @dmmh是的,不幸的是,我从Android API中看到了这一点.也许一个简单的ping可能会更好,http://stackoverflow.com/questions/3905358/how-to-ping-external-ip-from-java-android.如果你真的担心你甚至可以列出一个IP列表来ping,因为虽然谷歌的可能性很小,但谷歌,必应和雅虎在同一天失败的可能性更小.只是我的想法. (2认同)

小智 26

在此链接中找到并修改(!):

在您的清单文件中至少添加:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

如果您正在访问它,您可能已经拥有INTERNET权限.然后,允许测试连接的布尔函数是:

private boolean checkInternetConnection() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    // test for connection
    if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {
        return true;
    } else {
        Log.v(TAG, "Internet Connection Not Present");
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `cm.getActiveNetworkInfo().isAvailable()`似乎是多余的. (5认同)

小智 16

我做了这个代码,它是最简单的,它只是一个布尔值.通过询问if(isOnline()){

如果有连接并且它可以连接到页面状态代码200(稳定连接),则会获得.

确保添加正确INTERNETACCESS_NETWORK_STATE权限.

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return new Boolean(true);
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • 也许你应该用HttpURLConnection.HTTP_OK替换200 (6认同)
  • 如果Google失败怎么办? (5认同)
  • 即使我有互联网工作也变得虚假 (2认同)

Mus*_*laa 12

它对我有用:

要验证网络可用性:

private Boolean isNetworkAvailable() {
ConnectivityManager connectivityManager 
      = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();}
Run Code Online (Sandbox Code Playgroud)

验证互联网访问:

public Boolean isOnline() {
    try {
        Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
        int returnVal = p1.waitFor();
        boolean reachable = (returnVal==0);
        return reachable;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • isOnline() 根本不应该在主线程上运行,就好像有 wi-fi 信号但没有互联网它会花费太长时间并阻塞主线程。 (2认同)

Moh*_*aby 9

这不止一种方式

首先,最短但效率低的方式

仅需要网络状态权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

那么这个方法,

 public boolean activeNetwork () {
        ConnectivityManager cm =
                (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnected();

        return isConnected;

    }
Run Code Online (Sandbox Code Playgroud)

如答案所示ConnectivityManager是一个解决方案,我只是在一个方法中添加它这是一个简化的方法
ConnectivityManager如果网络访问不是因特网访问,所有使用返回true,意味着你的WiFi连接到路由器但路由器没有互联网它返回true,它检查连接可用性

第二,有效的方式

需要网络状态和Internet权限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
Run Code Online (Sandbox Code Playgroud)

然后这节课,

 public class CheckInternetAsyncTask extends AsyncTask<Void, Integer, Boolean> {

        private Context context;

        public CheckInternetAsyncTask(Context context) {
            this.context = context;
        }

        @Override
        protected Boolean doInBackground(Void... params) {

            ConnectivityManager cm =
                    (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

            assert cm != null;
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            boolean isConnected = activeNetwork != null &&
                    activeNetwork.isConnected();


            if (isConnected) {
                try {
                    HttpURLConnection urlc = (HttpURLConnection)
                            (new URL("http://clients3.google.com/generate_204")
                                    .openConnection());
                    urlc.setRequestProperty("User-Agent", "Android");
                    urlc.setRequestProperty("Connection", "close");
                    urlc.setConnectTimeout(1500);
                    urlc.connect();
                    if (urlc.getResponseCode() == 204 &&
                            urlc.getContentLength() == 0)
                        return true;

                } catch (IOException e) {
                    Log.e("TAG", "Error checking internet connection", e);
                    return false;
                }
            } else {
                Log.d("TAG", "No network available!");
                return false;
            }


            return null;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            Log.d("TAG", "result" + result);

            if(result){
                // do ur code
            }

        }


    }
Run Code Online (Sandbox Code Playgroud)

呼叫 CheckInternetAsyncTask

new CheckInternetAsyncTask(getApplicationContext()).execute();
Run Code Online (Sandbox Code Playgroud)

一些解释: -

  • 你必须检查互联网AsyncTask,否则它可以抛出android.os.NetworkOnMainThreadException一些情况

  • ConnectivityManager 如果为true,则用于检查网络访问请求(Ping)

  • 请求发送到http://clients3.google.com/generate_204,已知这个众所周知的URL返回一个HTTP状态204的空页面,这比http://www.google.com读取更快,更有效.如果你有网站,只有你在应用程序中使用它,首选你的网站而不是谷歌

  • 超时可以改变范围(20ms - > 2000ms),常用1500ms

  • 很好的问题,它很伤心,你没有更多的积分.这必须是正确的答案. (2认同)

Nic*_*aus 8

到目前为止,我所看到的最短和最干净的方式应该是:

public final static boolean isConnected( Context context )
{   
   final ConnectivityManager connectivityManager = 
         (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );  
   final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();    
   return networkInfo != null && networkInfo.isConnected();
}
Run Code Online (Sandbox Code Playgroud)

PS:这不会ping任何主机,它只是检查connectionstatus,所以如果您的路由器没有互联网连接并且您的设备已连接到它,这种方法将返回true,尽管您没有互联网.
对于实际测试,我建议执行HttpHead请求(例如,到www.google.com)并检查状态,如果它的200 OK一切正常并且您的设备有互联网连接.


Jar*_*ows 8

这是我使用的方法:

public boolean isNetworkAvailable(final Context context) {
    return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo() != null;
}
Run Code Online (Sandbox Code Playgroud)

更好的是,检查以确保它"连接":

public boolean isNetworkAvailable(final Context context) {
    final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
    return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}
Run Code Online (Sandbox Code Playgroud)

以下是如何使用该方法:

if (isNetworkAvailable(context)) {
    // code here
} else {
    // code
}
Run Code Online (Sandbox Code Playgroud)

需要许可:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

/sf/answers/1128744081/


use*_*493 7

移动设备上的一个重要用例是确保存在实际连接.当移动用户进入具有"强制门户"的Wifi网络时,这是一个常见问题,他们需要登录.我在后台使用此阻止功能以确保存在连接.

/*
 * Not Thread safe. Blocking thread. Returns true if it
 * can connect to URL, false and exception is logged.
 */
public boolean checkConnectionHttps(String url){
    boolean responded = false;
    HttpGet requestTest = new HttpGet(url);
    HttpParams params = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 5000);
    DefaultHttpClient client = new DefaultHttpClient(params);
    try {
        client.execute(requestTest);
        responded = true;
    } catch (ClientProtocolException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
    } catch (IOException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
        e.printStackTrace();
    }
    return responded;
}
Run Code Online (Sandbox Code Playgroud)

  • 实际检查端到端连接的+1.然而,对于"强制门户"情况,我发现许多人即使你还没有登录也会通过上述测试 - 无论你要求什么网址,你都会获得登录页面和200响应.所以我尝试在我自己的域上打一个我知道不存在的页面,并确保我得到一个404.或者,你可以点击一个已知的现有页面,确保你得到一个200,并检查内容返回以确保它是您所期望的. (3认同)

Haw*_*ike 7

Kotlin 和协程

我已将该函数放在 a 中ViewModel,该函数具有viewModelScope. 使用 observableLiveData通知活动有关连接的信息。

视图模型

 fun checkInternetConnection(timeoutMs: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                val socket = Socket()
                val socketAddress = InetSocketAddress("8.8.8.8", 53)

                socket.connect(socketAddress, timeoutMs)
                socket.close()

                _connection.postValue(true)
            }
            catch(ex: IOException) {
                _connection.postValue(false)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)
 private val _connection = MutableLiveData<Boolean>()
 val connection: LiveData<Boolean> = _connection
Run Code Online (Sandbox Code Playgroud)

活动

 private fun checkInternetConnection() {
     viewModel.connection.observe(this) { hasInternet ->
         if(!hasInternet) {
             //hasn't connection
         }
         else {
            //has connection
         }
     }
  }
Run Code Online (Sandbox Code Playgroud)


Emr*_*ici 6

您可以遍历所有网络连接并判断是否至少有一个可用连接:

public boolean isConnected() {
    boolean connected = false;

    ConnectivityManager cm = 
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    if (cm != null) {
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {
            if ((ni.getTypeName().equalsIgnoreCase("WIFI")
                    || ni.getTypeName().equalsIgnoreCase("MOBILE"))
                    && ni.isConnected() && ni.isAvailable()) {
                connected = true;
            }

        }
    }

    return connected;
}
Run Code Online (Sandbox Code Playgroud)


sel*_*chi 6

它对我有用.试试看.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        URL url = new URL("http://stackoverflow.com/posts/11642475/edit" );
        //URL url = new URL("http://www.nofoundwebsite.com/" );
        executeReq(url);
        Toast.makeText(getApplicationContext(), "Webpage is available!", Toast.LENGTH_SHORT).show();
    }
    catch(Exception e) {
        Toast.makeText(getApplicationContext(), "oops! webpage is not available!", Toast.LENGTH_SHORT).show();
    }
}

private void executeReq(URL urlObject) throws IOException
{
    HttpURLConnection conn = null;
    conn = (HttpURLConnection) urlObject.openConnection();
    conn.setReadTimeout(30000);//milliseconds
    conn.setConnectTimeout(3500);//milliseconds
    conn.setRequestMethod("GET");
    conn.setDoInput(true);

    // Start connect
    conn.connect();
    InputStream response =conn.getInputStream();
    Log.d("Response:", response.toString());
}}
Run Code Online (Sandbox Code Playgroud)


HiB*_*HiB 6

对我来说,检查Activity类中的连接状态不是一个好习惯,因为

ConnectivityManager cm =
    (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
Run Code Online (Sandbox Code Playgroud)

应该在那里调用,或者你需要将你的Activity实例(上下文)下推到连接处理程序类,以便能够检查那里的连接状态当没有可用的连接(wifi,网络)时,我捕获了UnknownHostException异常:

JSONObject jObj = null;
Boolean responded = false;
HttpGet requestForTest = new HttpGet("http://myserver.com");
try {
    new DefaultHttpClient().execute(requestForTest);
    responded = true;
} catch (UnknownHostException e) {
    jObj = new JSONObject();
    try {
        jObj.put("answer_code", 1);
        jObj.put("answer_text", "No available connection");
    } catch (Exception e1) {}
    return jObj;
} catch (IOException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,我可以处理这种情况以及同一类中的其他情况(我的服务器总是以json字符串回复)


Kni*_*ins 6

该方法为您提供了一种非常快速的方法(用于实时反馈)或一种较慢的方法(用于需要可靠性的一次性检查)的选项。

public boolean isNetworkAvailable(bool SlowButMoreReliable) {
    bool Result = false; 
    try {
        if(SlowButMoreReliable){
            ConnectivityManager MyConnectivityManager = null;
            MyConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo MyNetworkInfo = null;
            MyNetworkInfo = MyConnectivityManager.getActiveNetworkInfo();

            Result = MyNetworkInfo != null && MyNetworkInfo.isConnected();

        } else
        {
            Runtime runtime = Runtime.getRuntime();
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");

            int i = ipProcess.waitFor();

            Result = i== 0;

        }

    } catch(Exception ex)
    {
        //Common.Exception(ex); //This method is one you should have that displays exceptions in your log
    }
    return Result;
}
Run Code Online (Sandbox Code Playgroud)


Vid*_*nes 5

我使用此代码而不是InetAddress:

    try {

        URL url = new URL("http://"+params[0]);

        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
        urlc.setRequestProperty("User-Agent", "Android Application:"+Z.APP_VERSION);
        urlc.setRequestProperty("Connection", "close");
        urlc.setConnectTimeout(1000 * 30); // mTimeout is in seconds
        urlc.connect();
        if (urlc.getResponseCode() == 200) {
            Main.Log("getResponseCode == 200");
            return new Boolean(true);
        }
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
Run Code Online (Sandbox Code Playgroud)


小智 5

检查Android网络/互联网连接状态并不复杂.以下DetectConnection课程将帮助您检查此状态:

import android.content.Context;
import android.net.ConnectivityManager;

public class DetectConnection {
    public static boolean checkInternetConnection(Context context) {
        ConnectivityManager con_manager = (ConnectivityManager) context
                                .getSystemService(Context.CONNECTIVITY_SERVICE);

        if (con_manager.getActiveNetworkInfo() != null
            && con_manager.getActiveNetworkInfo().isAvailable()
            && con_manager.getActiveNetworkInfo().isConnected()) {
                return true;
        } else {
            return false;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请访问 如何检查Android网络/ Internet连接状态


小智 5

最佳方法:

public static boolean isOnline() {
    try {
    InetAddress.getByName("google.com").isReachable(3);

    return true;
    } catch (UnknownHostException e){
    return false;
    } catch (IOException e){
    return false;
    }
    }
Run Code Online (Sandbox Code Playgroud)

  • 但是,isReachable使用ICMP,它可能需要root权限并使用端口7,它通常在最新系统上没有运行服务.因此,检查到在线服务的路由的最佳方法是通过常规TCP; 因此投票率下降. (2认同)

Mah*_*iya 5

以下是我Utils班上的代码:

public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager 
              = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
Run Code Online (Sandbox Code Playgroud)


use*_*903 5

public class Network {

Context context;

public Network(Context context){
    this.context = context;
}

public boolean isOnline() {
    ConnectivityManager cm =
            (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null &&
                          activeNetwork.isConnectedOrConnecting();
}

}
Run Code Online (Sandbox Code Playgroud)


Aks*_*wal 5

您可以使用此方法检测网络可用性 -

public static boolean isDeviceOnline(Context context) {
        boolean isConnectionAvail = false;
        try {
            ConnectivityManager cm = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            return netInfo.isConnected();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isConnectionAvail;
    }
Run Code Online (Sandbox Code Playgroud)


kre*_*ker 5

这在 android 文档 http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html 中有介绍

  • 但那里描述的方法并没有真正检查互联网连接,它只是检查是否建立了连接(是否可以访问互联网)。该官方文档的标题确实具有误导性。 (2认同)
  • 给出问题的答案比仅仅发布信息链接要好。如果链接失效了怎么办?我们将没有答案。 (2认同)

Jor*_*sys 5

检查我们是否与isAvailable()连接以及是否可以与isConnected()建立连接非常重要

private static ConnectivityManager manager;

public static boolean isOnline(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected();
}
Run Code Online (Sandbox Code Playgroud)

您可以确定网络活动WiFi的类型:

public static boolean isConnectedWifi(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
}
Run Code Online (Sandbox Code Playgroud)

或移动Móvil

public static boolean isConnectedMobile(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
}
Run Code Online (Sandbox Code Playgroud)

不要忘记权限:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
   <uses-permission android:name="android.permission.INTERNET" />
Run Code Online (Sandbox Code Playgroud)


Jay*_*hal 5

我已经应用了@Levit提供的解决方案并创建了不会调用额外Http请求的函数.

它将解决错误 Unable to Resolve Host

public static boolean isInternetAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork == null) return false;

    switch (activeNetwork.getType()) {
        case ConnectivityManager.TYPE_WIFI:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        case ConnectivityManager.TYPE_MOBILE:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        default:
            return false;
    }
    return false;
}

private static boolean isInternet() {

    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int exitValue = ipProcess.waitFor();
        Debug.i(exitValue + "");
        return (exitValue == 0);
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }

    return false;
}
Run Code Online (Sandbox Code Playgroud)

现在称之为,

if (!isInternetAvailable(getActivity())) {
     //Show message
} else {
     //Perfoem the api request
}
Run Code Online (Sandbox Code Playgroud)