I am using the below code to download zip file in android.code works fine ,but sometimes download fails and throws socket exception. especially while Internet connection is slow(i guess).i have also posted the screen shots of logcat error message.
int count;
URL url = new URL(URL);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
//Log.e("ANDRO_ASYNC", "Lenght of file: " + "="+lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(StorezipFileLocation);
byte data[] = new byte[lenghtOfFile];
long total = 0;
while ((count = input.read(data)) != -1) {
total += c![enter image description here][1]ount;
publishProgress(""+(int)((total*100)/lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
connection reset by peer usually means that you are talking to a peer wich think that the connection has already been closed. What I don't understand is why it happens when closing a FileOutputStream.
Besides, the exception does not happen in your code but in the finalizer. Is it possible that when something goes wrong, you catch the exception in an upper level and leave the connection and file opened ? The abandonned connection is closed by the finalyser, but it's too late.
I am not sure that it will solves the problem but it is a good practice to use a finally clause to be sure that files and connections are properly closed.
The log doesn't say where the crash occurs in your code. Isn't there some more info that doesn't appear in your screenshot?
It seems that it fails on the close method of your file input stream.
You could simply surround the calls to close() with a try catch block and set your stream to null (if it failed on closing)
Related
I currently work on an app where I use the phone camera and open CV to process the frames. Now I thought it would be cool to be able to send the frames to another Android client. I thought frame by frame with steamer could work, but don't know how to setup the host and if it's not efficient. Any suggestions?
If you just want to send each frame as a raw set of data you can use sockets.
This code below is old now but it worked fine when last tested - it sends an entire video but you can use the same to send whatever file you want:
//Send the video file to helper over a Socket connection so he helper can compress the video file
Socket helperSocket = null;
try {
Log.d("VideoChunkDistributeTask doInBackground","connecting to: " + helperIPAddress + ":" + helperPort);
helperSocket = new Socket(helperIPAddress, helperPort);
BufferedOutputStream helperSocketBOS = new BufferedOutputStream(helperSocket.getOutputStream());
byte[] buffer = new byte[4096];
//Write the video chunk to the output stream
//Open the file
File videoChunkFile = new File(videoChunkFileName);
BufferedInputStream chunkFileIS = new BufferedInputStream(new FileInputStream(videoChunkFile));
//First send a long with the file length - wrap the BufferedOutputStream in a DataOuputStream to
//allow us send a long directly
DataOutputStream helperSocketDOS = new DataOutputStream(
new BufferedOutputStream(helperSocket.getOutputStream()));
long chunkLength = videoChunkFile.length();
helperSocketDOS.writeLong(chunkLength);
Log.d("VideoChunkDistributeTask doInBackground","chunkLength: " + chunkLength);
//Now loop through the video chunk file sending it to the helper via the socket - note this will simply
//do nothing if the file is empty
int readCount = 0;
int totalReadCount = 0;
while(totalReadCount < chunkLength) {
//write the buffer to the output stream of the socket
readCount = chunkFileIS.read(buffer);
helperSocketDOS.write(buffer, 0, readCount);
totalReadCount += readCount;
}
Log.d("VideoChunkDistributeTask doInBackground","file sent");
chunkFileIS.close();
helperSocketDOS.flush();
} catch (UnknownHostException e) {
Log.d("VideoChunkDistributeTask doInBackground","unknown host");
e.printStackTrace();
return null;
} catch (IOException e) {
Log.d("VideoChunkDistributeTask doInBackground","IO exceptiont");
e.printStackTrace();
return null;
}
The full source code is at: https://github.com/mickod/ColabAndroid/tree/master/src/com/amodtech/colabandroid
You may also find there are more up to date socket libraries available which might be better for you to use, but the general principles should be similar.
If you want to stream your video so that the other app can play it like a regular video it streams from the web, then you would want to set up a web server on the 'sending' device. At this point it might be easier to send it to a server and stream from there instead.
I am sending files between 2 devices, so I established a socket communication. Right now, I am just trying to send one file, but in the future I want to send multiple files (selected by the user from a gridview).
The problem is that when I send one file, on the server side (that receives the file) the socket.getInputStream().read(buffer) does not detect the end of the file. It just waits for "more" data to be sent.
After searching a bit on this issue, I reached some topics that kind of gave me some options, but I am still not satisfied with it because I dont know if those options would be efficient to send multiple files. This is an example : How to identify end of InputStream in java
I could close the socket or the stream objects after sending a file, but if I want to send a lot of files, it wouldn't be efficient to be always closing and opening the sockets.
Code on the receiver :
File apkReceived = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/testeReceiveServerComm.apk");
byte[] buffer = new byte [8192];
FileOutputStream fos=new FileOutputStream(apkReceived);
int count=0;
int total=0;//so apra ir vendo quanto recebi.
while((count = in.read(buffer)) != -1){
fos.write(buffer,0,count);
total+=count;
System.out.println("Server Comm receive thread - already received this ammount : "+total);
}
Code on the client (sender) :
File apkToSend=new File(filePath);
byte[] buffer = new byte [8192];
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(apkToSend));
int count;
int total=0;
while((count=bis.read(buffer))!=-1){
out.write(buffer,0,count);
total+=count;
out.reset();
System.out.println("send thread - already sent this ammount : "+total);
}
out.flush();
bis.close();
In my android application I am downloading large files from server(1GB) using the following:
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setReadTimeout(7000);
connection.connect();
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/Android/" + fileName, true);
byte data[] = new byte[1024];
int count;
int total = 0;
while (count = input.read(data)) > 0) {
total = total + count;
output.write(data, 0, count);
}
The code works well. But sometimes the downloaded file gets corrupted and I don't know why! Is there a mechanism or algorithm, library ... to guarantee a successful download 100%? Please help, I don't know what to do! I don't want to use checksum to check if the file is ok and if not then download it again! I want a solution to detect the problem while downloading and fix the corrupted portion instantly!
I'a using a asynctask to download file. It works normally until i turn off wifi connection (there are no other internet connection) of my android, download dialog still and no changes. When i check by log, i discover that function read() of inputstream is non stop. So how to check this case? here is my code:
URL url = new URL(this.url);
URLConnection connection = url.openConnection();
connection.setReadTimeout(1000);
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
fileName = "temp.zip";
// download the file
InputStream input = new BufferedInputStream(connection.getInputStream());
OutputStream output = new FileOutputStream(path+fileName);
byte buffer[] = new byte[1024000];
long total = 0;
int count;
Log.v("test download:","download in background");
while (((count = input.read(buffer)) != -1)) {
Log.v("test download:","read:"+count);
total += count;
publishProgress((int) (total * 100 / fileLength - 1));
output.write(buffer, 0, count);
}
Since you already set a timeout by calling setReadTimeout(), you should get a SocketTimeoutException shortly after the connection dropped.
Do your code happen to maybe capture this exception silently?
Your file download buffer size is too much byte buffer[] = new byte[1024]; is enough
when i try this Download a file with Android, and showing the progress in a ProgressDialog (top answer) with asynctask ,work fine, didn't get that problem
I am downloading on my android app. I am using a local network connection and the download is really slow.
Here's he code I am using:
URL url = new URL(ep.getFileURL());
File destFile = new File(<path to sd card file>);
URLConnection uCon = url.openConnection();
InputStream is = uCon.getInputStream();
OutputStream os = new FileOutputStream(destFile);
int progress = 0;
int lastProgress = 0;
int totalSize = uCon.getContentLength();
int downloadedSize = 0;
byte[] buffer = new byte[4096];
int count = -1;
while((count = is.read(buffer)) != -1)
{
os.write(buffer, 0, count);
downloadedSize = downloadedSize + count;
progress = (int)(downloadedSize * 100.0 / totalSize);
if(progress - lastProgress >= 5) {
publishProgress(progress);
lastProgress = progress;
}
}
os.close();
Do you spot any problems? thank you.
Edit:
I tested my code using your suggestions and I got these results:
# Download times tests #
Without bufferedoutput
Downloading file: 1 ms, Start download
Downloading file: 179812 ms, Finished downloading 54687744 bytes
Downloading file: end, 179813 ms
With bufferedoutput
Downloading file: 1 ms, Start download
Downloading file: 178312 ms, Finished downloading 54687744 bytes
Downloading file: end, 178313 ms
With httpclient
Downloading file: begin
Downloading file: 1 ms, Start download
Downloading file: 178241 ms, Finished downloading 54687744 bytes
Downloading file: end, 178242 ms
So, using Buffered streams or using HttpClient directly, doesn't change anything...
I also should have mentioned that my code is inside a AsyncTask, so publishProgress() actually runs on a separated thread already...
Thank you for your help.
You should wrap your input stream with a BufferedInputStream. You're probably getting a lot more shallow reads of a few bytes and a buffered stream will alleviate some of that. I would try that first, buffering both the input and output streams to reduce the OS level write delays.
Second, I'd be careful with how you are posting progress. It looks like you are limiting the number of times it comes up, but you might want to move the download into its own runnable and use an executor service for the download and maybe start an additional thread which evaluates the progress of all downloads and fires progress messages as necessary.
Use HttpClient instead of URLConnection