networking - 安卓如何检查internet访问?

  显示原文与译文双语对照的内容

我得到一个 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();
 } 
}

时间:

@Eddie. 只是对解决方案的一个小编辑- 如果设备处于飞行模式( 或者在没有可用网络的情况下),cm.getActiveNetworkInfo() 将是 null,所以你需要添加 null 检查。

修改后的解决方案如下:


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

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


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

另外一点,如果你绝对需要在给定时间点进行网络连接,那么最好使用 netInfo.isConnected() 而不是 netInfo.isConnectedOrConnecting 。 我想这取决于 indivudal use-case 。

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


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

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

你还可以使用 requestRouteToHost mind,中如果你有一个particualr主机和连接类型

你还需要:


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

在你的android清单中。

要使 getActiveNetworkInfo() 工作,你需要将以下内容添加到清单中。


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

检查这里代码。。它为我工作:)


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();
}

然后,我定义处理程序:


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

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

 } else {//code if connected

 } 
 }
};

然后启动测试:


isNetworkAvailable(h,2000);//get the answser within 2000 ms

你想要什么?

  • 如果你只想检查是否有一个连接到任何可用网络 - 不关怀如果互联网是- 那么这里大部分的答案实现 isConnectedOrConnecting() ( 包括被接受的),将很好地工作。
  • 现在,如果你想上如果你有一个互联网连接 ( 题目标题表示) 请阅读

主名称服务器的Ping


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

就是这样是的,简短,是快速的,不需要在后台运行,不需要根特权。

可能的问题

  • 真的够快了?

    是的,非常快 !

  • 除了测试互联网上的东西之外,没有可靠的方法来检查是否有互联网可用?

    我知道,但我知道,我会编辑我的答案。

  • 我不能直接ping我自己的页面,我想请求它?

    当然你甚至可以检查两者,如果你想区分"互联网连接可用"和你自己的服务器 !

  • 如果DNS被关闭怎么办?

    谷歌 DNS ( e.g 。8.8.8.8 ) 是世界上最大的公共DNS服务。 截至 2013年,它每天提供 130亿请求。 比如说,你的应用不响应可能不是对一天的讨论。

  • 需要哪些权限?

    
    <uses-permission android:name="android.permission.INTERNET"/>
    
    

    只要互联网接入- 什么惊喜 ^^ ( 顺便说一句你是否曾想过关于,怎么可能这里建议的一些方法甚至可以有远程胶水关于互联网的availablility 。不具有该权限)?

并在调节( ) 从此链接, found: !

在清单文件中添加至少:


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

如果你访问它,你可能已经拥有了互联网权限。 然后,允许测试连接性的布尔函数是:


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

这段代码,它是最简单的,它只是一个布尔。 通过询问 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;
}

所有我看到的最短和最干净的方式应该是:


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();
}

PS: 这不会ping任何主机,只是检查 ConnectionStatus,所以如果你的路由器没有互联网连接,你的设备将返回 ,尽管你没有互联网。
对于一个实际的测试,我推荐execuding一个HttpHead请求 。 到 www.google.com) 并检查状态,如果它 200 ok,一切都正常,你的设备有互联网连接。

...