首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在android studio中,当手机没有互联网时,如何防止从url读取缓冲阅读器的错误?

在android studio中,当手机没有互联网时,如何防止从url读取缓冲阅读器的错误?
EN

Stack Overflow用户
提问于 2019-11-13 06:27:21
回答 2查看 65关注 0票数 0

在我的应用程序中,当我按下一个按钮时,缓冲阅读器应该在线读取文本文件中的一行文本。

作为一个测试,如果文本被正确阅读,我希望出现一个说“成功”的祝酒词。如果读取失败,比如因为手机没有连接到互联网,我希望出现一个说“失败”的祝酒词。

然而,如果我打开飞行模式,然后按下按钮,它似乎永远“挂起”,并且“失败”的祝酒词永远不会出现--或者它只是完全使应用程序崩溃。

这是我使用的代码:

代码语言:javascript
运行
复制
    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服务器在三星手机上不起作用。

编辑:最终修复代码。

代码语言:javascript
运行
复制
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);
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-13 07:25:27

应用程序崩溃,因为当出现异常时,您正尝试在后台线程中执行与UI相关的任务。所以,下面是造成崩溃的原因,

代码语言:javascript
运行
复制
catch (Exception e) {
    Toast.makeText(MainActivity.this, "Fail!", Toast.LENGTH_SHORT).show(); 
}

因此,您可以通过以下方式重构代码来避免崩溃,

代码语言:javascript
运行
复制
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()。以便您可以设置更短连接和读取超时。

票数 1
EN

Stack Overflow用户

发布于 2019-11-13 07:06:19

是的,正如你所说,ConnectivityManager不会帮你,因为如果你有wifi但没有互联网,它就会崩溃。

但是,可以检查互联网连接。我不能用ping (和你一样)做到这一点,但当我尝试打开连接到一些打开的端口(80或443)的套接字时,我可以做到。下面是使用rxjava的代码,但您可以根据您正在使用的内容对其进行调整。

代码语言:javascript
运行
复制
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以防你没有后端。

它的使用方法是:

代码语言:javascript
运行
复制
isOnline(context).subscribe { hasInternet -> 
    //Conditional check
} 
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58827627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档