-5

I am getting the following exception when pressing home button while the progress dialog is visible.I have gone through lot of SO posts but they have given solution only for a activity screen. In this scenario i am getting this exception in a non-activity screen ie in my array adapter.

Exception:

android.view.WindowLeaked: Activity com.meru.parryvaibhav.MrpActivity has leaked window com.android.internal.policy.PhoneWindow$DecorView{78d89f9 V.E...... R......D 0,0-480,174} that was originally added here
 at android.view.ViewRootImpl.<init>(ViewRootImpl.java:460)
 at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:306)
 at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
 at android.app.Dialog.show(Dialog.java:326)
 at com.android.andy.ResourceArrayAdapter$DownloadFileTask.onProgressUpdate(ResourceArrayAdapter.java:297)
 at com.android.andy.ResourceArrayAdapter$DownloadFileTask.onProgressUpdate(ResourceArrayAdapter.java:192)
 at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:671)
 at android.os.Handler.dispatchMessage(Handler.java:111)
 at android.os.Looper.loop(Looper.java:207)
 at android.app.ActivityThread.main(ActivityThread.java:5728)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679)

Adapter Code:

 package com.android.andy;

import java.util.ArrayList;
import java.util.List;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

import android.content.Context;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.view.LayoutInflater;
import android.widget.TextView;
import android.widget.Button;
import android.os.AsyncTask;
import android.content.Intent;
import java.net.*;

import java.io.BufferedInputStream;
import android.net.Uri;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.widget.Toast;
import android.os.Environment;;
import android.view.View.OnClickListener;

import android.content.SharedPreferences;
import android.app.ProgressDialog;
import android.webkit.MimeTypeMap;


public class ResourceArrayAdapter extends ArrayAdapter<ResourceElement>
{
private List<ResourceElement> messages = new ArrayList<ResourceElement>();
LayoutInflater inflater;
Uri uri=null;
private SharedPreferences userPrefer;


@Override
public void add(ResourceElement object)
{
    messages.add(object);
    super.add(object);
}

public void addAll(List<ResourceElement> list)
{
    messages.addAll(list);
    //super.addAll(list);
}
public void clear()
{
    messages.clear();
    //super.addAll(list);
}
@Override
public void remove(ResourceElement object)
{
        messages.remove(object);
        super.remove(object);
}
private static class ViewHolder
{
    TextView sno;
    TextView description;
    Button view_pdf;
    //TableLayout table;

}
public ResourceArrayAdapter(Context context, int textViewResourceId)
{
    super(context, textViewResourceId);
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    userPrefer = context.getSharedPreferences(Props.USERPREFERENCES, Context.MODE_PRIVATE);
}

public int getCount()
{
    return this.messages.size();
}

public ResourceElement getItem(int index)
{
    return this.messages.get(index);
}
public View getView(int position, View convertView, ViewGroup parent)
{
    ViewHolder holder;

    if (convertView == null)
    {

        convertView = inflater.inflate(R.layout.resource_element, parent, false);
        holder = new ViewHolder();
        holder.sno = (TextView) convertView.findViewById(R.id.sno);
        //holder.table = (TableLayout) convertView.findViewById(R.id.table_layout);
        holder.description = (TextView) convertView.findViewById(R.id.description);
        holder.view_pdf = (Button) convertView.findViewById(R.id.view_pdf);

        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    }





    holder.view_pdf.setOnClickListener(new OnClickListener()
    {
          public void onClick(View view)
          {

                  new DownloadFileTask(reportPath,sno,size).execute();

          }
    });

    return convertView;
}

private class DownloadFileTask extends AsyncTask<String, String, String>
{
        private ProgressDialog vDialog;
        private String webpath,sno,size;String filename,filepath;String response="false";
        public DownloadFileTask(String wpath,String ser_no,String file_size)
        {
            sno = ser_no;
            webpath = wpath;
            size = file_size;
        }
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
            // Get the screen's density scale
             vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
        }
        @Override
        protected String doInBackground(String... args)
        {
            publishProgress("");
            StringBuilder sb = new StringBuilder(webpath.replaceFirst(".*/([^/?]+).*", "$1"));
            filename = sb.toString();

            InputStream inputStream=null;
            FileOutputStream outputStream =null; HttpURLConnection connection = null;long fileSize =0L,freespace=0L;
            try
            {
                URL filURL = new URL(webpath);
                byte buffer[] = new byte[1024];
                int dataSize;
                long loadedSize = 0L;

                connection =(HttpURLConnection) filURL.openConnection();

                int resCode = connection.getResponseCode();
                if(!(resCode == HttpURLConnection.HTTP_ACCEPTED || resCode == HttpURLConnection.HTTP_OK))
                {
                    response = connection.getResponseMessage();
                    return response;
                }
                fileSize = connection.getContentLength();
                File appdataDir = getDataFolder(ResourceArrayAdapter.this.getContext());
                freespace = appdataDir.getFreeSpace();
                if(fileSize > freespace)
                {
                  response="Insufficient Storage.Free "+String.format("%.2f", (((double)(fileSize-freespace))/(1024*1024)))+" MB space.";
                  return response;
                }
                inputStream = new BufferedInputStream(filURL.openStream(), 10240);

                File cacheFile = new File(appdataDir,filename);
                cacheFile.createNewFile();
                filepath = cacheFile.getAbsolutePath();
                outputStream = new FileOutputStream(cacheFile);

                while ((dataSize = inputStream.read(buffer)) != -1)
                {
                   loadedSize += dataSize;
                   outputStream.write(buffer, 0, dataSize);

                   //publishProgress((((float)loadedSize/fileSize)));

                   response="true";
                }
                outputStream.close();

             }
             catch(Exception e)
             {
                 response = e.getMessage();
                 e.printStackTrace();
             }
             finally
             {
                 try{
                 if(outputStream!=null)
                      outputStream.close();
                  if(inputStream!=null)
                      inputStream.close();
                  }catch(Exception ioex){}
             }


            return response;
        }
        @Override
        protected void onProgressUpdate(String... dprogress)
        {
            super.onProgressUpdate();

             vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
              vDialog.setMessage("Downloading "+filename+"..");
              vDialog.setIndeterminate(false);
              vDialog.setCancelable(false);
            Log.e("vdialog: ","Showing");


                try{
                    vDialog.show();    //getting error here
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }


        }
        @Override
        protected void onPostExecute(String isdownloaded)
        {
            if ((vDialog != null) && vDialog.isShowing()) {
                vDialog.dismiss();
            }

            if (isdownloaded.equals("true"))
            {
            try{
                File localpath = new File(getDataFolder(ResourceArrayAdapter.this.getContext()),filename);
                   if(localpath.exists())
                   {
                       Intent intent = new Intent();
                       intent.setAction(Intent.ACTION_VIEW);
                       intent.setData(Uri.fromFile(localpath));
                       ResourceArrayAdapter.this.getContext().startActivity(intent);
                   }
                  }
                  catch(Exception fe)
                  {

                  }

                 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
                 {
                         new SendDownloadAck(sno,size,webpath).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

                 } else
                 {
                      new SendDownloadAck(sno,size,webpath).execute();
                  }
            }
            else
            {
              Toast.makeText(ResourceArrayAdapter.this.getContext(),"Download Failed.", Toast.LENGTH_SHORT).show();
            }

         }

    }

}


 This Async Task is used for downloading a PDF file which may take 30 secs upto one minute. so in that time interval if the user presses the home button i am getting this error. I need to know where to dismiss the progress dialog which runs in a adapter class.

Edit1:

 private class DownloadFileTask extends AsyncTask<String, String, String>
{
        private ProgressDialog vDialog;
        private String webpath,sno,size;String filename,filepath;String response="false";
        public DownloadFileTask(String wpath,String ser_no,String file_size)
        {
            sno = ser_no;
            webpath = wpath;
            size = file_size;
        }
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();


            vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
            vDialog.setMessage("Downloading "+filename+"..");
            vDialog.setIndeterminate(false);
            vDialog.setCancelable(false);
            vDialog.show();
        }
        @Override
        protected String doInBackground(String... args)
        {
            publishProgress("");
            StringBuilder sb = new StringBuilder(webpath.replaceFirst(".*/([^/?]+).*", "$1"));
            filename = sb.toString();

            InputStream inputStream=null;
            FileOutputStream outputStream =null; HttpURLConnection connection = null;long fileSize =0L,freespace=0L;
            try
            {
                URL filURL = new URL(webpath);
                byte buffer[] = new byte[1024];
                int dataSize;
                long loadedSize = 0L;

                connection =(HttpURLConnection) filURL.openConnection();

                int resCode = connection.getResponseCode();
                if(!(resCode == HttpURLConnection.HTTP_ACCEPTED || resCode == HttpURLConnection.HTTP_OK))
                {
                    response = connection.getResponseMessage();
                    return response;
                }
                fileSize = connection.getContentLength();
                File appdataDir = getDataFolder(ResourceArrayAdapter.this.getContext());
                freespace = appdataDir.getFreeSpace();
                if(fileSize > freespace)
                {
                  response="Insufficient Storage.Free "+String.format("%.2f", (((double)(fileSize-freespace))/(1024*1024)))+" MB space.";
                  return response;
                }
                inputStream = new BufferedInputStream(filURL.openStream(), 10240);

                File cacheFile = new File(appdataDir,filename);
                cacheFile.createNewFile();
                filepath = cacheFile.getAbsolutePath();
                outputStream = new FileOutputStream(cacheFile);

                while ((dataSize = inputStream.read(buffer)) != -1)
                {
                   loadedSize += dataSize;
                   outputStream.write(buffer, 0, dataSize);

                   //publishProgress((((float)loadedSize/fileSize)));

                   response="true";
                }
                outputStream.close();

             }
             catch(Exception e)
             {
                 response = e.getMessage();
                 e.printStackTrace();
             }
             finally
             {
                 try{
                 if(outputStream!=null)
                      outputStream.close();
                  if(inputStream!=null)
                      inputStream.close();
                  }catch(Exception ioex){}
             }


            return response;
        }
}

        @Override
        protected void onPostExecute(String isdownloaded)
        {
            if ((vDialog != null) && vDialog.isShowing()) {
                vDialog.dismiss();
            }

            if (isdownloaded.equals("true"))
            {
            try{
                File localpath = new File(getDataFolder(ResourceArrayAdapter.this.getContext()),filename);
                   if(localpath.exists())
                   {
                       Intent intent = new Intent();
                       intent.setAction(Intent.ACTION_VIEW);
                       intent.setData(Uri.fromFile(localpath));
                       ResourceArrayAdapter.this.getContext().startActivity(intent);
                   }
                  }
                  catch(Exception fe)
                  {

                  }

                 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
                 {
                         new SendDownloadAck(sno,size,webpath).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

                 } else
                 {
                      new SendDownloadAck(sno,size,webpath).execute();
                  }
            }
            else
            {
              Toast.makeText(ResourceArrayAdapter.this.getContext(),"Download Failed.", Toast.LENGTH_SHORT).show();
            }

         }

    }
Rakesh Polo
  • 431
  • 1
  • 9
  • 27
  • I think this is because you have created `vDialog` twice and `dismiss()` will only called for newer one cause you have lost the reference to older one . – ADM Jan 17 '18 at 05:12
  • @Rakesh, I think your activity killed but still Any Dialog is there so You are getting this exception – coder_baba Jan 17 '18 at 05:13
  • @Rakesh so first dismiss your dialog and then kill activity – coder_baba Jan 17 '18 at 05:14
  • @ADM Now i have removed the creation of one vDialog but getting the same exception – Rakesh Polo Jan 17 '18 at 05:18
  • just remove `onProgressUpdate()` and call `vDialog.show()` in `onPreExecute()`. – ADM Jan 17 '18 at 05:22
  • @Zoe i have clearly explained that the exception occurs here is in a non-activity class. The duplicate you have quoted is partially irrelevant where you have access to `onDestroy` or `onPause` methods whereas here i don't have. – Rakesh Polo Jan 17 '18 at 06:48
  • @zoe I clearly understand why this exception occurs. i have read all the links before posting the question. i am asking for a solution on how to dismiss the progress dialog in a **NonActivity** class. – Rakesh Polo Jan 17 '18 at 06:56
  • @zoe Can you give me a proper reason or explanation on what made you feel or think that this question might be a possible duplicate ? – Rakesh Polo Jan 17 '18 at 07:09

3 Answers3

2

I wonder why are you creating ProgressDialog in onProgressUpdate()? There is no meaning as you are not updating progress.

Instead what you can do is - create and show ProgressDialog into onPreExecute(..) and dismiss into onPostExecute(..)

@Override
protected void onPreExecute() {
    super.onPreExecute();
    vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
    vDialog.setMessage("Downloading "+filename+"..");
    vDialog.setIndeterminate(false);
    vDialog.setCancelable(false);
    vDialog.show();
}

// Remove `onProgressUpdate()` completely.

@Override
protected void onPostExecute(String isdownloaded) {
    super.onPostExecute();
    if ((vDialog != null) && vDialog.isShowing()) {
        vDialog.dismiss();
    }
}

As, ADM mentioned in above comment, what you are doing is - You are creating another window in the terms of ProgressDialog while it is already existing in the current window. So the previous reference is being lost, hence result in leak.

Paresh P.
  • 6,677
  • 1
  • 14
  • 26
  • Now i have removed the `onProgressUpdate()` completely and added `onPreExecute` as you have mentioned. But still i am getting the same exception. no change @Wizard – Rakesh Polo Jan 17 '18 at 05:34
  • Update your code by Editing your question. – Paresh P. Jan 17 '18 at 05:35
  • I have updated the code @Wizard – Rakesh Polo Jan 17 '18 at 05:41
  • Okay, How about replacing `ResourceArrayAdapter.this.getContext()` with an `Activtiy` context?.. and add `super()` into `onPostExecute()`. – Paresh P. Jan 17 '18 at 05:47
  • Like replacing `ResourceArrayAdapter.this.getContext()` with `Activtiy.getContext` ?? and about the `super()` i have already added `super.onPreExecute();` sorry if its dumb. @Wizard – Rakesh Polo Jan 17 '18 at 05:54
  • Yes. May be you can pass `Activity` context to an adapter and use it to you `AsyncTask`. And I was talking about `super.onPostExecute()`. – Paresh P. Jan 17 '18 at 05:57
1

In you case

 vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext());
              vDialog.setMessage("Downloading "+filename+"..");
              vDialog.setIndeterminate(false);
              vDialog.setCancelable(false);

the first line should not initialize the ProgressDialog each time there is an progress update. You already have done the initialization in the PreExecute() stub. So remove vDialog = new ProgressDialog(ResourceArrayAdapter.this.getContext()); and if you continue to get the error in the same line within try statement, disclose the stackTrace. And moreover the ProgressDialog must be shown in the PreExecuteStub(), only updations should take place in this onProgressUpdate()

Have a look at this post

This (Window Leaks) usually happens when you call a method for a View element when the view is not yet created or has been destroyed. Such as setting OnCLickListener to a View on the Fragment in onAttach stub, whereas the listener must be placed after the view has been inflated in onCreateView() stub. I suggest you take a look at the lifecycle of different overridable methods of the Class you're getting this error upon, even if the problem is solved.

  • i have removed the initialization in `onProgressUpdate()` and added it in `onPreExecute` as you said. But still i am getting the same exception. @Koushik – Rakesh Polo Jan 17 '18 at 05:35
  • did any of the provided solutions work? If not, just remove the progress dialog from everywhere and see if it works then. – Koushik Shom Choudhury Jan 17 '18 at 05:53
  • as far now nothing worked – Rakesh Polo Jan 17 '18 at 05:54
  • After removing the **ProgressDialog** completely from everywhere, where is the error coming from? Specify exactly. – Koushik Shom Choudhury Jan 17 '18 at 05:57
  • I have now hidden all the code related to `ProgressDialog` while pressing home button when downloading process is in progress i don't get any errors now. – Rakesh Polo Jan 17 '18 at 06:11
  • Please upvote, if you think I was able to help for a bit. And now, You'll have to find a proper way to integrate the ProgressDialog now. Keep in mind to use the Context reference of the Activity you're performing this AsyncTask on as the context of the ProgressDialog. – Koushik Shom Choudhury Jan 17 '18 at 06:21
0

As per my understanding, You can do this

    @Override
    public void onDestroy(){
    super.onDestroy();
    if ( dialog!=null && dialog.isShowing() ){
        dialog.dismiss();
    }
}
vm345
  • 813
  • 12
  • 28
coder_baba
  • 447
  • 3
  • 21