如何在Android上检查互联网接入?InetAddress永远不会超时

我有一个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();
}
}
508324 次浏览

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

编辑:您可以使用

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
.getNetworkInfo(ConnectivityManager.TYPE_WIFI)

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

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

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
.requestRouteToHost(TYPE_WIFI, int hostAddress)

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

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

我使用此代码而不是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();
}

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

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


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

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

您还需要:

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

在你的Android清单中。

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

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

如果设备处于飞行模式(或者可能在没有可用网络的其他情况下),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可能更好。然而,我想这取决于单个用例。

链接找到并修改(!):

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

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

如果您正在访问它,您可能已经拥有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;
}
}

检查此代码…它对我有用:)

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
public boolean isOnline() {
boolean var = false;
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if ( cm.getActiveNetworkInfo() != null ) {
var = true;
}
return var;
}

我就是这样做的。 我想短一点,更易读。

干杯!

赛亚人

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

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

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

更多详情请访问 如何检查Android网络/Internet连接状态

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

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

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任何主机,它只是检查连接状态,因此如果您的路由器没有互联网连接并且您的设备已连接到它,则此方法将返回真正,尽管您没有互联网。
对于实际测试,我建议执行HttpHead请求(例如www.google.com)并检查状态,如果它的200 OK一切正常并且您的设备具有Internet连接。

对我来说,检查活动类中的连接状态不是一个好的做法,因为

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

应该在那里调用,或者您需要将活动实例(上下文)下推到连接处理程序类,以便能够检查那里的连接状态 当没有可用的连接(wifi,网络)时,我抓住了未知错误异常:

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

通过这种方式,我可以将这种情况与同一类中的其他情况一起处理(我的服务器总是用json字符串响应)

最佳方法:

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


return true;
} catch (UnknownHostException e){
return false;
} catch (IOException e){
return false;
}
}

以下是我的Utils类的代码:

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

移动设备上的一个重要用例是确保实际连接存在。当移动用户使用“Captive Portal”进入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;
}

以下是我使用的方法:

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

更好的是,检查以确保它已“连接”:

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

以下是如何使用该方法:

if (isNetworkAvailable(context)) {
// code here
} else {
// code
}

需要权限:

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

https://stackoverflow.com/a/16124915/950427

public static boolean isNetworkAvailable(Context ctx) {
ConnectivityManager connMgr = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
if(connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected() ||
connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnected()){
return true;
}


return false;
}

使用此

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


}

更新29/06/2015 如果您使用的是Xamarin. Android并希望检查连接性,您可以使用Nuget包,该包将在多个平台上为您提供此功能。不错的候选者是这里这里。 [更新结束]

上面的答案都很好,但它们都在Java,几乎所有人都检查连接。在我的情况下,我需要与特定类型的连接具有连接性,我正在Xamarin. Android上开发。此外,我不会在硬件层传递对我的活动上下文的引用,我使用应用程序上下文。所以这是我的解决方案,以防有人有类似的要求。不过,我还没有进行完整的测试,一旦我测试完成,将更新答案

using Android.App;
using Android.Content;
using Android.Net;


namespace Leopard.Mobile.Hal.Android
{
public class AndroidNetworkHelper
{
public static AndroidNetworkStatus GetWifiConnectivityStatus()
{
return GetConnectivityStatus(ConnectivityType.Wifi);
}


public static AndroidNetworkStatus GetMobileConnectivityStatus()
{
return GetConnectivityStatus(ConnectivityType.Mobile);
}


#region Implementation


private static AndroidNetworkStatus GetConnectivityStatus(ConnectivityType connectivityType)
{
var connectivityManager = (ConnectivityManager)Application.Context.GetSystemService(Context.ConnectivityService);
var wifiNetworkInfo = connectivityManager.GetNetworkInfo(connectivityType);
var result = GetNetworkStatus(wifiNetworkInfo);
return result;
}


private static AndroidNetworkStatus GetNetworkStatus(NetworkInfo wifiNetworkInfo)
{
var result = AndroidNetworkStatus.Unknown;
if (wifiNetworkInfo != null)
{
if (wifiNetworkInfo.IsAvailable && wifiNetworkInfo.IsConnected)
{
result = AndroidNetworkStatus.Connected;
}
else
{
result = AndroidNetworkStatus.Disconnected;
}
}
return result;
}


#endregion
}


public enum AndroidNetworkStatus
{
Connected,
Disconnected,
Unknown
}

使用ConnectivityManager的其他答案是错误的,因为拥有网络连接并不意味着您可以访问Internet。例如,用户可能连接到咖啡店的WiFi门户,但无法访问Internet。要检查Internet是否可访问,您必须尝试连接到实际服务器。通常,当您想要执行此操作时,您心中有一个要连接到的特定服务器,因此请继续检查您是否可以连接到该服务器。这里有一个检查与服务器连接的简单方法。

private boolean isOnTheInternet() {
try {
URLConnection urlConnection = new URL("http://yourserver").openConnection();
urlConnection.setConnectTimeout(400);
urlConnection.connect();
return true;
} catch (Exception e) {
return false;
}
}

设置ConnectTimeout的原因是,否则它默认为TCP超时,可能长达数秒。

另请注意,Android不会让您在主线程上运行它。

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

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

它为我工作:

验证网络可用性:

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

验证互联网访问:

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

有更多的编码方式真是太好了。 这是我的例子。

ConnectivityManager icheck = getSystemService(Context.CONNECTIVITY_SERVICE);


TextView tv = findViewById(R.id.textView1);


boolean wifi = icheck.getActiveNetworkInfo() != null;
if(wifi) {
tv.setText("Internet is on.");
} else {
tv.setText("Internet is off.");
}

祝你好运。

只需创建以下类来检查Internet连接:

public class ConnectionStatus {


private Context _context;


public ConnectionStatus(Context context) {
this._context = context;
}


public boolean isConnectionAvailable() {
ConnectivityManager connectivity = (ConnectivityManager) _context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity != null) {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
for (int i = 0; i < info.length; i++)
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
return false;
}
}

此类只包含一个返回连接状态布尔值的方法。因此,简单来说,如果该方法找到与Internet的有效连接,则返回值为true,否则如果没有找到有效连接,则返回值为false

MainActivity中的以下方法然后调用前面描述的方法的结果,并提示用户相应地采取行动:

public void addListenerOnWifiButton() {
Button btnWifi = (Button)findViewById(R.id.btnWifi);


iia = new ConnectionStatus(getApplicationContext());


isConnected = iia.isConnectionAvailable();
if (!isConnected) {
btnWifi.setOnClickListener(new View.OnClickListener() {


@Override
public void onClick(View v) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
Toast.makeText(getBaseContext(), "Please connect to a hotspot",
Toast.LENGTH_SHORT).show();
}
});
}
else {
btnWifi.setVisibility(4);
warning.setText("This app may use your mobile data to update events and get their details.");
}
}

在上面的代码中,如果结果为假,(因此没有互联网连接,用户将被带到Android Wi-Fi面板,在那里提示他连接到Wi-Fi热点。

网络连接/互联网接入

  • isConnectedOrConnecting()(用于大多数答案)检查任何网络连接
  • 要知道这些网络是否具有互联网访问权限,请使用以下方法之一

A)ping a Server(简单)

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

+可以在主线程上运行

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

B)连接到Internet上的Socket(高级)

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

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

-无法在UI线程上运行

这在每台设备上都非常可靠,并且非常快。不过,它需要在单独的任务中运行(例如ScheduledExecutorServiceAsyncTask)。

建议问题

  • 真的快吗?

    是的,非常快;-)

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

    据我所知没有,但让我知道,我会编辑我的答案。

  • 如果DNS关闭了怎么办?

    谷歌DNS(例如8.8.8.8)是世界上最大的公共DNS。截至2018年,它每天处理超过万亿次查询[1]。假设,你的应用程序可能不会成为当天的话题。

  • 需要哪些权限?

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

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

 

额外:One-shotRxJava/RxAndroid示例(静态编程语言)

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

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

public static Single<Boolean> hasInternetConnection() {
return Single.fromCallable(() -> {
try {
// Connect to Google DNS to check for connection
int timeoutMs = 1500;
Socket socket = new Socket();
InetSocketAddress socketAddress = new InetSocketAddress("8.8.8.8", 53);


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


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


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


hasInternetConnection().subscribe((hasInternet) -> {
if(hasInternet) {


}else {


}
});

额外:One-shotAsyncTask示例

警告:这显示了如何执行请求的另一个示例。但是,由于AsyncTask已弃用,它应该替换为应用程序的线程调度、静态编程语言Coroutines、Rx、…

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 */ });

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

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;
}
if(isConnected()){
Toast.makeText(getApplication(),"Thank you",Toast.LENGTH_SHORT).show();
}
else{


AlertDialog.Builder builder =
new AlertDialog.Builder(this, R.style.AppCompatAlertDialogStyle);
builder.setTitle("Amar Bhat");
builder.setMessage("Oops...You are not connected to Internet!!!");
builder.setPositiveButton("OK", null);
builder.setNegativeButton("Cancel", null);
builder.show();
//Toast.makeText(getApplication(),"You are not connected",Toast.LENGTH_SHORT).show();
}








//And outside the class define isConnected()


public boolean isConnected(){
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected())
return true;
else
return false;
}


// In minifest add these permission
<uses-permission android:name="android.permission.INTERNET" />


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

不要忘记将此权限添加到您的清单中:

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

此代码将帮助您找到互联网是否打开。

public final boolean isInternetOn() {
ConnectivityManager conMgr = (ConnectivityManager) this.con
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = conMgr.getActiveNetworkInfo();
return (info != null && info.isConnected());
}

此外,您应该提供以下权限

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

这个线程中的大多数答案只检查是否有可用的连接,但不检查该连接是否有效,其他答案不是设备范围的,我的解决方案应该适用于每个设备。

您可以在启动应用程序之前在您的主要活动中删除我的代码,它将快速确定是否有实际的互联网连接,如果有对话框将立即删除并启动应用程序,如果没有警报会弹出说应用程序需要互联网连接才能工作。

final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Checking Connection");
alertDialog.setMessage("Checking...");
alertDialog.show();
new CountDownTimer(5000, 1000) {
@Override
public void onTick(long millisUntilFinished) {


new Thread(new Runnable() {
public void run() {
try {
URL url = new URL("http://web.mit.edu/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
isConnected = connection.getResponseCode() == HttpURLConnection.HTTP_OK;
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();


if (isConnected == false){
alertDialog.setMessage("Try " +  (5 - millisUntilFinished/1000) + " of 5.");
} else {
alertDialog.dismiss();
}
}
@Override
public void onFinish() {
if (isConnected == false) {
alertDialog.dismiss();
new AlertDialog.Builder(activity)
.setTitle("No Internet")
.setMessage("Please connect to Internet first.")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// kill the app?
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
} else {
// Launch the app
}
}
}.start();
public boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

以下是您需要的权限:

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

您也可以使用以下代码检查互联网:

 public class CheckInternetConnection {
public Context context = null;


public CheckInternetConnection(Context ctx) {
this.context = ctx;
}


public boolean CheckInternet() {
return isOnline();
}
public Boolean isOnline()
{
try {
if(isNetAvailable(context))
return true;
else
{
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlc = (HttpURLConnection) url
.openConnection();
urlc.setRequestProperty("User-Agent", "Test");
urlc.setRequestProperty("Connection", "close");
urlc.setConnectTimeout(3000); // This is time limit if the
// connection time limit
try {
urlc.connect();
Log.e("TAG", " urlc ----------" + urlc.getResponseCode());
if (urlc.getResponseCode() == 200) {
return true;
}
}catch (Exception e){
e.printStackTrace();
}
} catch (MalformedURLException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}catch (Exception e){
e.printStackTrace();
}


return false;
}


public synchronized static boolean isNetAvailable(Context context){


try{
boolean isNetAvailable=false;
if ( context != null )
{
ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if ( mgr != null )
{
boolean mobileNetwork = false;
boolean wifiNetwork = false;
boolean wiMaxNetwork = false;


boolean mobileNetworkConnecetd = false;
boolean wifiNetworkConnecetd = false;
boolean wiMaxNetworkConnected = false;


NetworkInfo mobileInfo = mgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo wifiInfo = mgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
NetworkInfo wiMaxInfo = mgr.getNetworkInfo(ConnectivityManager.TYPE_WIMAX);


if ( mobileInfo != null )
mobileNetwork = mobileInfo.isAvailable();


if ( wifiInfo != null )
wifiNetwork = wifiInfo.isAvailable();


if(wiMaxInfo != null)
wiMaxNetwork = wiMaxInfo.isAvailable();


if(wifiNetwork == true)
wifiNetworkConnecetd = wifiInfo.isConnectedOrConnecting();
if(mobileNetwork == true)
mobileNetworkConnecetd = mobileInfo.isConnectedOrConnecting();
if(wiMaxNetwork == true)
wiMaxNetworkConnected = wiMaxInfo.isConnectedOrConnecting();


isNetAvailable = ( mobileNetworkConnecetd || wifiNetworkConnecetd || wiMaxNetworkConnected );
}
}
return isNetAvailable;
}catch(NullPointerException e)
{
return false;
}catch(Exception e)
{
return false;
}
}




}

我已经完成了所有的答案,我想出了我自己的答案,首先检查互联网是否可用,如果互联网可用,那么它检查它是否是活动的。

我已经包括了所有必要的方法和类来检查活动的互联网连接。

NetworkUtils.class

public class NetworkUtils {


public static final int STATUS_CONNECTED = 0 ;


public static boolean isInternetAvailable(Context ctx){
ConnectivityManager cm = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}


public static int isInternetActiveWithPing() {
try {
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
int exitValue = process.waitFor();
return exitValue;
} catch (Exception ex) {
return -1;
}
}


public static boolean isInternetActiveWithInetAddress() {
try {
InetAddress inetAddress = InetAddress.getByName("www.google.com");
return inetAddress != null && !inetAddress.toString().equals("");
} catch (Exception ex) {
return false;
}
}


public static void displayInternetConnectionMessage(Context ctx){
Toast.makeText(ctx, "Check Internet Connection", Toast.LENGTH_SHORT).show();
}
}

您可以使用以下代码检查Internet是否处于活动状态:

 private void checkInternetConnection() {
if (NetworkUtils.isInternetAvailable(this)) {
new Thread(new Runnable() {
@Override
public void run() {
if (NetworkUtils.isInternetActiveWithPing() == NetworkUtils.STATUS_CONNECTED) {
performNetworkingOperations();
} else {
if (NetworkUtils.isInternetActiveWithInetAddress()) {
performNetworkingOperations();
} else {
displayConnectionMessage();
}
}
}
}).start();


} else {
displayConnectionMessage();
}
}


private void performNetworkingOperations() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Internet is Available", Toast.LENGTH_SHORT).show();
}
});
}


private void displayConnectionMessage() {
runOnUiThread(new Runnable() {
@Override
public void run() {
NetworkUtils.displayInternetConnectionMessage(MainActivity.this);
}
});
}

我尝试了几乎5种不同的android方法,发现这是google提供的最好的解决方案,尤其是针对android:

  try {
HttpURLConnection urlConnection = (HttpURLConnection)
(new URL("http://clients3.google.com/generate_204")
.openConnection());
urlConnection.setRequestProperty("User-Agent", "Android");
urlConnection.setRequestProperty("Connection", "close");
urlConnection.setConnectTimeout(1500);
urlConnection.connect();
if (urlConnection.getResponseCode() == 204 &&
urlConnection.getContentLength() == 0) {
Log.d("Network Checker", "Successfully connected to internet");
return true;
}
} catch (IOException e) {
Log.e("Network Checker", "Error checking internet connection", e);
}

它的fasterefficientaccurate比任何其他可用的解决方案。

这是一些现代代码,它使用AsynTask来解决当您尝试在主线程上连接时android崩溃的问题,并为用户引入带有冲洗和重复选项的警报。

class TestInternet extends AsyncTask<Void, Void, Boolean> {
@Override
protected Boolean doInBackground(Void... params) {
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(3000);
urlc.connect();
if (urlc.getResponseCode() == 200) {
return true;
}
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return false;
}


@Override
protected void onPostExecute(Boolean result) {
if (!result) { // code if not connected
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setMessage("An internet connection is required.");
builder.setCancelable(false);


builder.setPositiveButton(
"TRY AGAIN",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
new TestInternet().execute();
}
});




AlertDialog alert11 = builder.create();
alert11.show();
} else { // code if connected
doMyStuff();
}
}
}

new TestInternet().execute();

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

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

您可以确定活动网络的类型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;
}

或移动莫维尔

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

不要忘记权限:

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

我已经应用了@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;
}

现在称之为,

if (!isInternetAvailable(getActivity())) {
//Show message
} else {
//Perfoem the api request
}

不要检查WIFI连接或移动数据连接,而是尝试点击任何托管域。这样,您就可以检查WIFI/Mobile连接是否能够连接公共互联网。

如果您的移动设备能够连接到所提供的公共域,以下内容将返回。

boolean isReachable()
{
boolean connected = false;
String instanceURL = "Your trusted domain name";
Socket socket;
try {
socket = new Socket();
SocketAddress socketAddress = new InetSocketAddress(instanceURL, 80);
socket.connect(socketAddress, 5000);
if (socket.isConnected()) {
connected = true;
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
socket = null;
}
return connected;
}

希望会有帮助…

如果您使用的是API 23或更高版本,您现在可以使用Google自己的ping服务支持的NetworkCapabilities.NET_CAPABILITY_VALIDATED检查互联网是否处于活动状态。

ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onLost(Network network) {
// handle network lost
}


@Override
public void onAvailable(Network network) {
ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getNetworkInfo(network);
boolean isConnected = (info != null && info.isConnectedOrConnecting());


if (isConnected) {
NetworkCapabilities nc = cm.getNetworkCapabilities(network);
if (nc != null) {
boolean isInternetValid = nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
if (isInternetValid) {
// internet is valid
}
}
}
}
};


NetworkRequest request = new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
connectivityManager.registerNetworkCallback(request, networkCallback);

Android提供ConnectivityManager类来了解Internet连接状态。以下方法对了解Internet连接状态非常有用。

首先将互联网ACCESS_NETWORK_STATE权限添加到AndroidManifest.xml

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

然后使用以下方法检查设备是否连接到互联网。如果设备连接到互联网,此方法将返回true。

public boolean isInternetAvailable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
return activeNetwork != null
&& activeNetwork.isConnectedOrConnecting();
}

参考链接:-http://www.androidtutorialshub.com/android-check-internet-connection-status/

如果您需要检查Internet连接,请使用ping到服务器使用此方法:

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

您可以使用检查通过使用端口

public boolean checkIntCON() {
try {
Socket sock = new Socket();
SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 80);
// port will change according to protocols


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


return true;
} catch (IOException e) { return false; }
}

有不止一种方法

最短但效率低下的方法

只需要网络状态权限

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

那么这个方法,

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


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


return isConnected;


}

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

第二,有效的方法

需要网络状态和Internet权限

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

那么这堂课,

 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
}


}




}

呼叫CheckInternetAsyncTask

new CheckInternetAsyncTask(getApplicationContext()).execute();

一些解释:-

  • 您必须在AsyncTask上检查Internet,否则在某些情况下可能会抛出android.os.NetworkOnMainThreadException

  • ConnectivityManager用于检查网络访问是否为true发送请求(ping)

  • 请求发送到http://clients3.google.com/generate_204,这个众所周知的URL返回一个带有HTTP状态204的空页面,这比http://www.google.com更快,更有效,阅读这个

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

这是检查wifi和移动数据的互联网连接的最简单易行的方法。

public static boolean isConnected(Activity _context) {
if (_context != null) {
ConnectivityManager connMgr = (ConnectivityManager) _context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
if (activeInfo != null && activeInfo.isConnected()) {
boolean wifiConnected = activeInfo.getType() == ConnectivityManager.TYPE_WIFI;
boolean mobileConnected = activeInfo.getType() == ConnectivityManager.TYPE_MOBILE;


if (wifiConnected || mobileConnected) {
Log.d(TAG, "Wifi Connected ");
return true;
} else {
showAlert(_context,_context.getString(R.string.err_no_internet));
return false;
}
} else {
showAlert(_context,_context.getString(R.string.err_no_internet));
return false;
}
} else {
Log.e(TAG, "networkConnectivity: Context NULL");


}
return false;
}

在kotlin中:

class UtilityMethods {
companion object {
fun isConnected(activity: Activity): Boolean {
val connectivityManager: ConnectivityManager =
activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return null != connectivityManager.activeNetworkInfo
}
}}

在活动类中调用isConnection作为:

UtilityMethods.isConnected(this)

内部片段类为:

UtilityMethods.isConnected(activity)
 public static boolean isNetworkAvailable(Context context) {
boolean flag = checkNetworkAvailable(context);


if (!flag) {
Log.d("", "No network available!");
}
return flag;
}




private static boolean checkNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null;
}

这是检查互联网连接的最佳方法。此方法的作用是执行一系列检查“手机是否处于飞行模式,手机是否连接到网络等”。如果所有检查都返回true,该方法将然后从互联网下载文件并查看内容是否与期望值匹配。

与ping服务器以检查Internet连接的其他方法相比,此方法的优点是:

  1. Android运行时在不同的手机上有所不同-因此您可能并不总是能够执行这些命令,如下所示:为什么ping在某些设备上工作而不是其他设备?

  2. ping服务器并不总是有效,因为wifi网络上的登录页面/重定向可能会给人一种连接的错误印象。

此答案是用静态编程语言编写的,并使用燃料库使用fetchUrlAsString方法从Internet下载文件,但只要您确保您的HTTP请求未被缓存,任何库都可以替换。将showConnectionWarning()hideConnectionWarning()分别等同于internet connection status = falseinternet connection status = true

private val networkReceiver = object : BroadcastReceiver() {


override fun onReceive(context: Context?, intent: Intent?) {


val activeNetworkInfo = (context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo


if (activeNetworkInfo != null) {
if (activeNetworkInfo.isConnectedOrConnecting) {
//Launches a coroutine to fetch file asynchronously
launch {
try {
//Downloads file from url on the internet - use any library you want here.
val connectionStatus = fetchUrlAsString(<url_for_file_on_internet>)
//check if the contents of the file is as expected
if (connectionStatus == "Connected To Database") {
hideConnectionWarning()
} else {
showConnectionWarning()
}
} catch (e: Exception) {
//Catches an exception - fetchUrlAsString only throws an exception if there is no internet
showConnectionWarning()
}
}
} else {
showConnectionWarning()
}
} else {
showConnectionWarning()
}
}
}


private suspend fun fetchUrlAsString(url: String): String = suspendCoroutine { cont ->
url.httpGet().header(Pair("pragma", "no-cache"), Pair("cache-control", "no-cache")).responseString { _, _, result ->


when (result) {
is Result.Failure -> {
cont.resumeWithException(result.getException())
}
is Result.Success -> {
cont.resume(result.value)
}
}


}
}

您将需要以下权限:

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

最简单的解决办法是

在大多数情况下,如果他/她想连接到远程服务器,他/她只会检查互联网连接,因此简单而最好的解决方案是按照以下方式ping您的服务器。

public boolean isConnected() {
final String command = "ping -c 1 yourExmapleDomain.com";
boolean isConnected = false;
try {
isConnected = Runtime.getRuntime().exec(command).waitFor() == 0;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return isConnected;
}

这是我用于可达性检查的静态编程语言版本,

静态编程语言

object MyReachability {


private val REACHABILITY_SERVER = "http://google.com" // can be any URL you want


private fun hasNetworkAvailable(context: Context): Boolean {
val service = Context.CONNECTIVITY_SERVICE
val manager = context.getSystemService(service) as ConnectivityManager?
val network = manager?.activeNetworkInfo
Log.d(classTag, "hasNetworkAvailable: ${(network != null)}")
return (network != null)
}


fun hasInternetConnected(context: Context): Boolean {
if (hasNetworkAvailable(context)) {
try {
val connection = URL(REACHABILITY_SERVER).openConnection() as HttpURLConnection
connection.setRequestProperty("User-Agent", "Test")
connection.setRequestProperty("Connection", "close")
connection.connectTimeout = 1500
connection.connect()
Log.d(classTag, "hasInternetConnected: ${(connection.responseCode == 200)}")
return (connection.responseCode == 200)
} catch (e: IOException) {
Log.e(classTag, "Error checking internet connection", e)
}
} else {
Log.w(classTag, "No network available!")
}
Log.d(classTag, "hasInternetConnected: false")
return false
}
}

您甚至可以根据政策和限制将REACHABILITY_SERVER作为参数传递,例如,当您在中国时,您可以选中https://baidu.com而不是https://google.com

举个例子,

val webLoaderThread = Thread {
if (MyReachability.hasInternetConnected(this)){
runOnUiThread {
//mWebView.loadUrl(LANDING_SERVER) // connected
}
} else {
runOnUiThread {
//showDialogNoNetwork() // not connected
}
}
}
webLoaderThread.start()

android权限

不要忘记将以下权限添加到您的AndroidManifest.xml

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

使用以下方法检查Internet连接,也ConnectivityManager.getAPI 28中不建议使用ActiveNetworkInfo()

@Suppress("DEPRECATION")
fun isNetworkConnected(context: Context): Boolean {
val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
return cm?.run {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
cm.getNetworkCapabilities(cm.activeNetwork)?.run {
when {
hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
else -> false
}
}
} else {
cm.activeNetworkInfo?.run {
when (type) {
ConnectivityManager.TYPE_WIFI -> true
ConnectivityManager.TYPE_MOBILE -> true
else -> false
}
}
}
} ?: false


}

还要将以下权限添加到清单中

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

HasTransfer(NetworkCapabilities.TRANSPORT_ETHERNET)用于为Android TV开发的应用程序,其中TV可以直接连接到以太网

正如Android doc建议的那样,在

获取活动网络信息()在Android 10中已弃用。使用 网络回调而不是针对Android 10(API级别)的应用程序 29)或更高。

所以下面是我们用来检查网络连接的方式目前

val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
val isConnected: Boolean = activeNetwork?.isConnectedOrConnecting == true

使用网络回调检查互联网连接的新方法

步骤1:

    private lateinit var connectivityManager:ConnectivityManager


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
}

步骤2:创建回调:

private val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
Timber.e("Network:onAvailable")
}


override fun onLost(network: Network) {
super.onLost(network)
Timber.e("Network:onLost")
}


}

步骤3:注册和取消注册回调:

private fun registerNetworkCallback() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
connectivityManager.registerDefaultNetworkCallback(callback)
} else {
// Old way to check network connection
}
}


override fun onStop() {
unRegisterNetworkCallback()
super.onStop()
}


private fun unRegisterNetworkCallback() {
connectivityManager.unregisterNetworkCallback(callback)
}

在下面的链接中查看更新详细信息:

https://developer.android.com/training/monitoring-device-state/connectivity-status-type

使用此静态编程语言扩展:

/**
* Check whether network is available
*
* @param context
* @return Whether device is connected to Network.
*/
fun Context.isNetworkAvailable(): Boolean {
with(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//Device is running on Marshmallow or later Android OS.
with(getNetworkCapabilities(activeNetwork)) {
return hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || hasTransport(
NetworkCapabilities.TRANSPORT_CELLULAR
)
}
} else {
activeNetworkInfo?.let {
// connected to the internet
@Suppress("DEPRECATION")
return listOf(ConnectivityManager.TYPE_WIFI, ConnectivityManager.TYPE_MOBILE).contains(it.type)
}
}
}
return false
}

使用方法:

private fun isInternetAvailable(context: Context): Boolean {
(context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).run {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return this.getNetworkCapabilities(this.activeNetwork)?.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET
) ?: false
} else {
(@Suppress("DEPRECATION")
return this.activeNetworkInfo?.isConnected ?: false)
}
}
}

需要的权限:

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

静态编程语言和协程

我已经将该函数放在ViewModel中,它具有viewModelScope。使用可观察的LiveData,我通知一个有关连接的活动。

视图模型

 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)
}
}
}
 private val _connection = MutableLiveData<Boolean>()
val connection: LiveData<Boolean> = _connection

活动

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

静态编程语言实现

/**
* Function that uses ping, takes server name or ip as argument.
*
* @return [Double.MAX_VALUE] if server is not reachable. Average RTT if the server is reachable.
*
* Success output example
*
* PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
* 64 bytes from 8.8.8.8: icmp_seq=1 ttl=254 time=172 ms
* 64 bytes from 8.8.8.8: icmp_seq=2 ttl=254 time=166 ms
* 64 bytes from 8.8.8.8: icmp_seq=3 ttl=254 time=167 ms
* 64 bytes from 8.8.8.8: icmp_seq=4 ttl=254 time=172 ms
* 64 bytes from 8.8.8.8: icmp_seq=5 ttl=254 time=167 ms


* --- 8.8.8.8 ping statistics ---
* 5 packets transmitted, 5 received, 0% packet loss, time 4011ms
* rtt min/avg/max/mdev = 166.470/169.313/172.322/2.539 ms
*          |________________________|
* value to parse using it.split('=')[1].trim().split(' ')[0].trim().split('/')[1].toDouble()
*/
@ExperimentalStdlibApi
fun pingServerAverageRtt(host: String): Double {


var aveRtt: Double = Double.MAX_VALUE


try {
// execute the command on the environment interface, timeout is set as 0.2 to get response faster.
val pingProcess: Process = Runtime.getRuntime().exec("/system/bin/ping -i 0.2 -c 5 $host")
// gets the input stream to get the output of the executed command
val bufferedReader = BufferedReader(InputStreamReader(pingProcess.inputStream))


bufferedReader.forEachLine {
if (it.isNotEmpty() && it.contains("min/avg/max/mdev")) {  // when we get to the last line of executed ping command
aveRtt = it.split('=')[1].trim()
.split(' ')[0].trim()
.split('/')[1].toDouble()
}
}
} catch (e: IOException) {
e.printStackTrace()
}


return aveRtt
}


用法示例


val latency = pingServerAverageRtt(ipString)
if (latency != Double.MAX_VALUE) {
//server reachable
} else {
//server not reachable
}

这是我解决这个问题的解决方法,并检查有效的互联网连接,因为他们说网络信息类不能给你预期的结果,当网络连接但没有互联网时,它可能返回true。

所以这是我基于@Levite的完成工作答案:

首先,你必须有Asynck的任务来检查网络可用性,这是我的:

public class Connectivity {
private static final String TAG = "Connectivity";
private static boolean hasConnected = false, hasChecked = false;
private InternetListener internetListener;
private Activity activity;


public Connectivity(InternetListener internetListener, Activity activity) {
this.internetListener = internetListener;
this.activity = activity;
}


public void startInternetListener() {




CheckURL checkURL = new CheckURL(activity);


checkURL.execute();


long startTime = System.currentTimeMillis();


while (true) {
if (hasChecked && hasConnected) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
internetListener.onConnected();
}
});


checkURL.cancel(true);
return;
}


// check if time
if (System.currentTimeMillis() - startTime >= 1000) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
internetListener.onDisconnected();
}
});




checkURL.cancel(true);
return;
}
}


//return hasConnected;
}




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


private Activity activity;


public CheckURL(Activity activity) {
this.activity = activity;
}


@Override
protected Boolean doInBackground(Void... params) {
if (!isNetWorkAvailable(activity)) {
Log.i(TAG, "Internet not available!");
return false;
}


int timeoutMs = 3000;


try {
Socket sock = new Socket();
SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);
sock.connect(sockaddr, timeoutMs);
sock.close();
Log.i(TAG, "Internet available :)");
return true;


} catch (IOException e) {
e.printStackTrace();
return false;
}


}


@Override
protected void onPostExecute(Boolean result) {
hasChecked = true;
hasConnected = result;
super.onPostExecute(result);}}
     



private static final String TAG = "Connectivity";




private static boolean isNetWorkAvailable(Activity activity) {


ConnectivityManager connectivityManager =
(ConnectivityManager)
activity.getSystemService(Activity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo =
null;
if (connectivityManager != null) {
networkInfo =
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
}
boolean isConnected;
boolean isWifiAvailable = false;
if (networkInfo != null) {
isWifiAvailable = networkInfo.isAvailable();
}
boolean isWifiConnected = false;
if (networkInfo != null) {
isWifiConnected = networkInfo.isConnected();
}
if (connectivityManager != null) {
networkInfo =
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
}
boolean isMobileAvailable = false;
if (networkInfo != null) {
isMobileAvailable = networkInfo.isAvailable();
}
boolean isMobileConnected = false;
if (networkInfo != null) {
isMobileConnected = networkInfo.isConnected();
}
isConnected = (isMobileAvailable && isMobileConnected) ||
(isWifiAvailable && isWifiConnected);
return (isConnected);}
}}






private static boolean isNetWorkAvailable(Context context) {


ConnectivityManager connectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo =
null;
if (connectivityManager != null) {
networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
}
boolean isConnected;
boolean isWifiAvailable = false;
if (networkInfo != null) {
isWifiAvailable = networkInfo.isAvailable();
}
boolean isWifiConnected = false;
if (networkInfo != null) {
isWifiConnected = networkInfo.isConnected();
}
if (connectivityManager != null) {
networkInfo =
connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
}
boolean isMobileAvailable = false;
if (networkInfo != null) {
isMobileAvailable = networkInfo.isAvailable();
}
boolean isMobileConnected = false;
if (networkInfo != null) {
isMobileConnected = networkInfo.isConnected();
}
isConnected = (isMobileAvailable && isMobileConnected) ||
(isWifiAvailable && isWifiConnected);
return (isConnected);


}

}

之后,您应该创建另一个线程来启动Ascnk任务并使用InternetListener侦听结果。

public interface InternetListener {
void onConnected();
void onDisconnected();
}

而等待AsynckTeam结果的Thread,您可以将其放在实用程序类中:

 private static Thread thread;


public static void startNetworkListener(Context context, InternetListener
internetListener) {


if (thread == null){
thread = new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();
new Connectivity(internetListener,context).startInternetListener();
}
});
}


thread.start();
}

最后调用start NetworkListener()方法并监听结果。

我的Utils.java类中的活动示例:

     Utils.startNetworkListener(this, new InternetListener() {
@Override
public void onConnected() {
// do your work when internet available.
}


@Override
public void onDisconnected() {
// do your work when no internet available.
}
});

快乐编码:)。

如果您想在连接丢失时显示警报。您可以使用以下方法。

此方法用于检查一次连接。首先,您必须在类中创建此方法。

private boolean isNetworkConnected() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if(!(cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected())){
showNetworkDialog();
return false;
}
return true;
}

在类中创建此方法作为连接侦听器。

private void ConnectionCheck(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest networkRequest = new NetworkRequest.Builder().build();
connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
Log.i("Tag", "active connection");
}


@Override
public void onLost(Network network) {
super.onLost(network);
Log.i("Tag", "losing active connection");
isNetworkConnected();
}
});
}
}

为了显示对话框,您可以创建showDialog()方法。

private void showNetworkDialog(){
new AlertDialog.Builder(MainActivity.this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Connection lost?")
.setMessage("Please check your internet connection!")
.setCancelable(false)
.setPositiveButton("Exit", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton("Retry", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
isNetworkConnected();
}
})
.show();
}

最后,您可以在onCreate()方法中调用此方法。

if(isNetworkConnected()){
ConnectionCheck();
}

在清单文件中,您必须提及权限。

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

代码:

    fun isInternetConnection(): Boolean {
var returnVal = false
thread {
returnVal = try {
khttp.get("https://www.google.com/")
true
}catch (e:Exception){
false
}
}.join()
return returnVal
}

Gradle:

implementation 'io.karn:khttp-android:0.1.0'

我使用khttp,因为它很容易使用。

所以在上面的代码中,如果它成功连接到google.com,它将返回true或false。这很简单。我不明白为什么每个人都要编写冗长的代码行,即使是这样简单的事情。

如果您使用的是Firebase,则可以使用这个

Java:

DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
Log.d(TAG, "connected");
} else {
Log.d(TAG, "not connected");
}
}


@Override
public void onCancelled(@NonNull DatabaseError error) {
Log.w(TAG, "Listener was cancelled");
}
});

静态编程语言:

val connectedRef = Firebase.database.getReference(".info/connected")
connectedRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val connected = snapshot.getValue(Boolean::class.java) ?: false
if (connected) {
Log.d(TAG, "connected")
} else {
Log.d(TAG, "not connected")
}
}


override fun onCancelled(error: DatabaseError) {
Log.w(TAG, "Listener was cancelled")
}
})

这是一个简单的解决方案,以确保您的应用程序可以访问互联网:

static final String CHECK_INTERNET_ACCESS_URL = "https://www.google.com";


public static void isInternetAccessWorking(Context context) {


StringRequest stringRequest = new StringRequest(Request.Method.GET, CHECK_INTERNET_ACCESS_URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Internet access is OK
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// NO internet access
}
});


Volley.newRequestQueue(context).add(stringRequest);
}

此解决方案使用Android的Volley lib,必须在build.gradle中声明:

implementation 'com.android.volley:volley:1.1.1'

Jetpack编写/静态编程语言

基于利未人的回答,可以在Jetpack Compose中使用此Composable

val DNS_SERVERS = listOf("8.8.8.8", "1.1.1.1", "4.2.2.4")
const val INTERNET_CHECK_DELAY = 3000L
@Composable
fun InternetAwareComposable(
dnsServers: List<String> = DNS_SERVERS,
delay: Long = INTERNET_CHECK_DELAY,
successContent: (@Composable () -> Unit)? = null,
errorContent: (@Composable () -> Unit)? = null,
onlineChanged: ((Boolean) -> Unit)? = null
) {
suspend fun dnsAccessible(
dnsServer: String
) = try {
withContext(Dispatchers.IO) {
Runtime.getRuntime().exec("/system/bin/ping -c 1 $dnsServer").waitFor()
} == 0
} catch (e: Exception) {
false
}


var isOnline by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
while (true) {
isOnline = dnsServers.any { dnsAccessible(it) }
onlineChanged?.invoke(isOnline)
delay(delay)
}
}
if (isOnline) successContent?.invoke()
else errorContent?.invoke()
}