Asynctask Android generating Nullpointerexception

Asked

Viewed 63 times

0

I have this static class in an Activity where its function is to download a file and save it on the user’s device. I tested on a real device in the version of Android 7.1.1 and 4.1.2 and worked correctly. However, while launching the application I have received error reports from Android versions 7.1, 6.0 and 7.0 relating to Nullpointerexception of the process doInBackground in the reference line catch (Exception and)

Class code

private static class DownloadFileFromURL extends AsyncTask<String, String, String> {

    private WeakReference<DownloadActivity> activityReference;

    DownloadFileFromURL(DownloadActivity context) {
        activityReference = new WeakReference<>(context);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        DownloadActivity activity = activityReference.get();
        activity.txt_status_progress.setText(String.format(activity.getString(R.string.txt_baixando_dados),String.valueOf(0)));
    }

    @Override
    protected String doInBackground(String... f_url) {

        DownloadActivity activity = activityReference.get();

        int count;

        try {
            URL url = new URL(f_url[0]);
            URLConnection conection = url.openConnection();
            conection.connect();

            int lenghtOfFile = conection.getContentLength();

            InputStream input = new BufferedInputStream(url.openStream(), 8192);

            FileOutputStream output = activity.openFileOutput(FOLDER + File.pathSeparator + FILE_SQL, Context.MODE_PRIVATE);

            byte data[] = new byte[1024];

            long total = 0;

            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress("" + (int) ((total * 100) / lenghtOfFile));
                output.write(data, 0, count);
            }
            output.flush();
            output.close();
            input.close();

        } catch (Exception e) {
            progressBar.setVisibility(View.GONE);
            txt_status_progress.setText(R.string.txt_erro_config);
        }
        return null;
    }

    protected void onProgressUpdate(String... progress) {
        DownloadActivity activity = activityReference.get();
        activity.txt_status_progress.setText(String.format(activity.getString(R.string.txt_baixando_dados),progress[0]));
    }

    @Override
    protected void onPostExecute(String file_url) {
        DownloadActivity activity = activityReference.get();
        new DownloadActivity.insertFromFile(activity).execute();
    }
}

What could be causing this error?

1 answer

1


Probably Activity, in which the download is taking place, is being destroyed by the system but the task continues running. And anywhere you access the variable activity(or any variable that belongs to the destroyed Activity) will generate a nullpointer, because this reference no longer exists.

Asynctasks do not follow the same life cycle as the Activity in which they started it. So it’s entirely possible that Asynctask will continue running while Activity no longer exists. Which can generate the problem you’re having. As much as you passed the Activity reference in the Asynctask constructor, Android may have killed her, so the reference you are currently holding in Asynctask is invalid and any attribute or method access will generate nullpointer.

As you have not given information that it is possible to change the orientation of the phone to horizontal and if there is the possibility to go to a next Activity during the download, I will assume that both are true.

There are some ways to test this hypothesis.

  1. The simplest is just start the download and close the app(kill the process) and see what happens.
  2. You can also start downloading and change the orientation of the mobile phone to horizontal, if possible.
  3. Another is to go to the developer settings and set the "do not keep activities" option. Start the download and go open a new Activity.

Probably scenarios 1. and 2. will actually show the cause of the bug.

And a possible solution would be for you to use Fragments to not only download, but for any use of Threads that access class variables.

Fragments has a method called setRetainInstance, which serves to maintain the current instance of Fragment when a Configuration change in the Activity on which Fragment is committed.

Another solution would be to kill(call the method cancel) a Asynctask no onDestroy of its Activty.

  • Max Fratane, thank you for your reply. You are absolutely right, the orientation of Activity was not configured, in xml, to Portrait to avoid the rotation of the screen, but I already fixed it. Regarding leaving the downlaod Activity, there is no such possibility, because the user is directed to download Activity and only after completing the process is directed to another Activity, this is done programmatically. I will perform test 1 and 3 and implement the Cancel method in onDestroy as you suggested. As soon as I finish the tests I mark the answer. Thanks again!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.