我得到了一个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();
}
}
不要检查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;
}
希望对大家有所帮助。
这个线程中的大多数答案只检查是否有可用的连接,但不检查该连接是否工作,其他答案不是设备范围,我的解决方案应该在每个设备上工作。
你可以在启动应用程序之前在你的主要活动中删除我的代码,它会快速确定是否有实际的互联网连接,如果有对话框将立即删除,应用程序将被启动,如果没有警报会弹出说应用程序需要互联网连接才能工作。
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();
Kotlin和协程
我将函数放置在一个ViewModel中,该ViewModel具有viewModelScope。使用一个可观察的LiveData,我通知一个活动有关连接。
ViewModel
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
}
}
}
对我来说,在Activity类中检查连接状态并不是一个好的实践,因为
ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
应该在那里调用,或者您需要下推您的活动实例(上下文)到连接处理程序类,以能够检查那里的连接状态
当没有可用的连接(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字符串)
看一下ConnectivityManager类。您可以使用这个类来获取主机上活动连接的信息。http://developer.android.com/reference/android/net/ConnectivityManager.html
编辑:你可以使用
Context.getSystemService(Context.CONNECTIVITY_SERVICE)
.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
or
Context.getSystemService(Context.CONNECTIVITY_SERVICE)
.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
并解析返回NetworkInfo对象的DetailedState枚举
EDIT EDIT:查看是否可以访问主机
Context.getSystemService(Context.CONNECTIVITY_SERVICE)
.requestRouteToHost(TYPE_WIFI, int hostAddress)
显然,我使用Context.getSystemService(Context.CONNECTIVITY_SERVICE)作为代理来表示
ConnectivityManager cm = Context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.yourMethodCallHere();