2

i have method like this :

public void extractFiles() {

    AsyncTask<Void, Void, Boolean> extractionTask = new AsyncTask<Void, Void, Boolean>() {

        @Override
        protected void onPreExecute() {
        progressDialog = new ProgressDialog(Activity.this);
        progressDialog.setCancelable(false);
        progressDialog.setMessage("Extracting Files Please wait...");
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.setProgress(0);
        progressDialog.show();
        super.onPreExecute();
        }

        @Override
        protected Boolean doInBackground(Void... params) {
        // TODO Auto-generated method stub
        String xapkFilePath = XAPKFilePath(Activity.this);
        String exportDirectory = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/"
            + Activity.this.getPackageName() + "/files/";
        File exportDirectoryFilepath = new File(exportDirectory);
        exportDirectoryFilepath.mkdirs();
        ZipHelper zhelper = new ZipHelper();


        System.out.println("In background called");
        zhelper.unzip(xapkFilePath, exportDirectoryFilepath);

        return true;
        }

        @Override
        protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
            System.out.println("progress dialog dismissed");
        }
        if (result) {
            //start intent.
        }
        }

    };
    extractionTask.execute();
    }

public class ZipHelper {

    boolean zipError = false;

    public boolean isZipError() {
    return zipError;
    }

    public void setZipError(boolean zipError) {
    this.zipError = zipError;
    }

    public void unzip(String archive, File outputDir) {
    try {
        Log.d("control", "ZipHelper.unzip() - File: " + archive);
        ZipFile zipfile = new ZipFile(archive);
        for (Enumeration e = zipfile.entries(); e.hasMoreElements();) {
        ZipEntry entry = (ZipEntry) e.nextElement();

        System.out.println("OUTPUT DIR 1*" + outputDir);
        System.out.println("ENTRY IS " + entry);

        unzipEntry(zipfile, entry, outputDir);

        }
    } catch (Exception e) {
        Log.d("control", "ZipHelper.unzip() - Error extracting file " + archive + ": " + e);
        setZipError(true);
    }
    }

    private void unzipEntry(ZipFile zipfile, ZipEntry entry, File outputDir) throws IOException {
    if (entry.isDirectory()) {
        createDirectory(new File(outputDir, entry.getName()));
        return;
    }

    File outputFile = new File(outputDir, entry.getName());
    if (!outputFile.getParentFile().exists()) {
        createDirectory(outputFile.getParentFile());
        System.out.println("OUTPUT FILE IS " + outputFile.getParentFile());
    }

    Log.d("control", "ZipHelper.unzipEntry() - Extracting: " + entry);
    BufferedInputStream inputStream = new BufferedInputStream(zipfile.getInputStream(entry));
    BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
    try {
        IOUtils.copy(inputStream, outputStream);
    } catch (Exception e) {
        Log.d("control", "ZipHelper.unzipEntry() - Error: " + e);
        setZipError(true);
    } finally {
        outputStream.close();
        inputStream.close();
    }
    }

    private void createDirectory(File dir) {
    Log.d("control", "ZipHelper.createDir() - Creating directory: " + dir.getName());
    if (!dir.exists()) {
        if (!dir.mkdirs()) {
        throw new RuntimeException("Can't create directory " + dir);
        }
    } else {
        Log.d("control", "ZipHelper.createDir() - Exists directory: " + dir.getName());
    }
    }

}

Here i call the method like this extractFiles() but what is happening is even before the doInBackground is completed that is extracting the files for which i am showing a spinner , the onPostExecute is called and moves to next screen.

What is wrong here?

Goofy
  • 6,040
  • 17
  • 87
  • 154

3 Answers3

1
public void extractFiles() {
     new TheTask().execute(params);
}
class TheTask extends AsyncTask<Void,Void,Void>
{ 
     .......
}

You should call super first in

  @Override
    protected void onPreExecute() 
      super.onPreExecute();
   }

Asynctask must be loaded on UI Thread. Asynctask onPreExecute() is inovked on the ui thread when asynctask is loaded. After which doInBAckground() is runs in the background thread. The result of doInBackground() is a parameter to onPostExecute().

When an asynchronous task is executed, the task goes through 4 steps:

  1. onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.

  2. doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.

  3. onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.

  4. onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.

http://developer.android.com/reference/android/os/AsyncTask.html

Raghunandan
  • 131,557
  • 25
  • 223
  • 252
  • thanks but where am i going wrong here ? can you please tell me – Goofy Apr 18 '13 at 05:27
  • see the above you need to call super first in onPreExecute(). also call asynctask like above inside the extractFiles() – Raghunandan Apr 18 '13 at 05:28
  • nope i din't see you had called execute() on your asynctask. You can do as before. Its not wrong .It would be easier to have a track if you load asynctask in extractFiles() – Raghunandan Apr 18 '13 at 05:40
  • ok please wait here i have made changes as you told and checking with that – Goofy Apr 18 '13 at 05:42
1

check your condition in doinbackground completely perform your operation or not if perform then return true,

zhelper.unzip(xapkFilePath, exportDirectoryFilepath);
MR. Kumar
  • 659
  • 8
  • 25
  • i mean to say that doinbackground returns true regular so postexecute is calling, instead of that return true when your extract operation completes. – MR. Kumar Apr 18 '13 at 06:16
  • yes i got your point but i am not getting how to do that? can you please help me? – Goofy Apr 18 '13 at 06:18
  • you can check return value from zhelper.unzip(xapkFilePath, exportDirectoryFilepath); and check its return value. And also check your zhelper.unzip(xapkFilePath, exportDirectoryFilepath); method is not resulting exception. – MR. Kumar Apr 18 '13 at 06:24
  • No buddy not yet zhelper.unzip(xapkFilePath, exportDirectoryFilepath); returns void – Goofy Apr 18 '13 at 06:42
  • this is my point i am trying to extract 300 files so i need to indicate the user that its extracting so i am using async task – Goofy Apr 18 '13 at 06:43
  • change the method make it return type and check its exception too. – MR. Kumar Apr 18 '13 at 06:44
  • then why you not using counter to check how many file has extract if its 300 hundred then return true from doin background. – MR. Kumar Apr 18 '13 at 06:51
  • ok but it varies from app to app, so thats difficult to get the count of how many files? – Goofy Apr 18 '13 at 07:01
  • yeah off course it will varies you can keep total file count in global variable using some method to count no. of file and use that global variable to check condition in doinbackground. – MR. Kumar Apr 18 '13 at 07:05
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28412/discussion-between-goofy-and-gunjan-verma) – Goofy Apr 18 '13 at 07:05
0

I solved a very similar problem by declaring both doInBackground and onPostExecute synchronized.
(...)
protected synchronized Boolean doInBackground(Void... params)
{...}
protected synchronized void onPostExecute(Boolean result) {...}
(...)
In my case, doInBackground() was entering first (as it should) but somehow onPostExecute() was called before doInBackground() "technically" completed (I couldnt figure out why - maybe my unzip library objects had its own threads and did not block the doInBackground() method). Synchronizing the methods solved the problem (not without performance consequences, of course)