在我的应用程序中,当我按下一个按钮时,缓冲阅读器应该在线读取文本文件中的一行文本。
作为一个测试,如果文本被正确阅读,我希望出现一个说“成功”的祝酒词。如果读取失败,比如因为手机没有连接到互联网,我希望出现一个说“失败”的祝酒词。
然而,如果我打开飞行模式,然后按下按钮,它似乎永远“挂起”,并且“失败”的祝酒词永远不会出现--或者它只是完全使应用程序崩溃。
这是我使用的代码:
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添加一个预检查,以测试是否有互联网连接,如代码: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);
}
}发布于 2019-11-13 07:25:27
应用程序崩溃,因为当出现异常时,您正尝试在后台线程中执行与UI相关的任务。所以,下面是造成崩溃的原因,
catch (Exception e) {
Toast.makeText(MainActivity.this, "Fail!", Toast.LENGTH_SHORT).show();
}因此,您可以通过以下方式重构代码来避免崩溃,
public class NotePadFileFromServer extends AsyncTask<Void, Void, String>{
@Override
protected String doInBackground(Void... params) {
try {
url = new URL(TextFileURL);
bufferReader = new BufferedReader(new InputStreamReader(url.openStream()));
TextHolder = bufferReader.readLine();
bufferReader.close();
return "Success!";
} catch (Exception e) {
return "Fail!";
}
}
@Override
protected void onPostExecute(String finalTextHolder) {
Toast.makeText(MainActivity.this, finalTextHolder, Toast.LENGTH_SHORT).show();
super.onPostExecute(finalTextHolder);
}
}如果出现超时问题,我建议您使用openConnection() (它返回一个UrlConnection)而不是openStream()。以便您可以设置更短连接和读取超时。
发布于 2019-11-13 07:06:19
是的,正如你所说,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
} https://stackoverflow.com/questions/58827627
复制相似问题