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";
Related
I want to download all the images I have on server in the array string of Url one by one so that I may do not have to download a zip file of images from the server and to unzip after downloading it.
So I thought to download the images one by one and to show the download status in the progress bar. But I am extremely failed in it. An Idea came into my mind to make the string array of the Url and to use the For loop to download but it is downloading the last image of the String array and decline or pass all other images in the array . I think I have got the idea that what is going on but I have know Idea what would be the solution then.
What I have done So far
protected Void doInBackground(Void... arg0) {
try {
//set the download URL, a url that points to a file on the internet
//this is the file to be downloaded
String [] imageUrl = {"http://www.androidbegin.com/tutorial/flag/india.png","http://www.androidbegin.com/tutorial/flag/pakistan.png"
,"http://www.androidbegin.com/tutorial/flag/china.png","http://www.androidbegin.com/tutorial/flag/unitedstates.png"};
URL url;
HttpURLConnection urlConnection = null;
for(int i=0;i<imageUrl.length;i++){
url = new URL(imageUrl[i]);
//create the new connection
urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
//and connect!
urlConnection.connect();
}
File storagePath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Test");
storagePath.mkdirs();
String finalName = Long.toString(System.currentTimeMillis());
File myImage = new File(storagePath, finalName + ".png");
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(myImage);
//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;
//this is where you would do something to report the prgress, like this maybe
// updateProgress(downloadedSize, totalSize);
}
//close the output stream when done
fileOutput.close();
//catch some possible errors...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// see http://androidsnippets.com/download-an-http-file-to-sdcard-with-progress-notification
return null;
}
** What I want :**
Download all the images one by one.
After downloading one Image it should get save in the device and update the progress status.
Please show me some source code rather then giving me just Idea how to do it. And little source code and complete work around on this would be appreciated.
the saving image code should be taken inside for loop. as this code is outside of for loop only your last image is getting saved as at the end of for loop last url is used.
I am trying to download a PPT file from a server.
it's in Bytes.
but while debugging I noticed that the input stream throws an exception of FileNotFound while running.. the file does exist on the server, here's my code, any help would be greatly appreciated.
public class DownloadFileAsync extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.addRequestProperty("Authorization", "Basic " + SharedPref.getAuthPrefValue());
connection.addRequestProperty("Device", BaseApplication.getCurrentDevice().getDevice().toString());
connection.addRequestProperty("DeviceId", BaseApplication.getCurrentDevice().getDeviceId());
connection.connect();
int lengthOfFile = connection.getContentLength();
Log.d("ANDRO_ASYNC", "Length of file: " + lengthOfFile);
InputStream input = new BufferedInputStream(url.openStream());
File sdcardDest = new File(Environment.getExternalStorageDirectory(), "Availo");
String finalDest = sdcardDest + File.separator + "Check1" + "." + "PPT";
OutputStream output = new FileOutputStream(finalDest);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lengthOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
I am using Charles on Mac (which is similar to fiddler on windows.) to see what I send and receive from the server,
The server doesn't return any error, though it shows download steps for 6-7 sec, downloading around 400 bytes and then it stops.
The Exception is thrown from the input stream line.
Thanks!
I suggest you take a look at the DownloadManager system service. it's designed specifically for what you are trying to do:
(from the documentation)
The download manager is a system service that handles long-running
HTTP downloads. Clients may request that a URI be downloaded to a
particular destination file. The download manager will conduct the
download in the background, taking care of HTTP interactions and
retrying downloads after failures or across connectivity changes and
system reboots
While I do agree with Muzikant regarding the download manager,
FileNotFoundException is usually thrown when... the file is not found on the local device...
You need to do the following to make sure it doesnt happen
File dest = new File(finalDest);
try{
File parentDest = dest.getParentFile();
if(!parentDest.exists()){
parentDest.mkdirs(); //make all the directory structures needed
}
if(!dest.exists()){
dest.createNewFile();
}
OutputStream output = new FileOutputStream(dest);
//now you can use your file dest
//write data to it...
}catch (Exception e){
}
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 created an app which allows the user to download audio file and store it in their SD card. The code below is actually working, but the problem is every time I hit the download button, the whole app freezes until the download is over. How can I solve this issue so that it wont freeze whenever I hit the download button? Please help me, I have been struggling for days trying to figure out te solution for this, I would really appreciate your help a lot. Thanks in advance.
try {
URL url = new URL("http://www.yourfile.mp3");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String PATH = Environment.getExternalStorageDirectory()
+ "/download/";
Log.v("", "PATH: " + PATH);
File file = new File(PATH);
file.mkdirs();
String fileName = "yourfilename.mp3";
File outputFile = new File(file, fileName);
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
}catch (IOException e) {
e.printStackTrace();
}
}
Since your download method works downloading your file, it will create an impression like the app has freezed. But the truth is your method is executing in the back. So to avoid app freeze you can show an ProgressDialog til the download method is downloading and after it gets executed you can cancel the ProgressDialog.
So you have to use a separate thread to download. Here is the link which explains you how to download and show an progressDialog in the mean time.
http://www.bogotobogo.com/Android/android23HTTP.html
Each time you click the button call the AsynchTask.Do your downloading in the doInBackground method. this class is designed exactly for the kind of work you are looking for.Use doInBackground() method to accomplish the task and onPreExecute you can show a progress Dialog.
I am working on an application that plays a video file on a loop. Up until now I was just mounting the device and copying the video file onto the SD card and then using the file path to start it up on my VideoView. I am trying to implement a way that I can remotely update what video it plays so I have moved to storing my video online. Inside the app I check for a local copy and download if it doesn't exist, or if there is a newer one. I have tested it on two different video files both .mp4s. After downloading one of them plays the first time but upon trying to start again for the loop it tells me video cannot be played. The other won't even play the first time, it just gives me the dialog that says the video cannot be played. Both of these files work correctly with my app if I copy them onto the SD card via the USB cable. They work if I exit my app and manually download them with something else(dropbox) but not if I download them from within my app. Here is the code I am using to download the file:
public static void DownloadFromUrl(String fileName) { //this is the downloader method
try {
URL url = new URL("http://dl.dropbox.com/u/myfile.mp4");
File file = new File(PATH + fileName);
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();
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");
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
Log.i(myTag, "Got FileOutputStream and BufferedOutputStream");
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
int current = 0;
Log.i(myTag, "About to write");
while ((current = bis.read()) != -1) {
bos.write(current);
}
fos.close();
Log.d(myTag, "download ready in"
+ ((System.currentTimeMillis() - startTime))
+ " sec");
} catch (IOException e) {
Log.d(myTag, "Error: " + e);
}
}
I know the dropbox url in this snippet is not correct I changed it only for this post, in my app the url is pointing to a file correctly. And the variable PATH thats used when creating the File is set in my code outside of this snippet.
Is there something about this code snippet that could be corrupting my mp4 files?
That method was corrupting the file somehow, I am still not quite sure how but I changed part of it and now it is fixed.
I am now using this:
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = bis.read(data)) != -1) {
total += count;
fos.write(data, 0, count);
}
fos.flush();
fos.close();
instead of the old while loop and it works correctly.