在我的Android应用程序中,我在进行远程HTTP时会遇到连接问题 (“轮询”)来自警报响起后启动的AsyncTask。
当标准Android设置“启用永远在线时,查找效果非常好 移动数据“(设置 - >无线和网络 - >移动网络)已启用 “on”。
解决方案有效:警报响起,Android“服务”收到警报意图, 启动后台线程(AsyncTask)。新线程获得部分唤醒 锁定,建立连接(轮询),通知用户并释放 唤醒锁。
到目前为止,这么好。问题是,当永远在线被“关闭”时,轮询会在大部分时间失败,如果 手机处于待机状态一段时间(> 30分钟)。
由于轮询线程发送通知,我直接得到反馈 不成功的投票尝试。
许多用户开启“永远在线”以减少电池消耗。所以,很可能 该应用用户遇到问题。我想处理或防止用户将面临的“错误”。
我经历了很多实验而没有任何重大突破:
似乎并非所有Android设备都具有“永远在线”设置。它似乎是设备,或者更可能是提供者依赖的。
答案 0 :(得分:0)
如果您打算实施实时通信协议,并尝试使用短期轮询,这可能会以类似的体验解决问题:
我们的应用程序有类似的要求,并注意到一些事项:
并非每个网络都具有“启用永远在线移动数据”首选项。我在使用DroidX的Verizon上,此选项不在菜单中。数据始终开启。
与您的想法相反,即使您没有部分唤醒锁定,当手机进入睡眠状态时,套接字也不会被杀死。当手机进入睡眠状态时,您的应用程序会停止接收广播事件(例如,连接更改事件),因此您不能依赖Android操作系统在临时断开数据连接时告诉您。不要进行报警轮询,而是考虑使用Keep-Alive发送HTTP请求的长轮询,并且无限期地保持连接打开,直到得到响应。
阻止套接字读取操作不会抛出IOException,EOFException,或者在丢弃信号时抛出其他信息,因此您需要有一个单独的线程定期检查网络状态。最简单的方法是使用NetworkInterface类并构建如下内容:
private OnCheckNetworkConnectivity networkConnectivityCallback = new OnCheckNetworkConnectivity() {
String ipAddress;
public boolean isConnected() {
String newIpAddress = getLocalIpAddress();
if(newIpAddress != null) {
if(ipAddress == null) {
ipAddress = newIpAddress;
return true;
}
if(!newIpAddress.equals(ipAddress)) {
ipAddress = newIpAddress;
return false;
}
// still the same IP address, we should still have the same connection
return true;
}
ipAddress = null;
return false;
}
public String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) {
return inetAddress.getHostAddress();
}
}
}
} catch (SocketException ex) {
return null;
}
return null;
}
};
答案 1 :(得分:0)
如果您使用的是AlarmManager,它应该唤醒设备。
我想知道在手机被唤醒之后,你是否正试图过快地建立连接,然后才有机会确保连接。
考虑:
检查AlarmManager接收器中的连接。如果没有连接,那么:
在从AlarmManager接收器返回之前,启动一个单独的线程。在帖子中:
尝试在收到CONNECTIVITY_CHANGE广播接收器的事件后才建立连接。