I have created a code to download multiple files showing a progressbar progress. This works perfectly, but now I want to deploy it to an external project (library itself) and I have problems.
My intention is to call "download" and when the download completes or returns 0 or 1. But being asynchronous the method returns the value before finishing., I tried to control it without success with "CountdownLatch" ...
Any idea?
The following code works, the problem is that the method "download" returns the value without waiting for it to finish the rest of code.
Main.java
if(MyLib.download(Main.this, url, nameFiles, "internal", "folderExtra") == 1){
System.out.println("SUCCESS DOWNLOAD!");
}else{
System.out.println("error download");
}
MyLib.java
/** DOWNLOADER WITH PROCESSDIALOG **/
ProgressDialog pDialog;
Context context;
String urlName;
String[] filesToDownload;
int downloadOK = -1;
int currentFile = -1;
int totalFiles = 0;
String typeStorage = "internal";
String folder = "";
CountDownLatch controlLatch;
public int download(Context ctx, String urlName, String[] filesToDownload, String typeStorage, String extraFolder ){
System.out.println("estoy en download");
this.context = ctx;
this.urlName = urlName;
this.filesToDownload = filesToDownload;
this.totalFiles = filesToDownload.length;
this.typeStorage = typeStorage;
/** Almacenamiento de la descarga - Interno o externo **/
if (typeStorage.equalsIgnoreCase("internal")) {
System.out.println("internal");
this.folder = context.getFilesDir().toString() + "/";
} else if (typeStorage.equalsIgnoreCase("external")) {
System.out.println("external");
}
/** COMPLETEMENTO DIRECTORIO/S OPCIONAL **/
if (extraFolder != null && extraFolder != "") {
folder += extraFolder;
}
System.out.println("FOLDER: " + folder);
File directoryFile = new File(folder);
if (!directoryFile.isDirectory()) {
if (!directoryFile.mkdir()) {
Toast.makeText(context, "No se puede crear el directorio o no existe", Toast.LENGTH_LONG).show();
}
}
pDialog = new ProgressDialog(context);
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.setMax(100);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setTitle("Descargando recursos...");
// controlLatch = new CountDownLatch(1);
startDownload();
/*
try {
System.out.println("STOP");
controlLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
return downloadOK;
}
private void startDownload() {
currentFile++;
System.out.println("startDownload!");
if (currentFile < totalFiles) {
pDialog.setMessage("Descargando " + (currentFile + 1) + " de " + totalFiles + "\n\n(..." + filesToDownload[currentFile] + ")");
System.out.println("startDownload currentFile +[" + currentFile + "] totalFiles [" + totalFiles + "]");
System.out.println("file: " + filesToDownload[currentFile].toString());
new DownloaderFile().execute(filesToDownload[currentFile]);
}
}
private class DownloaderFile extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
try {
File checkFile = new File(folder + params[0]);
if(!checkFile.exists()){
URL urlFinal = new URL(urlName+params[0]);
URLConnection connection = urlFinal.openConnection();
connection.connect();
int fileLength = connection.getContentLength();
InputStream input = new BufferedInputStream(urlFinal.openStream());
OutputStream output = new FileOutputStream(folder + params[0]);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} else {
System.out.println("The file " + filesToDownload[currentFile] + " is downloaded" );
}
} catch (Exception e) {
e.printStackTrace();
return "error";
}
return "ok";
}
#Override
protected void onPreExecute() {
super.onPreExecute();
System.out.println("-1");
File checkFile = new File(folder + filesToDownload[currentFile]);
if(!checkFile.exists()){
System.out.println("pDialogShow");
pDialog.show();
}
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
pDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String res) {
System.out.println("10");
if (currentFile == (totalFiles - 1)) {
System.out.println("FINISH!!!!!!!!!!!!!!");
currentFile = 0;
pDialog.dismiss();
downloadOK = 1;
//controlLatch.countDown();
} else {
if (res.equals("ok")) {
startDownload();
} else {
System.out.println("error download");
downloadOK = 0;
}
}
}
}
It sounds like you want callback.
Your DownloaderFile class can take a listener interface which is implemented by whatever contains the DownloaderFile object. Call that listener inside onPostExecute().
It might look like this:
public class MyActivity extends Activity implements OnDownloadCompleteListener {
private void startDownload() {
//inside whatever method
Downloader downloader = new Downloader(this); //'this' implements OnDownloadCompleteListener
downloader.go();
}
#Override
public void onDownloadFinished(boolean success) {
//implementation
}
}
Inside Downloader:
//...
#Override
protected void onPostExecute(String res) {
onDownloadCompleteListener.onDownloadComplete(true);
}
The OnDownloadCompleteListener interface:
public interface OnDownloadCompleteListener {
public void onDownloadComplete(boolean success);
}
Related
I have an application which has a button to start downloading a file and it works completely with no problem.
Now I want to do something more. If the download did not get complete (not overed or finished) or it canceled by user or other things (like losing internet connection), then again user click on the starting download button, the download should start from the continuation of the file but sadly it removes the file and start from the beginning of downloading the file.
What should I do to continue it and not starting again from the beginning?
public class Main extends AppCompatActivity {
private ProgressDialog pddDialog;
public static final int progress_bar_type = 0;
private Button startinstall;
private DownloadTask downloadTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layoutmain);
final ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo ni = cm.getActiveNetworkInfo();
Button bdd = (Button) findViewById(R.id.downdata);
bdd.setTypeface(tf);
bdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.startAnimation(anim);
File filedata = new File(Environment.getExternalStorageDirectory() + "/areasoft/dpei.cso");
if (filedata.exists()) {
Toast.makeText(Main.this, "you have downloaded the file completly.", Toast.LENGTH_SHORT).show();
}else {
if (ni == null) {
Toast.makeText(Main.this, " you are not connecting to the internet.", Toast.LENGTH_SHORT).show();
} else {
downloadTask = new DownloadTask(Main.this);
downloadTask.execute("download link");
}
}
}
});
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type:
pddDialog = new ProgressDialog(this);
pddDialog.setMessage("downloading fileā¦");
pddDialog.setIndeterminate(false);
pddDialog.setMax(100);
pddDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pddDialog.setCancelable(true);
pddDialog.setButton("cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
pddDialog.dismiss();
downloadTask.cancel(true);
}
});
pddDialog.show();
return pddDialog;
default:
return null;
}
}
class DownloadTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(progress_bar_type);
}
private Context context;
private PowerManager.WakeLock mWakeLock;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// HTTP 200 OK
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
int fileLength = connection.getContentLength();
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/areasoft/dpei.cso");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
if (isCancelled()) {
input.close();
return null;
}
total += count;
if (fileLength > 0)
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();
}
return null;
}
protected void onProgressUpdate(String... progress) {
pddDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String file_url) {
dismissDialog(progress_bar_type);
}
}
}
When i use asynctask method, activity indicator does not work. AsyncTask method is used to download the image from URL and put on phone memory. Below is my code
btnSubmit.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AsyncCallWS aws = new AsyncCallWS();
try {
retData = aws.execute().get();
Log.d(TAG, "STATUS is " + retData);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Close the window and go back to login page
Intent intent = new Intent(launchar.this, arcamera.class);
intent.putExtra("url", url_);
intent.putExtra(Strings.USERNAME, mUsername);
intent.putExtra(Strings.PASSWORD, mPassword);
intent.putExtra(Strings.COMP_ID, mCompId);
startActivity(intent);
}
});
My Async Method is below :
private class AsyncCallWS extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// Call the service
HttpConnectionHelper helper = new HttpConnectionHelper(
Constants.SERVICE_GETAR_URL);
final String REQUEST_DATA = String.format(
"<ReqData xmlns=\"http://www.ceolution.com/phone\"> "
+ "<key>%s|%s|%s</key>" + "</ReqData>", mUsername,
mPassword, mCompId);
try {
helper.setRequestMethod(HttpPost.METHOD_NAME);
helper.setPostData(REQUEST_DATA);
helper.setHeader("Content-Type", "application/xml");
int code = helper.getResponseCode();
if (Constants.LOG_ENABLED) {
Log.i(TAG, "Response code = " + code);
}
if (code == HttpURLConnection.HTTP_OK) {
String data = helper.getResponseData();
if (Constants.LOG_ENABLED) {
Log.v(TAG, "Response Data - " + data);
}
ARParser par = new ARParser();
String data_ = par.ParseAR(data);
Log.i(TAG, "RETURN DATA IS " + data_);
// Get Object
BufferedReader br = new BufferedReader(new StringReader(
data_));
InputSource is = new InputSource(br);
// Create XML Parser
ARXMLFormatter parser = new ARXMLFormatter();
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser sp = factory.newSAXParser();
XMLReader reader = sp.getXMLReader();
reader.setContentHandler(parser);
reader.parse(is);
myData = parser.itemList;
if (myData != null) {
String OutputData = "";
Location itemLocation = null;
for (Item item : myData) {
if (item != null) {
itemLocation = new Location("");
itemLocation.setLatitude(Double
.parseDouble(item.getLat()));
itemLocation.setLongitude(Double
.parseDouble(item.getLg()));
if (location != null) {
float distanceInMeters = itemLocation
.distanceTo(location);
Log.d(TAG, "distanceInMeters is "
+ distanceInMeters);
if (distanceInMeters <= Double
.parseDouble(item.getR())) {
// Must have to clean the directory
// before
// writing data
File savefilepath1 = new File(
COURSE_ZIP_FILE_PATH);
cleanDirectory(savefilepath1);
Image realData = null;
String imageName = "";
for (int k = 0; k < 8; k++) {
realData = null;
imageName = "";
switch (k) {
case 0: {
realData = item.getN();
imageName = "n.png";
break;
}
case 1: {
realData = item.getE();
imageName = "e.png";
break;
}
case 2: {
realData = item.getS();
imageName = "s.png";
break;
}
case 3: {
realData = item.getW();
imageName = "w.png";
break;
}
case 4: {
realData = item.getNe();
imageName = "ne.png";
break;
}
case 5: {
realData = item.getNw();
imageName = "nw.png";
break;
}
case 6: {
realData = item.getSe();
imageName = "se.png";
break;
}
case 7: {
realData = item.getSw();
imageName = "sw.png";
break;
}
}
url_[k] = realData.getL();
boolean status = false;
if (realData.getU() != ""
&& realData.getU() != null)
status = DownloadFile(
realData.getU()
.replace(
"http",
"https"),
imageName);
Log.d(TAG, "Download status is "
+ status);
}
Log.d(TAG,
"This is the item to processed");
return "SUCCESS";
}
OutputData = OutputData + item.toString();
} else
return "GPSISSUE";
} else
Log.e("Items", "No details");
}
Log.d(TAG, "OutputData data is " + OutputData);
}
return "NODATA";
}
} catch (Exception ex) {
ex.printStackTrace();
return "ERROR";
}
return "NODATA";
}
The XML file is below
<FrameLayout
android:id="#+id/laucnh_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<ImageView
android:id="#+id/btnSubmit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="#drawable/launch"
android:onClick="#string/onClick"
android:scaleType="center" />
</FrameLayout>
Even i tried to put the activity indicator in onPreExecute() and onPostExecute() also does not work.
I am not sure what may be reason .
Please help.
You will have to publish updates from your asyncTask to the UI. Here is an example of it. So in the onProgressUpdate Function you can update the UI. I hope this helps.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
I have 2 projects: App Project and own library.
My project have this code:
main.java (MyProject)
...
// call method Lib.download()
String nameFiles[] = {"do.mp3","re.mp3","mi.mp3","billiejean.mp3"};
String url = "http://myweb.net/getfiles/";
if( Lib.download(Main.this, url, nameFiles, "internal", "folderExtra" ) == 1){
System.out.println("finish");
} else {
System.out.println("error download");
}
The problem is that Lib.download return the default value without waiting for it to finish the rest of code.
I'm trying controller this with Semaphore / CountDownLatch / whiles but it doesn't work and also i'm trying implement a callback but without success because classes for "download" must be out of my project. Any help?
The downloads are done correctly but the download method returns the value before completing the downloads ...
My intention is to call a method "download" from any activity, this launch the dialog process and the rest of my activity code does not run until this method "download" returns a value.
Lib.java (MyLib)
/** DOWNLOADER WITH PROCESSDIALOG **/
ProgressDialog pDialog;
Context context;
String urlName;
String[] filesToDownload;
int downloadOK = -1;
int currentFile = -1;
int totalFiles = 0;
String typeStorage = "internal";
String folder = "";
CountDownLatch controlLatch;
public int download(Context ctx, String urlName, String[] filesToDownload, String typeStorage, String extraFolder ){
this.context = ctx;
this.urlName = urlName;
this.filesToDownload = filesToDownload;
this.totalFiles = filesToDownload.length;
this.typeStorage = typeStorage;
/** Almacenamiento de la descarga - Interno o externo **/
if (typeStorage.equalsIgnoreCase("internal")) {
System.out.println("internal");
this.folder = context.getFilesDir().toString() + "/";
} else if (typeStorage.equalsIgnoreCase("external")) {
}
/** EXTRA OPTIONALL **/
if (extraFolder != null && extraFolder != "") {
folder += extraFolder;
}
File directoryFile = new File(folder);
if (!directoryFile.isDirectory()) {
if (!directoryFile.mkdir()) {
Toast.makeText(context, "problems create directory", Toast.LENGTH_LONG).show();
}
}
pDialog = new ProgressDialog(context);
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.setMax(100);
pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pDialog.setTitle("Descargando recursos...");
// controlLatch = new CountDownLatch(1);
startDownload();
/*
try {
System.out.println("STOP");
controlLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
return downloadOK;
}
private void startDownload() {
currentFile++;
System.out.println("startDownload!");
if (currentFile < totalFiles) {
pDialog.setMessage("Descargando " + (currentFile + 1) + " de " + totalFiles + "\n\n(..." + filesToDownload[currentFile] + ")");
System.out.println("startDownload currentFile +[" + currentFile + "] totalFiles [" + totalFiles + "]");
System.out.println("file: " + filesToDownload[currentFile].toString());
new DownloaderFile().execute(filesToDownload[currentFile]);
}
}
private class DownloaderFile extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
try {
File checkFile = new File(folder + params[0]);
if(!checkFile.exists()){
URL urlFinal = new URL(urlName+params[0]);
URLConnection connection = urlFinal.openConnection();
connection.connect();
int fileLength = connection.getContentLength();
InputStream input = new BufferedInputStream(urlFinal.openStream());
OutputStream output = new FileOutputStream(folder + params[0]);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} else {
System.out.println("The file " + filesToDownload[currentFile] + " is downloaded" );
}
} catch (Exception e) {
e.printStackTrace();
return "error";
}
return "ok";
}
#Override
protected void onPreExecute() {
super.onPreExecute();
System.out.println("-1");
File checkFile = new File(folder + filesToDownload[currentFile]);
if(!checkFile.exists()){
System.out.println("pDialogShow");
pDialog.show();
}
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
pDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String res) {
System.out.println("10");
if (currentFile == (totalFiles - 1)) {
System.out.println("FINISH!!!!!!!!!!!!!!");
currentFile = 0;
pDialog.dismiss();
downloadOK = 1;
//controlLatch.countDown();
} else {
if (res.equals("ok")) {
startDownload();
} else {
System.out.println("error download");
downloadOK = 0;
}
}
}
}
AsyncTasks would run at separate thread once your .execute() is called. Your calling line startDownload() will never wait for AsyncTask to return any value, what you can do is:
Implement some callback interface on your main activity, so that your onPostExecute method would be able to notify your main activity once the operation is finished.
As you're the one developing this library, consider moving the AsyncTask to your main activity, and leave very plain download functions (what in your doInBackground method) in the library.
Use LocalBroadcastManager to send a broadcast from your library, listen and react to it on your main.java
I am going to implement the FTP download function. It works but when it comes to reporting the progress, I have only found that only the message changes but not the numbers and the bar changing
I have screen captured as below
The below is my code:
public void buttonExit(View v) {
System.exit(1);
}
public void doClick(View v){
//ftp
filename = null;
filename = "giant.mp4";
pd = new ProgressDialog(this);
pd.setTitle("EOrder");
pd.setMessage("Downloading file. Please wait...");
pd.setIndeterminate(true);
pd.setMax(100);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setProgress(0);
pd.setCancelable(false);
pd.show();
ad = new AlertDialog.Builder(this);
ad.setTitle("EOrder");
ad.setMessage("Download Finish");
ad.setNeutralButton("OK", null);
new FTPDownload().execute(filename);
}
class FTPDownload extends AsyncTask<String , String , Void>{
boolean running = true;
Date today = Calendar.getInstance().getTime();
Format formatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
String reportDate = formatter.format(today);
String fileAndroid = reportDate + "_" + filename;
#Override
protected Void doInBackground(String... params) {
// TODO Auto-generated method stub
Log.d("******", "Background thread starting......");
FTPClient client = new FTPClient();
try {
Log.d("tag" , "arrived");
client.connect("newaswrissssing.win5.siteonlinetest.com");
boolean successLogin = client.login("newaswrissssing", "newaswrissssing2014cap!");
if(successLogin){
client.changeWorkingDirectory("dummy");
Log.d("tag" , "success");
long fileSize = getFileSize(client , params[0]);
client.setFileType(FTP.BINARY_FILE_TYPE);
client.enterLocalPassiveMode();
File instanceRecordDirectory = new File(Environment.getExternalStorageDirectory() + File.separator + "TVB_Movie");
if(!instanceRecordDirectory.exists()){
instanceRecordDirectory.mkdirs();
}
File instanceRecord = new File(instanceRecordDirectory.getAbsolutePath() + File.separator + fileAndroid);
if(!instanceRecord.exists()){
instanceRecord.createNewFile();
}
BufferedOutputStream desFileStream = new BufferedOutputStream(new FileOutputStream(instanceRecord.getAbsolutePath()),8*1024);
InputStream in = client.retrieveFileStream(params[0]);
Log.d("as" , String.valueOf(in));
byte[] buffer = new byte[1024];
int len1 = 0;
long total = 0;
while ((len1 = in.read(buffer)) > 0) {
total += len1; //total = total + len1
Log.d("aDDs" , String.valueOf(in));
publishProgress("" + (int)((total*100)/fileSize));
desFileStream.write(buffer, 0, len1);
}
desFileStream.flush();
desFileStream.close();
client.completePendingCommand();
in.close();
}else{
Log.d("tag" , "sosad");
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
client.logout();
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
protected void onProgressUpdate(String... progress) {
super.onProgressUpdate(progress);
Log.d("progress","values: "+progress[0]);
pd.incrementProgressBy(Integer.parseInt(progress[0]));
pd.setMessage("Downloading file... Progress at " + progress[0] + "%");
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
pd.dismiss();
ad.show();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
Would you please tell me what other steps to do besides using pd.incrementProgressBy(Integer.parseInt(progress[0])); or setProgress?
your ProgressDialog should not be intederminate. You should call setIndeterminate with false instead of true
pd.setIndeterminate(false);
and you should use setProgress instead of incrementProgressBy
When I try this code, it starts download but then stuck with alert "force close"
what should I do? Use some kind of background thread?
try {
long startTime = System.currentTimeMillis();
URL u = new URL("http://file.podfm.ru/3/33/332/3322/mp3/24785.mp3");
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
FileOutputStream f = new FileOutputStream(new File("/sdcard/","logo.mp3"));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) != -1 ) {
f.write(buffer,0, len1);
}
f.close();
Log.d("ImageManager", "download ready in" +
((System.currentTimeMillis() - startTime) / 1000) + " sec");
}
catch (IOException e)
{
Log.d("ImageManager", "Error" +
((System.currentTimeMillis()) / 1000) + e + " sec");
}
I was dealing with similar problem last week and ended up using AsyncTask with progress bar displayed since it could take some time for the file to be downloaded. One way of doing it is to have below class nested in your Activity and just call it where you need to simply like this:
new DownloadManager().execute("here be URL", "here be filename");
Or if the class is not located within an activity and calling from an activity..
new DownloadManager(this).execute("URL", "filename");
This passes the activity so we have access to method getSystemService();
Here is the actual code doing all the dirty work. You will probably have to modify it for your needs.
private class DownloadManager extends AsyncTask<String, Integer, Drawable>
{
private Drawable d;
private HttpURLConnection conn;
private InputStream stream; //to read
private ByteArrayOutputStream out; //to write
private Context mCtx;
private double fileSize;
private double downloaded; // number of bytes downloaded
private int status = DOWNLOADING; //status of current process
private ProgressDialog progressDialog;
private static final int MAX_BUFFER_SIZE = 1024; //1kb
private static final int DOWNLOADING = 0;
private static final int COMPLETE = 1;
public DownloadManager(Context ctx)
{
d = null;
conn = null;
fileSize = 0;
downloaded = 0;
status = DOWNLOADING;
mCtx = ctx;
}
public boolean isOnline()
{
try
{
ConnectivityManager cm = (ConnectivityManager)mCtx.getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo().isConnectedOrConnecting();
}
catch (Exception e)
{
return false;
}
}
#Override
protected Drawable doInBackground(String... url)
{
try
{
String filename = url[1];
if (isOnline())
{
conn = (HttpURLConnection) new URL(url[0]).openConnection();
fileSize = conn.getContentLength();
out = new ByteArrayOutputStream((int)fileSize);
conn.connect();
stream = conn.getInputStream();
// loop with step
while (status == DOWNLOADING)
{
byte buffer[];
if (fileSize - downloaded > MAX_BUFFER_SIZE)
{
buffer = new byte[MAX_BUFFER_SIZE];
}
else
{
buffer = new byte[(int) (fileSize - downloaded)];
}
int read = stream.read(buffer);
if (read == -1)
{
publishProgress(100);
break;
}
// writing to buffer
out.write(buffer, 0, read);
downloaded += read;
// update progress bar
publishProgress((int) ((downloaded / fileSize) * 100));
} // end of while
if (status == DOWNLOADING)
{
status = COMPLETE;
}
try
{
FileOutputStream fos = new FileOutputStream(filename);
fos.write(out.toByteArray());
fos.close();
}
catch ( IOException e )
{
e.printStackTrace();
return null;
}
d = Drawable.createFromStream((InputStream) new ByteArrayInputStream(out.toByteArray()), "filename");
return d;
} // end of if isOnline
else
{
return null;
}
}
catch (Exception e)
{
e.printStackTrace();
return null;
}// end of catch
} // end of class DownloadManager()
#Override
protected void onProgressUpdate(Integer... changed)
{
progressDialog.setProgress(changed[0]);
}
#Override
protected void onPreExecute()
{
progressDialog = new ProgressDialog(/*ShowContent.this*/); // your activity
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Downloading ...");
progressDialog.setCancelable(false);
progressDialog.show();
}
#Override
protected void onPostExecute(Drawable result)
{
progressDialog.dismiss();
// do something
}
}
You should try using an AsyncTask. You are getting the force quit dialog because you are trying to do too much work on the UI thread and Android judges that your application has become unresponsive.
The answers to this question have some good links.
Something like the following would be a good start:
private class DownloadLargeFileTask extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog;
public DownloadLargeFileTask(ProgressDialog dialog) {
this.dialog = dialog;
}
protected void onPreExecute() {
dialog.show();
}
protected void doInBackground(Void... unused) {
downloadLargeFile();
}
protected void onPostExecute(Void unused) {
dialog.dismiss();
}
}
and then execute the task with:
ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("Loading. Please Wait...");
new DownloadLargeFileTask(dialog).execute();