Vojtěch Hořánek
Vojtěch Hořánek

Reputation: 117

AsyncTask memory crash

I use AsyncTask to download page html and then extract theme-color and other thing from the html (Also download drawable). This gets executed in onPageStarted like this:

if (interfaceUpdating && !url.contains("download.php")) {
            new themeColorTask().execute(url);
   }                                  

That works completly fine but the problem is when the user downloads a file, it works fine for few seconds but then i get this in crashlog:

12-30 20:08:18.645 3936-3975/cf.vojtechh.apkmirror E/art: Throwing OutOfMemoryError "Failed to allocate a 78465796 byte allocation with 16777168 free bytes and 73MB until OOM"
12-30 20:08:18.755 3936-3975/cf.vojtechh.apkmirror E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing     doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112    )
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 78465796 byte allocation with 16777168 free bytes and 73MB until OOM
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:146)
at java.lang.StringBuilder.append(StringBuilder.java:216)
at cf.vojtechh.apkmirror.MainActivity$themeColorTask.doInBackground(MainActivity.java:679)
at cf.vojtechh.apkmirror.MainActivity$themeColorTask.doInBackground(MainActivity.java:660)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)

This is my AsyncTask:

    private class themeColorTask extends AsyncTask<String, Integer, Integer> {


    @Override
    protected Integer doInBackground(String... url) {
        if (!url[0].contains("download.php")){
            try {
                // Downloading html source
                URLConnection connection = (new URL(url[0])).openConnection();
                connection.setConnectTimeout(5000);
                connection.setReadTimeout(5000);
                connection.connect();


                // Read and store the result line by line then return the entire string.
                InputStream in = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                StringBuilder html = new StringBuilder();
                for (String line; (line = reader.readLine()) != null; ) {
                    html.append(line);
                }
                in.close();

                Source source = new Source(html.toString());

                //theme color
                String extractedThemeColor = ColorDarkTheme;
                List<Element> elements = source.getAllElements("meta");
                for (Element element : elements) {
                    final String id = element.getAttributeValue("name"); // Get Attribute 'id'
                    if (id != null && id.equals("theme-color")) {
                        extractedThemeColor = element.getAttributeValue("content");
                    }
                }

                //App title
                appName = "APKMirror";
                List<Element> h1elements = source.getAllElements("h1");
                for (Element element : h1elements) {
                    final String id = element.getAttributeValue("class"); // Get Attribute 'id'
                    if (id != null && id.contains("app-title")) {
                        appName = element.getAttributeValue("title");
                    }
                }
                if (appName == null) {
                    appName = "APKMirror";
                }

                //Favicon
                List<Element> IMGelements = source.getAllElements("img");
                for (Element element : IMGelements) {
                    final String id = element.getAttributeValue("style"); // Get Attribute 'id'
                    if (id != null && id.matches("width:96px; height:96px;")) {
                        faviconURL = "http://www.apkmirror.com" + element.getAttributeValue("src");
                    }
                }

                // Favicon download
                URLConnection favIconDownload = (new URL(faviconURL)).openConnection();
                favIconDownload.setConnectTimeout(5000);
                favIconDownload.setReadTimeout(5000);
                favIconDownload.connect();

                InputStream favIconDownloadStream = favIconDownload.getInputStream();
                favico = BitmapFactory.decodeStream(favIconDownloadStream);
                favIconDownloadStream.close();



                if (extractedThemeColor != null && !extractedThemeColor.matches("#FF8B14")) {
                    //convert the color to darker color so its nice and material
                    float[] hsv = new float[3];
                    int color = Color.parseColor(extractedThemeColor);
                    Color.colorToHSV(color, hsv);
                    hsv[2] *= 0.8f; // value component
                    themeColor = Color.HSVToColor(hsv);
                    return themeColor;
                } else {
                    //if color is not found we will return orange color
                    return Color.parseColor(ColorDarkTheme);
                }


            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        } else {
            return Color.parseColor(ColorDarkTheme);
        }

    }


    @Override
    protected void onPostExecute(Integer result) {
        // updating interface
        if (isLollipop) {
            setSystemBarColor(result);
        }

        fab.setBackgroundTintList(ColorStateList.valueOf(result));
        drawable.setColorFilter(new LightingColorFilter(0xFF000000, result));
        bottomBar.setBackgroundColor(result);
        swipeRefreshLayout.setColorSchemeColors(result,result,result);

        //updating recents

        if (isLollipop) {
            Bitmap bm = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher_circle);
            if (currentUrl.matches(urlFrontPage)) {
                ActivityManager.TaskDescription taskDesc = new ActivityManager.TaskDescription(getString(R.string.app_name), bm, ContextCompat.getColor(getApplicationContext(), R.color.colorPrimaryDark));
                MainActivity.this.setTaskDescription(taskDesc);
            } else {
                ActivityManager.TaskDescription taskDesc = new ActivityManager.TaskDescription(appName, favico, result);
                MainActivity.this.setTaskDescription(taskDesc);

            }
        }


    }


}

Upvotes: 0

Views: 205

Answers (2)

Vardan95
Vardan95

Reputation: 622

78Mb it's not too much. You can add android:largeHeap="true" in manifest file. Also, don't forget to recycle bitmaps after usage.

Upvotes: 2

pawar
pawar

Reputation: 70

Its not async task I think it's your bitmap object. Try using bitmap.recycle() and the set bitmap = null after you have used bitmap object bm in your post execute.

Upvotes: 0

Related Questions