0

I'm still trying to make my first App. So, it grows... and i try divide it to few Packeges. My first Pack works with Files, it will contains classes which can: download files, read data from files and et.c.

So i try to move out of my main activity first class, but have problem with ProgressDialog it does not work. So i have few qwestions:

1) What is the best way to sent % of downloading to activity of My App? 2) What will happens, if user changes current Activity during download progress?

package com.domen.myapplication.Files;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.PowerManager;
import android.widget.Toast;


import com.domen.myapplication.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by DL  on 01.08.2016.
 */
public class DownloadTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;
    public int progress=0;
    public int progressShow=0;
    public ProgressDialog mProgressDialog;




    public DownloadTask(Context context) {
        this.context = context;

        mProgressDialog = new ProgressDialog(this.context);
        mProgressDialog.setMessage(this.context.getResources().getString(R.string.loading_empty));
        mProgressDialog.setIndeterminate(true);
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mProgressDialog.setCancelable(true);


    }

    @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();

            // 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();
            }

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            //output = new FileOutputStream("/sdcard/file_name.extension");


            File cacheFile = new File(this.context.getCacheDir(), "FIRMWARE");

            output = new FileOutputStream(cacheFile);

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    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();
        }
        return null;
    }


    //метод выше (doInBackground) запускается отдельным поток все сотальное ниже в главном потоке
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // 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);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                getClass().getName());
        mWakeLock.acquire();
        progressShow=1;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(progress[0]);
        this.progress=progress[0];
    }

    @Override
    protected void onPostExecute(String result) {
        mWakeLock.release();
        progressShow=1;
        mProgressDialog.dismiss();
        if (result != null)
            Toast.makeText(context, "Download error: " + result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(context, "File downloaded", Toast.LENGTH_SHORT).show();
    }


}
Dmitry Lyalin
  • 341
  • 6
  • 15

1 Answers1

1

If you want to download the file only in the activity, Make AsyncTask as a inner class in the activity and use it.

But if you want to download file irrespective of Activity, Create a service and implement the download logic in the service and show a file download progress notification from service and update it with download percentage, Just like Play Store app download progress.

Your second question What will happens, if user changes current Activity during download progress?

Yes, Async Task will be running even after the activity is destroyed, until it finishes its job. check this link for more info https://stackoverflow.com/a/13147992/1066839

Community
  • 1
  • 1
John
  • 8,846
  • 8
  • 50
  • 85
  • Oh, This is great help! Thanks! I have already one service in my App. So if user change current activity, service will work? And i need to reBind it from new activity? In my App i have only one activity and I with help of ViewFlipper change screens (but i think this is bad idea, or not?) – Dmitry Lyalin Aug 01 '16 at 09:52
  • If you have service already. create a thread inside a service and start service and download the file and show notification of the file progress. – John Aug 01 '16 at 09:54
  • My service is managing Bluetooth connection. And i think i need to have one more service... is it currect? – Dmitry Lyalin Aug 01 '16 at 10:00
  • Yes. Its better to separate the features. so that it can handled easily – John Aug 01 '16 at 10:03
  • Downloaded file will be transfered via bluetooth. And in App activity user must have list of thise files... and user must have ability to sellect which file will be sent by bluetooth Service. – Dmitry Lyalin Aug 01 '16 at 10:04
  • You can download the files in the service and You can store the downloaded files in a folder in sdcard. And later read it and list it in the activity. – John Aug 01 '16 at 11:46
  • Yes i understand, thank you. I just trying to make some progress bar in my App activity which will show download progress from my service. I know only one way - broadcastreceiver. Is there another way to sent data from service to App? – Dmitry Lyalin Aug 04 '16 at 12:22
  • Usual way is to use broadcast receivers. Thats is recommended. But there are some event bus libraries which can accomplish this. Check Square's Otto Event Bus http://square.github.io/otto/ – John Aug 04 '16 at 12:34