Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Download code in android downloads incomplete files

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.

like image 698
Nirab Pudasaini Avatar asked Nov 20 '25 14:11

Nirab Pudasaini


1 Answers

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");
like image 185
Niraj Adhikari Avatar answered Nov 22 '25 04:11

Niraj Adhikari



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!