我感觉应该是一个已解决的问题。我正在编写的 Android 应用程序发送一条消息,就像用户可以附加文件的 SMS 一样。我正在使用 HttpUrlConnection 将此数据发送到我的服务器,这基本上归结为 java.io.OutputStream(我将其包装在 DataOutputStream 中)。
在移动设备上,有时网络连接可能非常糟糕,发送可能需要太长时间。我有以下两个基本问题:
- 用户无法知道上传进度
- 如果网络很糟糕并且进展很糟糕 - 我宁愿中止或有一些合理的超时,而不是坐在那里尝试 5-10 分钟。
问题1:
我试图根据我正在使用 4K 缓冲区执行的输出流 write() 调用来显示上传进度:
buffer = new byte[4096];
long totalBytes = 0;
while ((bytesRead = fis.read(buffer)) > -1) {
totalBytes += bytesRead;
dos.write(buffer, 0, bytesRead);
if(showProgress){
updateProgressBar(totalBytes);
}
}
虽然这向我展示了进展,但它似乎只是向我展示了应用程序将文件缓冲区传输到操作系统网络堆栈缓冲区的速度。即使在慢速网络上,进度条也很快完成,然后在我最终从服务器获取 JSON 并告诉我发送状态之前又在那里停留了很长时间。从我将它传递给操作系统到我的服务器告诉我它收到它的时间,肯定有一些方法可以取得一些进展吗?
问题2:
有时网络连接很糟糕,但还不够糟糕,以至于硬件无线电触发未找到连接的回调(在这种情况下,我进入离线模式)。所以当它很糟糕但没有关闭时,我的应用程序只会坐在发送对话框中,直到奶牛回家。这与问题 1 相关,因为我需要以某种方式了解实际吞吐量,因为 OutputStream 本身不提供超时机制。如果它低于某个阈值,我可以取消连接并通知用户他们需要去一个接收良好的地方。
旁注:异步发送/输出队列对我来说不是一个选项,因为我无法将消息持久化到磁盘,因此不能保证起草的消息是无限期的,以防它在稍后的某个时间点发送失败。我需要/想要阻止发送,我只需要更聪明地放弃和/或通知用户正在发生的事情。