在这篇文章中,我将展示如何处理连接错误或连接更改时的情况(即,从UMTS到WI-FI)。 在所有这些情况下,我们都必须妥善处理这些错误并实施一些策略以尝试在可能的情况下重新连接。
在理想环境中,当我们使用HTTP协议连接到远程服务器时,一切都可以正常运行,我们不必担心连接错误,服务器在高请求负载下或网络不稳定的情况。 在最后几篇文章中,我们讨论了如何连接到远程服务器以及如何发送和接收数据。 在现实世界中,通常当我们连接到远程服务器时,我们会走路或跑步,甚至是在车里,这样网络信号可能会发生变化或突然中断。 同时,Android可以设备从UMTS切换到WI-FI ,反之亦然,也可以从一个APN切换到另一个APN ,依此类推。 在编写应用程序代码时,我们必须考虑所有这些情况并正确处理它们。 我们可以简化并尝试将所有这些事件分为两类:
- 网络错误
- 网络配置更改
如果我们使用Apache HTTP Client,那么已经有一种机制可以帮助我们,我们可以使用重试机制逻辑或默认实现来实现HttpRequestRetryHandler接口。 如果我们使用标准的Android HTTP连接,则我们必须自己实现。
处理连接错误
在这篇文章中,我展示了如何连接到远程服务器,并且我们创建了一个管理连接的HttpClient类。 在这种情况下,我们扩展此类来处理可能的网络错误。 为此,我们使用了回调机制,换句话说,我们设置了一个侦听器,该侦听器在发生连接错误时得到通知。 为此,我们创建一个接口:
public interface HttpConnectionRetryHandler {
public boolean shouldRetry(Throwable t, int attemptNumber) ;
}
此接口只有一种方法,我们可以在其中实现逻辑来处理或不处理网络错误。 我们传递异常和一个计数器,该计数器保存尝试重新建立连接的次数。 然后必须修改HttpClient以处理连接错误。 它不必连接到服务器就不必立即引发异常,而必须询问实现HttpConnectionRetryHandler的类是否应引发该异常或尝试再次连接。
public void connect(String method, Properties props) throws HttpClientException {
boolean status = true;
int attemptNumber = 0;
while (status) {
try {
attemptNumber++;
doConnection(method, props);
status = false;
}
catch(Throwable t) {
if (handler != null) {
status = handler.shouldRetry(t, attemptNumber);
if (!status)
throw new HttpClientException(t);
}
else {
throw new HttpClientException(t);
}
}
}
}
在第12行,当我们遇到异常时,我们调用handler.shouldRetry来验证我们的连接错误处理程序是否要处理该错误。 如果没有,我们将引发异常,否则我们将继续尝试重新连接。 在处理错误的类中,我们实现了业务逻辑。 最简单的事情是检查尝试次数。 在这种情况下,我们有:
public class DefaultHttpConnectionRetryHandler implements HttpConnectionRetryHandler {
@Override
public boolean shouldRetry(Throwable t, int attemptNumber) {
System.out.println("Attempt ["+attemptNumber+"]");
if (attemptNumber > 5)
return false;
return true;
}
}
因此,当我们调用HttpClient时,我们有:
...
client.setHandler(new DefaultHttpConnectionRetryHandler());
...
处理网络配置更改
正如我们在移动智能手机或平板电脑时所说的那样,网络配置可能会从WI-FI切换到UMTS,反之亦然,或者从UTMS切换到从一个APN切换到另一个(可能是漫游)。 我们必须处理所有这些更改,并尝试使用网络配置来重新建立连接。 为了处理这些事件,我们可以使用广播接收器 ,当网络配置发生变化时,它会得到通知。 APN配置 更改或连接更改由ConnectivityManager处理,该广播向其订户广播一些信息。 因此,我们首先对广播接收器进行编码:
public class ConnectionMonitorReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent intent) {
System.out.println("Receive..");
NetworkInfo netInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (netInfo == null)
return ;
System.out.println("Here");
if (netInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
String proxyHost = System.getProperty( "http.proxyHost" );
String proxyPort = System.getProperty( "http.proxyPort" );
if (proxyHost != null)
HttpClient.getInstance().setProxy(proxyHost, proxyPort);
else
HttpClient.getInstance().setProxy(null, null);
}
}
}
在第1行,我们只是扩展了BroadcastReceiver并实现了onReceive方法(第4行)。 在第6行,我们将信息传递到意图内,并实现了我们的逻辑。 在我们的案例中,我们仅检查代理是否已更改,但是我们可以实现其他类型的业务逻辑。
我们要做的最后一件事是注册广播接收器,以便可以对其进行调用。 我们在Activity的onCreate方法中执行此操作:
registerReceiver(new ConnectionMonitorReceiver(), new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
运行我们拥有的代码:
翻译自: https://www.javacodegeeks.com/2013/08/android-http-client-network-error-and-connectivitymanager.html