1

I'm trying to extract RAR files with junRAR. But as I read from this question: OutOfMemoryError when I decompress RAR file on Android, junRAR is not optimized yet for Android. So, what I want to do is to check if the extraction is successful or not, then give an error message if it fails.(because my app crashes if it the extraction is not successful). Can somebody tell me how can I do that checking? My thread is being done here:

public class MyTask extends AsyncTask<Void, Void, Void> {

  private ProgressDialog progress;
  public MyTask(ProgressDialog progress) {
      this.progress = progress;   
  }

  public void onPreExecute() {
    progress.show();
  }    
@Override
protected Void doInBackground(Void... params) {
    if(taskType==1){
         extractArchive(rarFile, destinationFolder);            
    }
return null;
}

public void onPostExecute(Void unused) {
    progress.dismiss();
    if(taskType==1){
        refreshFileList();
        Toast.makeText(MainActivity.this, "Extracted to " + targetPath, Toast.LENGTH_LONG).show();
    }
} 

Here's my Logcat error:


03-02 16:59:40.777: E/AndroidRuntime(28573): FATAL EXCEPTION: AsyncTask #1
03-02 16:59:40.777: E/AndroidRuntime(28573): java.lang.RuntimeException: An error occured while executing doInBackground()
03-02 16:59:40.777: E/AndroidRuntime(28573):    at android.os.AsyncTask$3.done(AsyncTask.java:278)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.lang.Thread.run(Thread.java:856)
03-02 16:59:40.777: E/AndroidRuntime(28573): Caused by: java.lang.OutOfMemoryError
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.github.junrar.unpack.ppm.SubAllocator.startSubAllocator(SubAllocator.java:146)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.github.junrar.unpack.ppm.ModelPPM.decodeInit(ModelPPM.java:216)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.github.junrar.unpack.Unpack.readTables(Unpack.java:656)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.github.junrar.unpack.Unpack.unpack29(Unpack.java:165)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.github.junrar.unpack.Unpack.doUnpack(Unpack.java:120)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.github.junrar.Archive.doExtractFile(Archive.java:501)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.github.junrar.Archive.extractFile(Archive.java:443)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.jearom.thesisfmanager.MainActivity.extractArchive(MainActivity.java:2270)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.jearom.thesisfmanager.MainActivity$MyTask.doInBackground(MainActivity.java:1962)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at com.jearom.thesisfmanager.MainActivity$MyTask.doInBackground(MainActivity.java:1)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at android.os.AsyncTask$2.call(AsyncTask.java:264)
03-02 16:59:40.777: E/AndroidRuntime(28573):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
03-02 16:59:40.777: E/AndroidRuntime(28573):    ... 5 more
03-02 16:59:41.437: E/WindowManager(28573): Activity com.jearom.thesisfmanager.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@41d3a0c0 that was originally added here
03-02 16:59:41.437: E/WindowManager(28573): android.view.WindowLeaked: Activity com.jearom.thesisfmanager.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@41d3a0c0 that was originally added here
03-02 16:59:41.437: E/WindowManager(28573):     at android.view.ViewRootImpl.(ViewRootImpl.java:344)
03-02 16:59:41.437: E/WindowManager(28573):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:267)
03-02 16:59:41.437: E/WindowManager(28573):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215)
03-02 16:59:41.437: E/WindowManager(28573):     at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140)
03-02 16:59:41.437: E/WindowManager(28573):     at android.view.Window$LocalWindowManager.addView(Window.java:537)
03-02 16:59:41.437: E/WindowManager(28573):     at android.app.Dialog.show(Dialog.java:278)
03-02 16:59:41.437: E/WindowManager(28573):     at com.jearom.thesisfmanager.MainActivity$MyTask.onPreExecute(MainActivity.java:1867)
03-02 16:59:41.437: E/WindowManager(28573):     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:561)
03-02 16:59:41.437: E/WindowManager(28573):     at android.os.AsyncTask.execute(AsyncTask.java:511)
03-02 16:59:41.437: E/WindowManager(28573):     at com.jearom.thesisfmanager.MainActivity$6.onClick(MainActivity.java:752)
03-02 16:59:41.437: E/WindowManager(28573):     at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
03-02 16:59:41.437: E/WindowManager(28573):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-02 16:59:41.437: E/WindowManager(28573):     at android.os.Looper.loop(Looper.java:137)
03-02 16:59:41.437: E/WindowManager(28573):     at android.app.ActivityThread.main(ActivityThread.java:4456)
03-02 16:59:41.437: E/WindowManager(28573):     at java.lang.reflect.Method.invokeNative(Native Method)
03-02 16:59:41.437: E/WindowManager(28573):     at java.lang.reflect.Method.invoke(Method.java:511)
03-02 16:59:41.437: E/WindowManager(28573):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
03-02 16:59:41.437: E/WindowManager(28573):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
03-02 16:59:41.437: E/WindowManager(28573):     at dalvik.system.NativeStart.main(Native Method)

Community
  • 1
  • 1
  • Look at this link: maybe it will help you http://stackoverflow.com/questions/13694850/java-start-one-background-thread-after-another-complete – HK.avdalyan Mar 02 '14 at 09:38
  • post the full stacktrace not just 1 line and you need a return statement in `doInbackground()` – Raghunandan Mar 02 '14 at 09:54
  • You're allocating way too much memory with at MainActivity.java:2270. Also try to not have such big classes, refactor. – m0skit0 Mar 02 '14 at 11:01
  • I think its something to do with junrar. It consumes a lot of memory with certain RAR files. That's why I'm trying to catch the error here. – The_Student Mar 02 '14 at 11:09

2 Answers2

1

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

For more information :http://developer.android.com/reference/android/os/AsyncTask.html

Here is one example

  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");
  }
}
M D
  • 47,665
  • 9
  • 93
  • 114
  • I am already using onPostExecute(Result), but the thing is that my app crashes during the doInBackground stage, so what I'm thinking is to check if the extraction will have no error during the doInBackground stage. – The_Student Mar 02 '14 at 09:46
  • @The_Student post your logcat then. – M D Mar 02 '14 at 09:47
  • Here: 03-02 16:59:40.777: E/AndroidRuntime(28573): FATAL EXCEPTION: AsyncTask #1 03-02 16:59:40.777: E/AndroidRuntime(28573): java.lang.RuntimeException: An error occured while executing doInBackground() 03-02 16:59:40.777: E/AndroidRuntime(28573): at android.os.AsyncTask$3.done(AsyncTask.java:278) – The_Student Mar 02 '14 at 09:50
  • @The_Student edit your post and post the same. Also if there is a crash happening in `doInbackground` the control does not go to `onPostExecute`. – Raghunandan Mar 02 '14 at 09:52
  • @The_Student put your all code and logcat into your question. – M D Mar 02 '14 at 09:52
  • @Simple Plan: there it is. – The_Student Mar 02 '14 at 09:59
0

You can solve this problem using SharedPreferences by creating a SharedPreference file that hold the state of each action you perform on a file using it name as a KEY and a boolean value that describe the state of it either succeeded in extraction or not. Also make your method return true if the process succeded and false otherwise.

Modify your constructor as the following to save the context of the app

private ProgressDialog progress;
private Context mContext;
public MyTask(ProgressDialog progress, Context context) {
  this.progress = progress;   
  this.mContext = context;
}

Replace your doInBackground method with this one:

@Override
protected Void doInBackground(Void... params) {
if(taskType==1){
     if(extractArchive(rarFile, destinationFolder)){
        SharedPreferences myLog = mContext.getSharedPreferences("state_holder", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = myLog.edit();
        editor.putBoolean("file_name", true);
        editor.commit();
   }            
}
return null;
}    

More info about SharedPReference in this LINK

Sami Eltamawy
  • 9,874
  • 8
  • 48
  • 66
  • Let me try this method. I will get back here if it works. Thanks. – The_Student Mar 02 '14 at 09:55
  • I think I can't apply this method on my codes. Can you help me how can I apply the same approach on my codes? I update my codes on the question. – The_Student Mar 02 '14 at 10:24
  • Ok, wait I create this modifications for you – Sami Eltamawy Mar 02 '14 at 10:25
  • @The_Student check the new answer – Sami Eltamawy Mar 02 '14 at 10:32
  • replace the string `file_name` with your file name and when you get want to get this value later check the link provided :). I hope it helps and don`t forget to vote up and accept it if you found my answer somehow useful. Feel free to ask any further questions @The_Student – Sami Eltamawy Mar 02 '14 at 10:43
  • can I ask again? What does Context.MODE_PRIVATE do? I'm getting this error: "The method getSharedPreferences(String, int) is undefined for the type MainActivity.MyTask". Sorry Im not really familiar with these. – The_Student Mar 02 '14 at 10:47
  • Context.MODE_PRIVATE makes your preferences are only visible for you app not public for all apps. Makes sure you are importing the class `Context` in your main class and modify your `AsyncTask` constructor to take the context from your activity and save it. I will post this edits for you – Sami Eltamawy Mar 02 '14 at 10:55
  • Try the new modifications, Pass `this` to the constructor in the `context` parametere – Sami Eltamawy Mar 02 '14 at 11:00
  • Hmm... Thanks for your help Abd, but I think I can't perform this anymore because junRAR is the real problem here. Its taking too much memory while extracting. I think I need to find other library. Thanks again for your help! – The_Student Mar 02 '14 at 11:17