Android - 编程检查网络连接并在未连接时显示对话框

32
我正在进行一个实时项目,当用户点击应用程序时,欢迎屏幕出现(该屏幕上有一个Webview)。如果没有连接到互联网,则应用程序会崩溃。我的问题是通过编程方式检查移动设备是否连接到互联网。如果没有连接,则不要从Web服务抓取数据到Webview中,并显示一个对话框,显示“检查您的互联网连接”。
在研究过程中,我发现了许多事情,并尝试着去实现它,但是没有满足我的需求。
我的代码是:
public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
        return true;
    }
    else
    {
        Description.setVisibility(View.INVISIBLE);
        new AlertDialog.Builder(WelcomePage.this)
        .setTitle(getResources().getString(R.string.app_name))
        .setMessage(
                getResources().getString(
                        R.string.internet_error))
        .setPositiveButton("OK", null).show();
    }
    return false;
}

我正在AsyncTaskdoInBackground()中调用此函数。

请帮忙!


这个检查的是互联网连接还是WiFi连接?我怀疑是后者,而互联网连接只能通过ping来验证? - carl
14个回答

30

你可以查看这个库:

https://github.com/novoda/merlin

只需实现 Connectable 接口,当网络断开或重新连接时,您将获得一个回调。

因此,您可以在这种情况下展示您的对话框。

您还可以查询库的当前状态,并选择不执行网络任务

example

使用 Merlin.Builder() 创建 Merlin

merlin = new Merlin.Builder().withConnectableCallbacks().build(context);

在您的活动中绑定和解除绑定服务

@Override
protected void onResume() {
    super.onResume();
    merlin.bind();
}

@Override
protected void onPause() {
    super.onPause();
    merlin.unbind();
}

注册回调函数

merlin.registerConnectable(new Connectable() {
        @Override
        public void onConnect() {
            // Do something!
        }
});

在演示中,MerlinActivity 展示了一种简单的方法来减少 Merlin 对主应用程序代码的干扰。


如果您访问 https://github.com/novoda/merlin 并向下滚动,阅读自述文件,它会非常简单地解释。 - Blundell
每次我完成第二个活动并使用Merlin(第一个活动也在使用),Merlin都会泄漏(我在onPause和onDestroy中使用了merlin.unbind和merlin == null)。 - Krzysztof Dziuba
@KrzysztofDziuba 如果您在 GH 存储库 https://github.com/novoda/merlin/issues 上开一个问题,我们很乐意帮助您解决 Merlin 的问题。 - MechaRyRy

21

终于,我得到了答案。

ConnectivityManager conMgr =  (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = conMgr.getActiveNetworkInfo();
if (netInfo == null){
    Description.setVisibility(View.INVISIBLE);
    new AlertDialog.Builder(WelcomePage.this)
        .setTitle(getResources().getString(R.string.app_name))
        .setMessage(getResources().getString(R.string.internet_error))
        .setPositiveButton("OK", null).show();
}else{
    dialog = ProgressDialog.show(WelcomePage.this, "", "Loading...", true,false);
    new Welcome_Page().execute();
}

9
这不应该是期望的答案,因为你自己问的是如何检查互联网连接而不是网络连接,而上面的答案展示了后者。 - therealprashant
1
如果设备已连接到网络但没有可用的数据(互联网)余额,则将执行Welcome_Page()。 - User
你必须小心,因为互联网连接与网络连接不同。我强烈建议你使用一些可靠的东西,比如 https://dev59.com/CWMm5IYBdhLWcg3wFL_s#17880697,或者检查源代码。 - zegnus

14

NetworkInfo 类在 API 29 (Android 10.0)中已被弃用。有关详细信息,请参见这里:

此类已在API级别29中弃用。请使用ConnectivityManager#getNetworkCapabilities或ConnectivityManager#getLinkProperties以同步方式获取信息。

更新后的代码(使用Kotlin)

var isConnected = false
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    val activeNetwork = connectivityManager.activeNetwork ?: return false
    val networkCapabilities = connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
    isConnected = when {
        activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
        activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
        activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
        else -> false
    }
} else {
    isConnected = when (connectivityManager.activeNetworkInfo?.type) {
        ConnectivityManager.TYPE_WIFI -> true
        ConnectivityManager.TYPE_MOBILE -> true
        ConnectivityManager.TYPE_ETHERNET -> true
        else -> false
    }
}

1
更新为: val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true - Siddhesh Chandorkar

12

检查网络连接

 ConnectivityManager mgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
 NetworkInfo netInfo = mgr.getActiveNetworkInfo();

        if (netInfo != null) {
            if (netInfo.isConnected()) {
                // Internet Available
            }else {
               //No internet
            }
        } else {
            //No internet
        }

5
这是一个简单的函数,用于检查您的互联网连接。如果连接成功,则返回true,否则返回false。
 public boolean isInternetOn() {

        // get Connectivity Manager object to check connection
        ConnectivityManager connec =
                (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

        // Check for network connections
        if (connec.getNetworkInfo(0).getState() == android.net.NetworkInfo.State.CONNECTED ||
                connec.getNetworkInfo(0).getState() == android.net.NetworkInfo.State.CONNECTING ||
                connec.getNetworkInfo(1).getState() == android.net.NetworkInfo.State.CONNECTING ||
                connec.getNetworkInfo(1).getState() == android.net.NetworkInfo.State.CONNECTED) {


            return true;

        } else if (
                connec.getNetworkInfo(0).getState() == android.net.NetworkInfo.State.DISCONNECTED ||
                        connec.getNetworkInfo(1).getState() == android.net.NetworkInfo.State.DISCONNECTED) {


            return false;
        }
        return false;
    }
}

这是一个检查互联网连接并检查有效或包含在服务器中的URL的项目,点击此处查看。


3
if (InternetConnection.checkConnection(context)) {
    // Internet Available...
} else {
    // Internet Not Available...
}

只需复制以下类

public class InternetConnection {

    /** CHECK WHETHER INTERNET CONNECTION IS AVAILABLE OR NOT */
    public static boolean checkConnection(Context context) {
        final ConnectivityManager connMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetworkInfo = connMgr.getActiveNetworkInfo();

        if (activeNetworkInfo != null) { // connected to the internet
            Toast.makeText(context, activeNetworkInfo.getTypeName(), Toast.LENGTH_SHORT).show();

            if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                // connected to wifi
                return true;
            } else if (activeNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
                // connected to the mobile provider's data plan
                return true;
            }
        }
        return false;
    }
}

请在清单文件中添加以下权限:

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

2

我尝试了上面描述的不同方法,但在某些情况下遇到了问题。因此,最终我使用以下代码片段进行网络调用...

try {
    InetAddress address = InetAddress.getByName("www.stackoverflow.com");
    //Connected to working internet connection
} catch (UnknownHostException e) {
    e.printStackTrace();
    //Internet not available
}

这个方法在许多方面都很有用。如果这种方法存在问题,请告诉我。


这个代码可以工作,但必须在工作线程中执行。上面的代码会引发主线程网络异常。 - SkyTreasure
同意@SkyTreasure,这取决于我们如何利用这个片段 ;) - User
@SkyTreasure,你能提供一下如何在主线程中使用它的代码吗? - Rawnak Yazdani

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

1
这段代码可以帮助您检查API级别16到30之间的互联网连接是否可用。
@SuppressWarnings("deprecation")
public static boolean isInternetAvailable(Activity activity) {
    ConnectivityManager conMgr = (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Network network = conMgr.getActiveNetwork();
        NetworkCapabilities networkCapabilities = conMgr.getNetworkCapabilities(network);
        if (networkCapabilities != null) {
            return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        } else return false;
    } else {
        // below API Level 23
        return conMgr.getActiveNetworkInfo() != null
                && conMgr.getActiveNetworkInfo().isAvailable()
                && conMgr.getActiveNetworkInfo().isConnected();
    }
}

1

如何检查互联网连接的更新版 Kotlin 和 Android 29 版本(在 SDK 29 中,getNetworkInfo 已弃用),适用于 minSDK >= 23:

fun hasInternet(): Boolean {
    val connectivityManager = appContainer.contextProvider.currentAppContext()
        .getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val network = connectivityManager.activeNetwork

    val capabilities = connectivityManager.getNetworkCapabilities(network)
    var hasInternet = false
    capabilities?.let {
        hasInternet = it.hasCapability(NET_CAPABILITY_INTERNET)
    }
    return hasInternet
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接