I originally posted this in my library’s thread in Networking & Multiplayer, but this is a complicated issue that if anyone else encounters will likely want to find the answer easily, so I made this thread. I was working today on fixing the issue where my auto-updater/patcher freezes when internet connection is lost in the middle of a download, and I came up with a solution that seemed to work. The download would be run on a separate thread and if the thread takes longer to finish than expected the internet connection would be checked and if there is not internet then “return;” would be called in the method after something was printed to the console about how the download was aborted due to internet being lost. This is the code:
ReadableByteChannel rbc = null;
FileOutputStream fos = null;
try {
// creates file in temporary directory to be downloaded to, so that the main file isn't lost if the download is aborted
File temp = File.createTempFile("tempFile", filePath.substring(filePath.lastIndexOf('.'), filePath.length()));
// the file will be deleted upon exit unless the download is aborted mid-way
temp.deleteOnExit();
URL file = new URL(fileSite);
URLConnection urlconnection = file.openConnection();
urlconnection.setReadTimeout(5000);
long size = urlconnection.getContentLength();
rbc = Channels.newChannel(file.openStream());
fos = new FileOutputStream(temp);
long position = 0;
if(usingChunks)
while(position < size){
if(!hasInternet)
return;
// downloads chunkSize bytes and increases the position on the download accordingly
final long finalPosition = position;
final FileOutputStream finalFos = fos;
final ReadableByteChannel finalRbc = rbc;
Thread download = new Thread(new Runnable(){
public void run(){
try {
if(hasInternet)
finalFos.getChannel().transferFrom(finalRbc, finalPosition, chunkSize);
} catch (IOException e) {
e.printStackTrace();
}
}
});
download.start();
long timeout = chunkSize;
try {
download.join(timeout);
} catch (InterruptedException e) {
ErrorLogger.logError(e);
return;
}
if(download.isAlive())
if(!isInternetReachable())
if(!hasInternetFallback()){
// this is a nested if because I only want to check internet if the above requirement works because checking internet takes some time
System.out.println("Internet connection lost");
hasInternet = false;
return;
}
position += chunkSize;
// position += fos.getChannel().transferFrom(rbc, position, chunkSize);
// sets progress to the nearest tenth of the amount of bytes downloaded out of the total
progress = Math.round((float)(100 * (float)position / (float)size) * (float)10) / (float)10;
System.out.println(progress + "% done");
}
The error is that if internet connection is lost the transferFrom method keeps running and running and running and running and running… It just doesn’t stop. I really wish it would throw an exception but it just keeps running. This makes it so that when the checkForUpdate() method (the method from which the excerpt that is posted is from) tries to stop, the thread still running prevents the main method that called checkForUpdate() to advance further down the code line (which in my main method for testing would involve launching the extracted zip file’s jar). Do you know how I can fix this? After searching on Google for an hour or two, I’m completely clueless.