java - 在android studio中,当手机没有互联网时,如何防止缓冲阅读器从url读取错误
问题描述
在我的应用程序中,当我按下按钮时,缓冲阅读器应该从在线文本文件中读取一行文本。
作为测试,如果文本被正确阅读,我希望出现“成功”的祝酒词。如果读取失败,例如因为手机没有连接到互联网,我希望出现“失败”的祝酒词。
但是,如果我打开飞行模式,然后按下按钮,它似乎永远“挂起”,“失败”的 toast 永远不会出现——或者它只是让应用程序完全崩溃。
这是我正在使用的代码:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new NotePadFileFromServer().execute();
}
});
public class NotePadFileFromServer extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
try {
url = new URL(TextFileURL);
bufferReader = new BufferedReader(new InputStreamReader(url.openStream()));
TextHolder = bufferReader.readLine();
bufferReader.close();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "Fail!", Toast.LENGTH_SHORT).show();
}
return null;
}
@Override
protected void onPostExecute(Void finalTextHolder) {
Toast.makeText(MainActivity.this, "Success!", Toast.LENGTH_SHORT).show();
super.onPostExecute(finalTextHolder);
}
}
我尝试使用 ConnectivityManager 添加预检查以测试是否有按照以下代码的 Internet 连接:https ://stackoverflow.com/a/58146646/4250107 ,但这仅适用于电话用户已专门关闭互联网,如果打开wifi功能,再次发生崩溃,但没有互联网。然后我尝试按照以下代码检查互联网连接:https://stackoverflow.com/a/58146896/4250107,但这也会使应用程序崩溃,因为显然(?)尝试 ping 服务器在三星手机上不起作用.
编辑:最终固定代码。
public class NotePadFileFromServer extends AsyncTask<Void, Void, String>{
@Override
protected String doInBackground(Void... params) {
try {
URLConnection url = new URL(TextFileURL).openConnection());
url.setConnectTimeout(1000);
url.setReadTimeout(1000);
bufferReader = new BufferedReader(new InputStreamReader(url.getInputStream()));
TextHolder = bufferReader.readLine();
bufferReader.close();
return "Success!";
} catch (Exception e) {
return "Fail!";
}
}
@Override
protected void onPostExecute(String success) {
Toast.makeText(MainActivity.this, success, Toast.LENGTH_SHORT).show();
super.onPostExecute(success);
}
}
解决方案
是的,正如您所说,ConnectivityManager 不会帮助您,因为如果您有 wifi 但没有互联网,它会崩溃。
但是,可以检查互联网连接。我不能用 ping 来做(和你一样),但是当我尝试打开一些打开的端口(80 或 443)的套接字时我可以做到。这是使用 rxjava 的代码,但您可以将其调整为您正在使用的代码。
fun isOnline(context: Context?): Single<Boolean> {
return Single.fromCallable {
try {
// Connect to Google DNS to check for connection
val timeoutMs = 2500
val socket = Socket()
val address = InetAddress.getByName("www.google.com")
val socketAddress = InetSocketAddress(address, 443)
socket.connect(socketAddress, timeoutMs)
socket.close()
true
} catch (e: Exception) {
false
}
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
就我而言,我用后端打开了套接字,所以我也可以检查它是否正常工作。我把 www.google.com 放在你没有后端的情况下。
使用方法是:
isOnline(context).subscribe { hasInternet ->
//Conditional check
}
推荐阅读
- mongodb - 蒙古数据库。展平内部数组
- python - 有没有办法让 Python 自动与 Excel 一起运行?
- python - 即使不是按顺序,如何检查一个字符串是否是另一个字符串的子字符串?
- django - 如何修复“/orders/create/'tuple'对象的AttributeError在Django中没有属性'get'
- c# - 将按钮对象添加到 DataGridView
- c - 如何在 C 套接字中进行同步?
- ios - 在 SceneKit 中,当从 RunAction 的完成处理程序调用时,SCNAction 挂起
- maven - 不在 war 文件中包含 src/lib/*.jar
- django - 如何将 django-datatables-view 重定向到正确的 HTML 模板?
- swift - Firebase-Swift 如何将子值相加