I use below code to download file:
URL u = new URL(one.getSrcPath());
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.setReadTimeout(10000);
c.connect();
int lenghtOfFile = c.getContentLength();
FileOutputStream f = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/" + SavePath, FileName);
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
int finishbyte = 0;
long total = 0;
while((len1 = in.read(buffer)) > 0) {
total += len1; //total = total + len1
f.write(buffer, 0, len1);
finishbyte++;
}
f.close();
I have two problems:
First, why my download task download fail very high frequency?
Second, if I want my download task resume from break point.
I have get the finishbyte.
How can I modify?
finishbyte both does not represent any information (except the number of calls to the read method, but certainly not the size of the downloaded file), and is not relevant, since you have written to a file and can use the File.length() method to know how much you got so far.
To resume a download:
Open your file, check the size, request a range using the http header that is:
Range: <file.length()>-
(example, if you have downloaded 234 bytes:
Range: 234-
If the response code from the server is 206 Partial Content, you can append to your file, if it is 200, you have to overwrite your file (content have changed or Range is not supported)
To start downloading a file starting with finishbyte position, you will have to use the Range HTTP header. As for the failed downloads problem, it's probably a network issue or phone sleep issue, in which case you should check out the wifi lock
Related
I want to install the update automatically as my APK is not on the Play store. So I tried the following:
I followed all the steps given in
http://www.wepstech.com/download-and-install-app-programmatically/
Below is the Async Task: (URL given is correct)
URL url = new URL(arg0[0]);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
int lenghtOfFile = c.getContentLength();
String PATH = Objects.requireNonNull(mContext.getExternalFilesDir(null)).getAbsolutePath();
File file = new File(PATH);
boolean isCreate = file.mkdirs();
File outputFile = new File(file, "my_apk.apk");
if (outputFile.exists()) {
boolean isDelete = outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int len1;
long total = 0;
while ((len1 = is.read(buffer)) != -1) {
total += len1;
fos.write(buffer, 0, len1);
publishProgress((int) ((total * 100) / lenghtOfFile));
}
fos.close();
is.close();
if (mPDialog != null)
mPDialog.dismiss()
;
I have an API checking the version and if the version is old I have given a button to download and install, So when I do that the apk is getting downloaded only (but not a full-size file) I see only 189bytes. The Async just closes thinking the file has downloaded it starts to install and when it does it gives "There was a problem parsing the package".
It is because the APK file not downloaded fully.
I am not sure why the file is not getting downloaded fully. It is an 8MB file. And I am running Android 11.
you can use the lib fetch, it's a best file downloader library for android
https://github.com/tonyofrancis/Fetch
For example I am downloading a file from server, in between the connectivity is lost at that point in time my download was 30%, after some time I got a connection .Now I want to start a downloading from 30%, not from 0%.How to achieve this asynctask android.
If any alternative is there please, let me know.???
You need to first figure out how many bytes you have actually downloaded. I suggest saving your file with an different name when it's being downloaded so you can can easily see if you have an unfinished download.
Check the status of you file first to see how much you have downloaded.
private long isIncomplete(){
File from = new File(dir,fileName+"-incomplete");
if(from.exists()){
Log.d("status","download is incomplete, filesize:" + from.length());
return from.length();
}
return 0;
}
Then when creating your http request you can tell the server from what point to serve you the file so that you can resume download.
long downloaded = isIncomplete();
urlConnection.setRequestProperty("Range", "bytes="+(downloaded)+"-");
See this class that I wrote a few years back for a complete implementation.
Update: I suggest you do not use the Shared Preferences for this. SSOT states that you get the info from only one source not more hence reading the progress from the downloaded file.
You can store the destination file path in sharedpreferences and you can do the following code.
HttpURLConnection connection = (HttpURLConnection) url.openConnection();//Opening the url
File file=new File(DESTINATION_PATH);
if(file.exists()){ //check if file exists
downloaded = (int) file.length();
connection.setRequestProperty("Range", "bytes="+(file.length())+"-");
}
else{
connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
}
connection.setDoInput(true);
connection.setDoOutput(true);
pBar.setMax(connection.getContentLength());
in = new BufferedInputStream(connection.getInputStream());
fos=(downloaded==0)? new FileOutputStream(DESTINATION_PATH): new FileOutputStream(DESTINATION_PATH,true);
bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
int x = 0;
while ((x = in.read(data, 0, 1024)) >= 0) {
bout.write(data, 0, x);
downloaded += x;
pBar.setProgress(downloaded);
}
i m making an android app to download pdf files from android and then saving them in a folder in internal or external memory.but sometime due to bad internet connection download stops without finshing .like file size is 1.1mb and its only downloaded upto 750kb. now the problem is whether file fully download or not my app showing it as download but in real it is not.so i want to know the exact size of file befor and after download so that i can found whether file is completely download or not.and want to restart the download.
can anybody help me........
my code
String DownloadUrl = "http://www.example.com/books/"+book_name;
String fileName = book_name;
URL url = new URL(DownloadUrl);
//create the new connection
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
//and connect!
urlConnection.connect();
//set the path where we want to save the file
//in this case, going to save it on the root directory of the
//sd card.
// File SDCardRoot = new File("/storage/emulated/0/documents/docx/stuff/");
File SDCardRoot = new File(Environment.getExternalStorageDirectory()+File.separator+"MybookStore/paper/paperStuff/documents/docx/other/stuff/");
//create a new file, specifying the path, and the filename
//which we want to save the file as.
File file = new File(SDCardRoot,fileName);
String file_size = Long.toString(file.length()/1024);
int size_file=Integer.parseInt(file_size);
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(file);
//this will be used in reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file
int totalSize = urlConnection.getContentLength();
//variable to store total downloaded bytes
int downloadedSize = 0;
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
//now, read through the input buffer and write the contents to the file
while ( (bufferLength = inputStream.read(buffer)) > 0 )
{
//add the data in the buffer to the file in the file output stream (the file on the sd card
fileOutput.write(buffer, 0, bufferLength);
//add up the size so we know how much is downloaded
downloadedSize += bufferLength;
int progress=(int)(downloadedSize*100/totalSize);
//this is where you would do something to report the prgress, like this maybe
//updateProgress(downloadedSize, totalSize);
}
my code
Any reasonable server response header will include a Content-Length key, which will hopefully denote the full length of the resource you’re trying to download.
With that in mind, here's a quick example:
HttpURLConnection connection = null;
InputStream input = null;
OutputStream output = null;
try {
final URL url = new URL(resourceUrl);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
final int length = connection.getContentLength();
int downloaded = 0;
input = url.openStream();
output = new FileOutputStream(targetFile);
final byte[] buffer = new byte[BUFFER_SIZE];
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
downloaded += read;
}
if (downloaded == length) {
// The file was successfully downloaded.
} else {
// The file was not fully downloaded.
}
} catch (IOException e) {
// Handle exception.
} finally {
// Close resources.
}
working on my first real android app and one part of it is a download manager.
it must download video files that the app uses to teach people Gaelic.
it works fine on all but 3 files, it downloads bigger files and smaller files. but will not download colours.mp4 1.86MB, weekdays 1.53 MB or numbers 1.99 MB all the files between 1MB and 2MB.
it will just stop at the end of the download loop no errors for a few minutes just looking like its waiting to continue downloading then it will give an error "unexpected end of stream"
can anyone suggest what the problem could be please?
I have crated the same app for the iPhone and that app has not got the same problem with these files.
this is the download loop called from inside an asynctask.
protected void download(String where, String file){
try {
//makes output file
OutputStream output = new FileOutputStream(getFilesDir()
.getAbsolutePath() + "/vidos/" +file);
int count=0;
//gets url to download from
URL url = new URL(where);
URLConnection conection = url.openConnection();
conection.connect();
//gets the length of the file to work out percent downloaded
int lengthOfFile = conection.getContentLength();
InputStream input = null;
Log.v("downloading", String.valueOf(showprg));
input = new BufferedInputStream(url.openStream());
byte data[] = new byte[lengthOfFile];
long total = 0;
Log.v("downloading", "size: " + String.valueOf(downloading));
while ((count = input.read(data)) > 0 && downloading) {
total += count;
publishProgress(String
.valueOf((int) ((total * 100) / lengthOfFile)));
output.write(data, 0, count);
//this is where it brakes
};
Log.v("publishProgress", "done");
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
}
I changed my URLConnection to a HttpURLConnection and removed the BufferedInputStream and now it downloads without problem.
thanks to Harshit Rathi for his link to Cristian's post
I have this snippet of code in which I want to handle the downlaod of the file being clicked:
else if (url.startsWith("http://rapahh.com/songs2/Music%20Promotion/Download/")) {
}
return false;
Although I have no idea how to handle downloads in Android, so does anyone have a snippet of code I can use to download the file in the background to a folder.. the download folder is fine. Thanks.
What version of android are you building for?
Starting with API lvl 9 there is the DownloadManager that can handle this for you. If at all possible you should use the DownloadManager, because it will automatically handle network interuptions and resume the downloads for you.
If you are aiming for lower API lvl than that you'll have to make the download code yourself. You'll have an inputStream coming from your web source and an outputStream going to your local file and you will loop through the inputStream writing chunks until there are none left.
Something like this:
try {
URL url = new URL(URL); //URL of the video
//Set our file to the correct path and name.
File file = new File(PATH + fileName);
//keep the start time so we can display how long it took to the Log.
long startTime = System.currentTimeMillis();
Log.d(myTag, "download begining");
//Log.d(myTag, "download url:" + url);
Log.d(myTag, "downloaded file name:" + fileName);
/* Open a connection to that URL. */
URLConnection ucon = url.openConnection();
// this will be useful so that you can show a tipical 0-100% progress bar
int lenghtOfFile = ucon.getContentLength();
Log.i(myTag, "Opened Connection");
/************************************************
* Define InputStreams to read from the URLConnection.
************************************************/
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Log.i(myTag, "Got InputStream and BufferedInputStream");
/************************************************
* Define OutputStreams to write to our file.
************************************************/
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
Log.i(myTag, "Got FileOutputStream and BufferedOutputStream");
/************************************************
* Start reading the and writing our file.
************************************************/
byte data[] = new byte[1024];
long total = 0;
int count;
//loop and read the current chunk
while ((count = bis.read(data)) != -1) {
//Post our progress update back to the UI thread
postProgress((int)(total*100/lenghtOfFile));
//write this chunk
total += count;
bos.write(data, 0, count);
}
//Have to call flush or the video file can get corrupted and won't play correctly.
bos.flush();
bos.close();
Log.d(myTag, "download ready in "
+ ((System.currentTimeMillis() - startTime))
+ " milisec");
} catch (IOException e) {
Log.d(myTag, "Error: " + e);
}
You'll need to implement the postProgress(int progress) method to do whatever is appropriate for your application to inform the user of what percentage complete the download is.
Edit:
you can comment out the logs to get it to work. I leave them on while I am debugging though to make the process easier. Log statements such as Log.i(String tag, String text)
are similar to System.out.println(String txt) The difference is that these statements are printed into the log file ( which you can see in the DDMS perspective in eclipse) And they have an additional parameter called "tag" you can pass it whatever string you like and this string will show up along side of your text in the log file. You can also filter the log output basted on these tags in the DDMS perspective. It is common practice to declare your tag as a static String so that you can just use that reference to it for all of your log statements and you are guaranteed to always have the same tag. So if you add something like this to your class it should fix your error:
final static String myTag = "NameOfYourActivity";