我有一个 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();
}
}
if(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) ...
来完成。请参阅 my answer 以获得更好的实现。顺便说一句,接受的答案(以及这里的许多其他答案)只是检查网络连接,而不是互联网。
如果设备处于飞行模式(或可能在其他没有可用网络的情况下),则 cm.getActiveNetworkInfo()
将为 null
,因此您需要添加 null
检查。
修改 (Eddie's solution) 如下:
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
可能会更好。我想这取决于个人用例。
网络连接/互联网访问
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;
}
+
可以在主线程上运行
-
在某些旧设备(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 线程上运行
这在每台设备上都非常可靠,而且速度非常快。它需要在单独的任务中运行(例如 ScheduledExecutorService
或 AsyncTask
)。
可能的问题
真的够快吗?是的,非常快;-)
除了在互联网上测试一些东西之外,没有可靠的方法来检查互联网吗?据我所知,但请告诉我,我将编辑我的答案。
如果 DNS 关闭了怎么办? Google DNS(例如 8.8.8.8)是世界上最大的公共 DNS。截至 2018 年,它每天处理超过一万亿个查询 [1]。我们只是说,您的应用程序可能不会成为今天的热门话题。
需要哪些权限?
额外:一次性 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 */}
额外:One-shot 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 {
}
});
额外:一次性 AsyncTask 示例
注意: 这显示了如何执行请求的另一个示例。但是,由于 AsyncTask
已被弃用,它应该被您的应用程序的线程调度、Kotlin 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 */ });
不需要很复杂。最简单和框架的方式是使用 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 清单中。
context.getSystemService
中添加上下文,否则它不起作用。我在这里得到了线索androidhive.info/2012/07/…
要使 getActiveNetworkInfo()
工作,您需要将以下内容添加到清单中。
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
getActiveNetworkInfo()
在 API 级别 29 中已弃用。
看一下 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 对象的详细状态枚举
编辑编辑:要了解您是否可以访问主机,您可以使用
Context.getSystemService(Context.CONNECTIVITY_SERVICE)
.requestRouteToHost(TYPE_WIFI, int hostAddress)
显然,我使用 Context.getSystemService(Context.CONNECTIVITY_SERVICE) 作为代理说
ConnectivityManager cm = Context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.yourMethodCallHere();
检查此代码...它对我有用:)
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
在此 link 中找到并修改 (!):
在您的清单文件中至少添加:
<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;
}
}
我做了这个代码,它是最简单的,它只是一个布尔值。通过询问if(isOnline()){
如果有连接,如果它可以连接到页面,您会得到状态代码 200
(稳定连接)。
确保添加正确的 INTERNET
和 ACCESS_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;
}
它对我有用:
要验证网络可用性:
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;
}
方法不止一种
一、最短但效率低的方法
仅需要网络状态权限
<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
是一个解决方案,我只是在一个方法中添加了它,这是一个简化的方法 all use
ConnectivityManager
如果有网络访问而不是 Internet 访问,则返回 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 更快更高效,请阅读这个。如果您有网站,最好将您的网站而不是 google,前提是您在应用程序中使用它
超时可更改范围(20ms -> 2000ms),常用1500ms
这是我使用的方法:
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
Kotlin 和协程
我已将该函数放在具有 viewModelScope
的 ViewModel
中。使用可观察的 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
}
}
}
_connection
变量。
到目前为止,我所看到的所有内容中最短和最干净的方式应该是:
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任何主机,它只是检查连接状态,所以如果您的路由器没有互联网连接并且您的设备已连接到它,尽管您没有互联网,但此方法将返回true。对于实际测试,我建议执行 HttpHead 请求(例如到 www.google.com)并检查状态,如果它的 200 OK 一切正常并且您的设备有互联网连接。
移动设备上的一个重要用例是它确保存在实际连接。这是移动用户通过“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;
}
我使用此代码而不是 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();
}
您可以遍历所有网络连接并检查是否至少有一个可用连接:
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;
}
对我来说,检查 Activity 类中的连接状态不是一个好习惯,因为
ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
应该在那里调用,或者您需要将 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();
}
通过这种方式,我可以将这种情况与同一类中的其他情况一起处理(我的服务器总是以 json 字符串响应)
最佳方法:
public static boolean isOnline() {
try {
InetAddress.getByName("google.com").isReachable(3);
return true;
} catch (UnknownHostException e){
return false;
} catch (IOException e){
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 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;
}
此方法为您提供了一种非常快速的方法(用于实时反馈)或一种较慢的方法(用于需要可靠性的一次性检查)的选项
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;
}
检查 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;
}
}
}
有关详细信息,请访问 How to Check Android Network / Internet Connectivity Status
以下是我的 Utils
类的代码:
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager connectivityManager
= (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
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();
}
}
这在 android 文档 http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html 中有介绍
检查我们是否与 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();
}
并且您可以确定网络活动的类型 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;
}
或移动 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;
}
不要忘记权限:
<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
}
2015 年 6 月 29 日更新 如果您使用 Xamarin.Android 并想要检查连接,您可以使用 Nuget 包,它可以在多个平台上为您提供此功能。好的候选人是 here 和 here。 [更新结束]
上面的答案都很好,但是它们都是 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 的其他答案是错误的,因为拥有网络连接并不意味着您可以访问互联网。例如,用户可能连接到咖啡店的 WiFi 门户,但无法访问互联网。要检查互联网是否可以访问,您必须尝试连接到实际的服务器。通常,当您要执行此操作时,您会想到要连接的特定服务器,因此请继续检查是否可以连接到该服务器。这是检查与服务器的连接性的简单方法。
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 不会让您在主线程上运行它。
我已经浏览了所有答案,并提出了自己的答案,首先检查 Internet 是否可用,如果 Internet 可用,则检查它是否处于活动状态。
我已经包含了所有必要的方法和类来检查活动的 Internet 连接。
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);
}
});
}
不定期副业成功案例分享
context.getSystemService
中添加上下文,否则它不起作用。我在这里得到了线索androidhive.info/2012/07/…