I am new in android and i ask a question about my thread that i create. I think it is stupid question but I am sorry.I have a onClick button listener. Its job is get the URL download link and stores in a variable.
/**
* this method invoke from setPositiveButton's dialog
*
* #param rootView
*/
private void addURLToList(View rootView) {
editTextAddURL = (EditText) rootView.findViewById(R.id.editText_add_url);
Log.i("===", "addURLToList: " + editTextAddURL.getText());
stringUrl = editTextAddURL.getText().toString();
*start GetSizeOfFile thread for getting size file and store
* in lenghtOfFile variable
*/
new GetSizeOfFile().start();
Log.i("====", "size of file after Thread: " + lenghtOfFile);
}
I create a Thread because I want to get file size.
private class GetSizeOfFile extends Thread {
#Override
public void run() {
super.run();
try {
URL url = new URL(stringUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
lenghtOfFile = connection.getContentLength();
Log.i("====", "size of file in Thread: " + lenghtOfFile);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
everything is ok but when thread is started ,after few second my lenghtOfFile variable is initialized and I got 0 in lenghtOfFile in this Line Log.i("====", "size of file after Thread: " + lenghtOfFile);
this is my logcat:
02-22 10:02:11.352 11333-11333/com.example.manifest.simplefiledownloadmanager I/===: addURLToList: http://dl2.soft98.ir/soft/a/Adobe.Shockwave.Player.12.2.7.197.IE.rar
02-22 10:02:11.352 11333-11333/com.example.manifest.simplefiledownloadmanager I/====: file name : Adobe.Shockwave.Player.12.2.7.197.IE.rar
02-22 10:02:11.352 11333-11333/com.example.manifest.simplefiledownloadmanager I/====: size of file after Thread: 0
02-22 10:02:36.544 11333-11495/com.example.manifest.simplefiledownloadmanager I/====: size of file in Thread: 13524394
I want to get file's size from thread first.is it correct that I have to sleep the thread or exit standard way?sorry I am new in android
When working with threads you cannot assume their order of execution.
What happens in your case I presume is that while your new thread is waiting on the connection to be established, the original thread is being run with the uninitialized lenghtOfFile variable so the log looks like it does. Another possibility is that the new thread didn't even begin running when the lenghtOfFile=0 line was logged. That is just how threads work.
For this exact purpose the ASyncTask class exists in Android.
Your code should be somewhat like this:
private class GetSizeOfFile extends AsyncTask<String, Void, Long> {
// runs on a background thread
protected Long doInBackground(String... stringUrls) {
String stringUrl = stringUrls[0];
try {
URL url = new URL(stringUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
long lenghtOfFile = connection.getContentLength();
return lenghtOfFile;
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
// runs on main thread
protected void onPostExecute(Long lenghtOfFile) {
if (lenghtOfFile == -1) {
// something went wrong
} else {
Log.i("====", "size of file: " + lenghtOfFile);
// whatever else you want to do
}
}
}
new GetSizeOfFile().execute(stringUrl);
Related
Got an weird issue. A file with Url: https://s3.amazonaws.com/myappdata/msg/171401089927.mp3 (not available any more) downloads ok on PC and its mp3 file. But when I try to DL it on Android FOA Im getting content-type "application/xml" instead of "audio/mpeg" and when downloading starts I'm getting:
05-30 12:13:44.478: E/PlayerService(28023): java.io.FileNotFoundException: https://s3.amazonaws.com/myappdata/msg/171401089927.mp3
05-30 12:13:44.478: E/PlayerService(28023): at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
05-30 12:13:44.478: E/PlayerService(28023): at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:270)
The code used to DL:
/**
* Download the url stream to a temporary location
*/
public void downloadAudioIncrement(String mediaUrl) throws IOException {
Log.i(TAG, "downloadAudioIncrement(): mediaUrl: "+mediaUrl+"\ncacheDir: "+cacheDir);
URL url = null;
try {
url = new URL(mediaUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
throw new IOException("Unable to create InputStream for mediaUrl:" + mediaUrl);
}
// this file will represent whole downloaded song
mp3FileDownloaded = new File(cacheDir, mp3FileName);
if (!mp3FileDownloaded.exists())
//FileUtils.makeDirsForFile(mp3FileDownloaded);
try{
mp3FileDownloaded.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
if (!mp3FileDownloaded.canWrite())
throw new IOException("Can't open temporary file for writing");
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setReadTimeout(1000 * 20);
urlConnection.setConnectTimeout(1000 * 5);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
int mp3BytesSize = urlConnection.getContentLength();
// final String
// contentLengthStr=urlConnection.getHeaderField("content-length");
String ctype = urlConnection.getContentType();
if (ctype == null) {
ctype = "";
} else {
ctype = ctype.toLowerCase(Locale.US);
}
// See if we can handle this type
Log.i(TAG, "Content Type: " + ctype);
if ( ctype.contains("audio/mpeg") || TextUtils.isEmpty(ctype) ) {
String temp = urlConnection.getHeaderField(BITRATE_HEADER);
Log.i(TAG, "Bitrate: " + temp);
// if (temp != null){
// bitrate = new Integer(temp).intValue();
// }
} else {
Log.e(TAG, UNSUPPORTED_AUDIO_TYPE+": " + ctype);
// throw new IOException(UNSUPPORTED_AUDIO_TYPE+": " + ctype);
// Log.e(TAG, "Or we could not connect to audio");
// stop();
// return;
}
final InputStream stream = new BufferedInputStream(urlConnection.getInputStream(),8192);
...
Right at the last shown line of code (instantiating the InputStream stream) the mentioned IOExeption raised. There are other mp3 files exists at same location and they are downloading with no any issue but only mentioned above url fails.What could be wrong here?
UPDATE
Its appears that this issue happens on HTC Rezound with AOS 4.0.4. On other device, with AOS 2.3.5 everything works ok.
seems like the line
urlConnection.setDoOutput(true);
was the source of issue since I don't upload any data. Everything works fine since I'd comment it. Also these FileNotFoundException while getting the InputStream object from HttpURLConnection and Android HttpUrlConnection getInputStream throws NullPointerException threads might be helpfull.
I have followed some online tutorials and created this code to download the files that i have hosted in dropbox
I am using async task to do this
// AsyncTask to download a file
private class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
wl.acquire();
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error
// report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK)
return "Server returned HTTP "
+ connection.getResponseCode() + " "
+ connection.getResponseMessage();
// TODO
File file = new File(Environment
.getExternalStorageDirectory().getPath()
+ "/kathmandu.map");
if (file.exists()) {
Log.i("File Exists", "Code Gets here, file exists");
return "exists";
// if (connection.getResponseCode() ==
// HttpURLConnection.HTTP_NOT_MODIFIED) {
//
// return null;
// }
}
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
Log.i("Length", String.valueOf(fileLength));
// download the file
input = connection.getInputStream();
output = new FileOutputStream(Environment
.getExternalStorageDirectory().getPath()
+ "/kathmandu.map");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled())
return null;
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
} finally {
wl.release();
}
return null;
}
I call the download code when the download options menu is clicked.
final DownloadTask downloadTask = new DownloadTask(MapActivity.this);
downloadTask
.execute("https://dl.dropboxusercontent.com/u/95497883/kathmandu-2013-8-12.map");
mProgressDialog
.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
The code works fine but at the times the outputstream does not write full file and exits. Everything looks okay. The file is downloaded but it is corrupted.
The getContentLength() also returns -1 so i cannot check if the whole file has been downloaded using the content length. The file is a offline vector map and i need it to display offline maps. The corrupted file causes a runtime exception while trying to access it. Is there is any way to ensure that the file has been downloaded correctly.
Also i would like to provide the data with the app itself. Can i put this in the assets folder of my app. What is the best way to access the files in the assets folder during runtime.
Your assets folder is not writable as it is a part of the apk. you can of course use your application's sandbox storage (using Environment.getDir() ) or external storage (using Environment.getExternalStorageDirectory()) like you have done in your code.
I think using the DownloadManager would be a great idea to achieve exactly what you want please refer : http://developer.android.com/reference/android/app/DownloadManager.html
a short solution
DownloadManager.Request req=new DownloadManager.Request(url);
req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
| DownloadManager.Request.NETWORK_MOBILE)
.setTitle("Downloading")
.setDescription("Map is Being Downloaded")
.setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory,
"+/maps_app/something.map");
I'm not really sure what goes wrong with my code or structure. I wanted to use AsyncTask to download images and display out the progress bar at the mean time. But I tried out a few different way of doing it. It still failed and no idea what's wrong with it. My structure flow is
ContentID is a string array that stores the content ID of the Images.
Primary Issue: It managed to download images from the url and store into the phone, but the downloaded images are all the same image. It should be different images, it's not what I expected.
Secondary Issue: The progress bar pop up while the application downloading images, but the progress bar did not update it's progress. It just remains 0% and dismissed after the download completed.
I wanted to know what causes primary and secodary issue as i mentioned. Please leave a comment or answer if you might know what's wrong with my code. Any help will be appreciated.
if(isSyncSuccess){
SetConstant.IMAGE_EXIST = 1;
pDialog = new ProgressDialog(GalleryScreen.this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setProgress(0);
pDialog.setMax(contentId.length);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
if (contentId.length>0){
Log.i(TAG, "contentid.length:" +contentId.length);
for (int i=0;i<contentId.length;i++){
if(helper.databaseChecking(useremail, contentId[i])){
contentdownload = i;
SetConstant.CONTENT_ID = contentId[i];
String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];
DownloadFile downloadFile = new DownloadFile();
downloadFile.execute(URL);
}
private class DownloadFile extends AsyncTask<String, Integer, String>{
#Override
protected String doInBackground(String... sUrl){
Bitmap bm;
InputStream in;
try{
in = new java.net.URL(sUrl[0]).openStream();
bm = BitmapFactory.decodeStream(new PatchInputStream(in));
File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
Log.i(TAG,"storage:" +storage);
Log.i(TAG,"storage:" +storage.getAbsolutePath());
if(!storage.exists()){
storage.mkdirs();
}
String FileName = "/"+SetConstant.CONTENT_ID+".jpg";
FileOutputStream fos = new FileOutputStream(storage + FileName);
bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);
String filepath = storage + FileName;
File filecheck = new File (filepath);
long fileSize = filecheck.length();
fos.flush();
fos.close();
Log.i(TAG, "bm:" +bm);
Log.i(TAG, "fos:" +fos);
Log.i(TAG, "filesize:" +fileSize);
Log.i(TAG, "filepath:" +filepath);
}
catch(IOException e1){
e1.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute(){
super.onPreExecute();
pDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress){
super.onProgressUpdate(progress);
pDialog.setProgress(progress[0]);
}
protected void onPostExecute(String result){
super.onPostExecute(result);
pDialog.dismiss();
}
}
Edit
Now the application able to download images according and the progress bar is working as well! But I got another issue is how to return error message when the application failed to complete the download. Currently when the application failed to download it will crash. I believed that I should not run it inside the doInBackground side. But where else can I do the checking? Any idea how to return as an error message and request for the user to retry instead of crashing the application?
You never called onProgressUpdate during your doInBackGround(...). Please note that running multiple instances of AsyncTask is a bad idea. Here is what I suggest:
if(isSyncSuccess){
SetConstant.IMAGE_EXIST=1;
pDialog=new ProgressDialog(GalleryScreen.this);
pDialog.setMessage("Downloading file. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setProgress(0);
pDialog.setMax(contentId.length);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setCancelable(true);
new DownloadFile().execute();
}
private class DownloadFiles extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
Bitmap bm;
InputStream in;
if (contentId.length > 0) {
for (int i = 0; i < contentId.length; i++) {
if (helper.databaseChecking(useremail, contentId[i])) {
contentdownload = i;
SetConstant.CONTENT_ID = contentId[i];
String URL = SetConstant.URL_DOWNLOAD_CONTENT + contentId[i];
//YOUR INTRESTING LOOP HERE.
publishProgress(30);
//SOME INTRESTING NUMBER FOR PROGRESS UPDATE
}
}
try {
in = new java.net.URL(sUrl[0]).openStream();
bm = BitmapFactory.decodeStream(new PatchInputStream(in));
File storage = new File(Environment.getExternalStorageDirectory() + File.separator + "/Image/");
Log.i(TAG, "storage:" + storage);
Log.i(TAG, "storage:" + storage.getAbsolutePath());
if (!storage.exists()) {
storage.mkdirs();
}
String FileName = "/" + SetConstant.CONTENT_ID + ".jpg";
FileOutputStream fos = new FileOutputStream(storage + FileName);
bm.compress(Bitmap.CompressFormat.JPEG, 85, fos);
String filepath = storage + FileName;
File filecheck = new File(filepath);
long fileSize = filecheck.length();
fos.flush();
fos.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute () {
super.onPreExecute();
pDialog.show();
}
#Override
protected void onProgressUpdate (Integer...progress){
super.onProgressUpdate(progress);
pDialog.setProgress(progress[0]);
}
protected void onPostExecute (String result){
super.onPostExecute(result);
pDialog.dismiss();
}
}
}
Of course this code don't run and you need to fix the scopes. But what I am trying to suggest is that your loop should be in doInBackGround(...), you should only have 1 instance of AsyncTask at given time for this case, and call the onProgressUpdate().
Primary issue :
SetConstant.CONTENT_ID = contentId[i];
String URL = SetConstant.URL_DOWNLOAD_CONTENT+contentId[i];
Here, you are facing trouble. As #Sofi Software LLC's answer, you are using a global variable, whose value is being changed by the main thread, in another thread.
Secondary Issue :
If you want a progress bar to update, you have to update its value;
it doesn't update itself.
You do need to download the image in AsyncTask (Downloading from URL). Effectively to achieve your functionality, you need to do
Create AsyncTask to download your image (implement download in
doInBackground()), also have a boolean (say isImageDownloaded) to
track if the image is successfully downloaded in postExecute().
Don't forget to also show your progress bar before initiating the
download
Execute your AsyncTask to initiate download
Create extension of android.os.CountDownTimer to countdown a minimum
time
On the method onFinish() check the boolean that you track, if it is
false then you cancel the AsyncTask and throw the toast/dialog that
you intended
Running multipule instance of AsyncTask is not a good idea, so do one after another. You can execute your AsyncTask's on an Executor using executeOnExecutor().To make sure that the threads are running in a serial fashion please use: SERIAL_EXECUTOR.
Following resources may help you #
If you need to download an image, show progress bar and load in a imageview
https://github.com/koush/UrlImageViewHelper
http://developer.aiwgame.com/imageview-show-image-from-url-on-android-4-0.html
http://blog.blundell-apps.com/imageview-with-loading-spinner/
If you need to download multiple files (here, for images) using AsyncTask
Problem with downloading multiple files using AsyncTask
How to get back the task completion status in AsyncTask
Implement Progress Bar for File Download in Android
EDIT:
From http://developer.aiwgame.com/imageview-show-image-from-url-on-android-4-0.html
new DownloadImageTask((ImageView) findViewById(R.id.imageView1))
.execute("http://java.sogeti.nl/JavaBlog/wp-content/uploads/2009/04/android_icon_256.png"); }
public void onClick(View v) {
startActivity(new Intent(this, IndexActivity.class));
finish();
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
} }
From Image download in an Android ImageView and Progressbar implementation
// note that you could also use other timer related class in Android aside from this CountDownTimer, I prefer this class because I could do something on every interval basis
// tick every 10 secs (or what you think is necessary)
CountDownTimer timer = new CountDownTimer(30000, 10000) {
#Override
public void onFinish() {
// check the boolean, if it is false, throw toast/dialog
}
#Override
public void onTick(long millisUntilFinished) {
// you could alternatively update anything you want every tick of the interval that you specified
}
};
timer.start()
In the following line:
SetConstant.CONTENT_ID = contentId[i];
You're setting a global variable to a value, then you create a string url based on that same value and pass it to the AsyncTask. That executes, and then when it is done downloading, it create a file whose name is based on the global variable SetConstant.CONTENT_ID.
In other words, you are using a global variable, whose value is being changed by the main thread, in another thread. Don't do this, as you will get all kinds of weird problems due to the different threads updating at different times.. Pass in the value or the name of the output file to the AsyncTask. You can do that in a constructor for DownloadFile, and stash the value in a field.
If you want a progress bar to update, you have to update its value; it doesn't update itself. Call AsyncTask.publishProgress during the task (in doInBackground) and implement onProgressUpdate to update the progress dialog.
[EDIT: onProgressUpdate is indeed called in the UI thread.]
First create a separated class which allows you to reach to image address
like following:
public class ImageDownloader extends AsyncTask {
#Override
protected Bitmap doInBackground(String... urls) {
try {
URL url = new URL(urls[0]);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream inputStream = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(inputStream);
return myBitmap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Then get access to that class (through a method called by a button) by creating an object and execute the Bitmap task like following :
public class MainActivity extends Activity {
ImageView downloadedImg;
public void downloadImage(View view) {
ImageDownloader task = new ImageDownloader();
Bitmap myImage;
try {
myImage = task.execute("YOUR IMAGE ADDRESS ........").get();
downloadedImg.setImageBitmap(myImage);
} catch (Exception e) {
e.printStackTrace();
}
}
Do NOT forget to:
1 - define the imageView in onCreat method ==> downloadedImg = (ImageView) findViewById(R.id.imageView);
2 - to link the method you've created by a button in user interface ==> (public void downloadImage(View view){})
3 - ask for permission in manifest file
I made an app that downloads videos from our server.
The issue is:
When i cancel the downloading i call:
myAsyncTask.cancel(true)
I noticed, that myAsyncTask doesn't stops on calling cancel... my ProgressDialog still goes up and its like jumping from status to status showing me that each time I cancel and start again an AsyncTask by clicking the download button, a new AsyncTask starts...
Each time I click download.. then cancel, then again download a separate AsyncTask starts.
Why is myAsynTask.cancle(true) not cancelling my task ? I don't want it anymore on the background. I just want to completely shut it down if I click cancel.
How to do it ?
E D I T:
Thanks to gtumca-MAC, and the others who helped me did it by:
while (((count = input.read(data)) != -1) && (this.isCancelled()==false))
{
total += count;
publishProgress((int) (total * 100 / lenghtOfFile));
output.write(data, 0, count);
}
Thanks!!!
AsyncTask does not cancel process on
myAsynTask.cancel(true)
For that you have to stop it manually.
for example you are downloading video in doInBackground(..) in while/for loop.
protected Long doInBackground(URL... urls) {
for (int i = 0; i < count; i++) {
// you need to break your loop on particular condition here
if(isCancelled())
break;
}
return totalSize;
}
Declare in your class
DownloadFileAsync downloadFile = new DownloadFileAsync();
then On Create
DownloadFileAsync downloadFile = new DownloadFileAsync();
downloadFile.execute(url);
in Your Background ()
if (isCancelled())
break;
#Override
protected void onCancelled(){
}
and you can kill your AsyncTask by
downloadFile.cancel(true);
When you start a separate thread(AyncTask) it has to finish. You have to manually add a cancel statement to your code inside the AsyncTask.
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
Checkout more in the documentation: http://developer.android.com/reference/android/os/AsyncTask.html
I have been researching from the last 2 weeks and I don't get to know that how we kill the Async operation manually. Some developers use BREAK; while checking in for loop. But on my scenario I am not using the loop inside of background thread.
But I have got to know how it woks its a stupid logic but works perfectly fine.
downloadFile.cancel(true); //This code wont work in any case.
Instead of canceling and doing so much work on background thread turn off the wifi programmatically
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(false);
where do you want to kill the operation and turn on it where do you need that.
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(true);
What happens is your try block jumps in to the IOException killing the background tasks.
You better use vogella asyncTask library which have a lot of features like priority and canceling background task. And a great tutorial or using it is here
You can use this code. I am downloading a OTA file as follow:
static class FirmwareDownload extends AsyncTask<String, String, String> {
public String TAG = "Super LOG";
public String file;
int lenghtOfFile;
long total;
#Override
protected String doInBackground(String... f_url) {
try {
int count;
Utilies.getInternet();
URL url = new URL(f_url[0]);
URLConnection connection = url.openConnection();
connection.connect();
lenghtOfFile = connection.getContentLength();
mProgressBar.setMax(lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream(), 8192);
String fileName = f_url[0].substring(f_url[0].lastIndexOf("/"), f_url[0].length());
File root = Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + fileName);
Log.d(TAG, "trying to download in : " + dir);
dir.getAbsolutePath();
OutputStream output = new FileOutputStream(dir);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
if (isCancelled())
break;
total += count;
mProgressBar.setProgress(Integer.parseInt("" + total));
Log.d("Downloading " + fileName + " : ", " " + (int) ((total * 100) / lenghtOfFile));
mPercentage.post(new Runnable() {
#Override
public void run() {
mPercentage.setText(total / (1024 * 1024) + " Mb / " + lenghtOfFile / (1024 * 1024) + " Mb");
}
});
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
//new InstallHelper().commandLine("mkdir data/data/ota");
File fDest = new File("/data/data/ota/" + fileName);
copyFile(dir, fDest);
FirmwareInstaller fw = new FirmwareInstaller();
fw.updateFirmware();
} catch (Exception a) {
System.out.println("Error trying donwloading firmware " + a);
new InstallHelper().commandLine("rm -r data/data/ota");
dialog.dismiss();
}
return null;
}
}
So, If you want to cancel, just use this code:
fDownload.cancel(true);
I have used with success inside an activity with TextView onclick ...
//inside the doInBackground() ...
try {
while (true) {
System.out.println(new Date());
//should be 1 * 1000 for second
Thread.sleep(5 * 1000);
if (isCancelled()) {
return null;
}
}
} catch (InterruptedException e) {
}
and in my onCreate() ...
//set Activity
final SplashActivity sPlashScreen = this;
//init my Async Task
final RetrieveFeedTask syncDo = new RetrieveFeedTask();
syncDo.execute();
//init skip link
skip_text = (TextView) findViewById(R.id.skip_text);
skip_text.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//cancel Async
syncDo.cancel(true);
//goto/start another activity
Intent intent = new Intent();
intent.setClass(sPlashScreen, MainActivity.class);
startActivity(intent);
finish();
}
});
and my xml TextView element ...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/skip_text"
android:layout_marginTop="20dp"
android:text="SKIP"
android:textColor="#color/colorAccent"/>
I'm making an Android app where the user can download files from a FTP-server. For the ftp parts I am using apache.org.commons-net package.
When I have connected to server I get a list of the filenames, and then I want to download each file. I start the download routine which runs in a thread of it's own.
The problem I'm experiencing is, that if I have say 6 files on the server, and I run this code on my emulator, it will download the first two files, and then just freeze (with the progressbar hanging on 34 %). When I run it on my phone it will download three files and freeze.
If I debug my way through the code on the emulator it will download all six files just fine and not freeze.
Does anyone have any idea what might be the problem?
Thanks in advance,
LordJesus
This is my code (the client is already initialized):
private void downloadFiles2() {
dialog = new ProgressDialog(this);
dialog.setCancelable(true);
dialog.setMessage("Loading...");
// set the progress to be horizontal
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
// reset the bar to the default value of 0
dialog.setProgress(0);
dialog.setMax(DownloadCount);
// display the progressbar
dialog.show();
// create a thread for updating the progress bar
Thread background = new Thread (new Runnable() {
public void run() {
InputStream is = null;
try {
for (String filename : fileNames) {
is = client.retrieveFileStream(filename);
byte[] data = new byte[1024];
int x = 0;
x = is.read(data, 0, 1024);
boolean downloadIsNewer = true;
File fullPath = new File(path + "/" + filename);
Log.d("FTP", "Starting on " + filename);
if (fullPath.exists()) {
downloadIsNewer = checkIfNewer(data, fullPath);
}
if (downloadIsNewer) {
Log.d("FTP", "Need to download new file");
FileOutputStream fos = new FileOutputStream(fullPath);
fos.write(data,0,x);
while((x=is.read(data,0,1024))>=0){
fos.write(data,0,x);
}
fileText += filename + " - downloaded OK." + FileParser.newline;
is.close();
client.completePendingCommand();
fos.flush();
fos.close();
}
else {
Log.d("FTP", "No need to download");
is.close();
fileText += filename + " - own copy is newer." + FileParser.newline;
}
// active the update handler
progressHandler.sendMessage(progressHandler.obtainMessage());
}
client.logout();
client.disconnect();
}
catch (Exception e) {
// if something fails do something smart
}
}
});
// start the background thread
background.start();
}
Handler progressHandler = new Handler() {
public void handleMessage(Message msg) {
dialog.incrementProgressBy(1);
InfoTextView.setText(fileText);
if(dialog.getProgress()== dialog.getMax())
{
dialog.dismiss();
}
}
};
OK, found the problem:
When the boolean downloadIsNewer is false I do not call client.completePendingCommand(). When I add that before the line is.close() it works like a charm.