0

currently I am developing an Android Application (Native). In my application, I need to load many images and that cause a problem.

The problem is: 1. When I first open the app after deploy it on my android phone, it works fine. However, after I close the application (by clicking the back button), and then I open the application again, the app closed unexpectedly. When I check the logcat, I found out that it was closed because of OutOfMemory error. 2. Second problem: after I open my application, and I go to the next page, it also give me OutOfMemory error.

I guess, the problem occur because I load too many images. After I do some searching on the internet, it suggest me to do System.gc

But unfortunately, it did not work for me.

Here is my code:

Homepage_Activity.java

package dev.com.friseur;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import dev.friseur.insert.AddComment;
import dev.friseur.rest.Photo;

import android.support.v7.app.ActionBarActivity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.SystemClock;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

public class HomePage extends ActionBarActivity {

    private String p_id = "1";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_page);

        Intent intent = getIntent();

        int size = Integer.parseInt(intent.getStringExtra("size")) * 2;
        LinearLayout hp = (LinearLayout)findViewById(R.id.homepage);
        Photo photo = new Photo(hp, this, size);
        photo.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.home_page, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

The photo.execute() code will call an asynchronous task. Here it is:

package dev.friseur.rest;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import dev.com.friseur.RecognizeFace;
import dev.com.friseur.ViewPhoto;
import dev.friseur.insert.AddComment;
import dev.friseur.insert.AddLike;

import android.R;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.SystemClock;
import android.text.InputFilter;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

public class Photo extends AsyncTask<String, Void, String>{

    private Context context;
    private LinearLayout homepage;
    private int size;
    private String sessionUname;
    private String sessionUserid;
    private File file;
    private ArrayList<String> photo_id;
    private ArrayList<String> imageName;
    private ArrayList<String> date_upload;
    private ArrayList<String> url_original;
    private ArrayList<String> url_with_hair;
    private ArrayList<String> caption;
    private ArrayList<String> user_id;
    private ArrayList<String> username;
    private ArrayList<JSONArray> comments;
    private ArrayList<Integer> totalcomment;

    public Photo(LinearLayout homepage, Context context, int size){
        this.context = context;
        this.homepage = homepage;
        this.size = size;
        this.sessionUname = "testuser";
        this.sessionUserid = "1";

        photo_id = new ArrayList<String>();
        imageName = new ArrayList<String>();
        date_upload = new ArrayList<String>();
        url_original = new ArrayList<String>();
        url_with_hair = new ArrayList<String>();
        caption = new ArrayList<String>();
        user_id = new ArrayList<String>();
        username = new ArrayList<String>();
        comments = new ArrayList<JSONArray>();
        totalcomment = new ArrayList<Integer>();
    }

    @Override
    protected String doInBackground(String... arg0) {
        // TODO Auto-generated method stub
        InputStream is = null;
        //http post
        try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost("http://192.168.43.8:8080/FriseurRest/WebService/GetPhotos");
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();
        }
        catch(Exception e){
                Log.e("log_tag", "Error in http connection "+e.toString());
        }

        //convert response to string
        try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                int i = 0;
                while ((line = reader.readLine()) != null) {
                    JSONObject json_data = new JSONObject(line);

                    photo_id.add(json_data.getString("p_id"));
                    imageName.add(json_data.getString("imagename"));
                    date_upload.add(json_data.getString("date_upload"));
                    url_original.add(json_data.getString("url_original"));
                    url_with_hair.add(json_data.getString("url_with_hair"));
                    caption.add(json_data.getString("caption"));
                    user_id.add(Integer.toString(json_data.getInt("user_id")));
                    username.add(json_data.getString("username"));
                    comments.add(json_data.getJSONArray("photoComments"));
                    totalcomment.add(json_data.getInt("total_comment"));
                    i++;
                }
                is.close();

        }catch(Exception e){
                Log.e("log_tag", "Error converting result "+e.toString());
        }
        return null;
    }

    protected void onDestroy() {
        System.gc();
        Runtime.getRuntime().gc();
    }

    protected void onPostExecute(String p_id) {
        for(int i = 0; i < imageName.size(); i++){
            final int j = i;
            LinearLayout photo = new LinearLayout(context);
            photo.setOrientation(LinearLayout.VERTICAL);
            photo.setPadding(0, 0, 0, 50);

            LinearLayout postdesc = createPostDesc(i);

            file = new File(Environment.getExternalStorageDirectory() + "/" + url_original.get(i), imageName.get(i));
            Uri imgUri = Uri.fromFile(file);

            ImageView img = new ImageView(context);
            img.setImageURI(imgUri);

            img.setMaxWidth(size);
            img.setMinimumWidth(size);
            img.setMaxHeight(size);
            img.setMinimumHeight(size);

            TextView tv = new TextView(context);
            tv.setText(caption.get(i));

            final LinearLayout showcomment = new LinearLayout(context);
            showcomment.setOrientation(LinearLayout.VERTICAL);
            showcomment.setPadding(0, 10, 0, 10);

            try {

                if(totalcomment.get(i) > 5){
                    LinearLayout more = new LinearLayout(context);
                    more.setPadding(0, 0, 0, 5);

                    TextView viewmore = new TextView(context);
                    viewmore.setTextColor(Color.GRAY);
                    viewmore.setText("View More Comments");
                    viewmore.setClickable(true);
                    viewmore.setOnClickListener(new View.OnClickListener() {
                        public void onClick(View v) {
                            Intent intent = new Intent(context, ViewPhoto.class);
                            intent.putExtra("size", size);
                            intent.putExtra("p_id", photo_id.get(j));
                            intent.putExtra("imageName", imageName.get(j));
                            intent.putExtra("date_upload", date_upload.get(j));
                            intent.putExtra("url_original", url_original.get(j));
                            intent.putExtra("url_with_hair", url_with_hair.get(j));
                            intent.putExtra("caption", caption.get(j));
                            intent.putExtra("user_id", user_id.get(j));
                            intent.putExtra("username", username.get(j));
                            context.startActivity(intent);
                        }
                    });

                    more.addView(viewmore);
                    showcomment.addView(more);
                }

                for(int k = 0; k < comments.get(i).length(); k++) {
                    //ArrayList<String> photoCom = comments.get(k);
                    //int userCom = photoCom.length();

                    JSONObject photoCom = comments.get(i).getJSONObject(k);

                    LinearLayout ll_comment = new LinearLayout(context);
                    ll_comment.setPadding(0, 0, 0, 5);

                    TextView uname = new TextView(context);
                    uname.setTextColor(Color.BLUE);
                    uname.setPadding(0,0,3,0);
                    uname.setText(photoCom.getString("com_username"));

                    TextView showcom = new TextView(context);
                    showcom.setText(photoCom.getString("com_desc"));

                    ll_comment.addView(uname);
                    ll_comment.addView(showcom);

                    showcomment.addView(ll_comment);
                }
            } catch (Exception e) {
            }

            LinearLayout addcomment = createAddComment(i);
            final EditText et_comment = new EditText(context);
            et_comment.setHint("Add Comment");
            et_comment.setMaxWidth(size*3/4);
            et_comment.setMinimumWidth(size*3/4);
            int maxLength = 150;    
            et_comment.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength)});

            Button button_comment = new Button(context);
            button_comment.setText("Post");
            button_comment.setTextSize(15);
            button_comment.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                    String com = et_comment.getText().toString();

                    try{
                        AddComment ac = new AddComment(sessionUserid, com, photo_id.get(j));
                        ac.execute();
                    }
                    catch(Exception e){
                        CharSequence text = "Internet Connection Unstable. Please Try Again!";
                        int duration = Toast.LENGTH_SHORT;

                        Toast toast = Toast.makeText(context, text, duration);
                        toast.show();
                    }

                    LinearLayout ll_comment = new LinearLayout(context);
                    ll_comment.setPadding(0, 0, 0, 5);

                    TextView uname = new TextView(context);
                    uname.setTextColor(Color.BLUE);
                    uname.setPadding(0,0,3,0);
                    uname.setText(sessionUname);

                    TextView showcom = new TextView(context);
                    showcom.setText(com);
                    showcom.setAnimation(AnimationUtils.loadAnimation(context, android.R.anim.fade_in));

                    et_comment.setText("");

                    ll_comment.addView(uname);
                    ll_comment.addView(showcom);

                    showcomment.addView(ll_comment);
                }
            });

            addcomment.addView(et_comment);
            addcomment.addView(button_comment);

            addcomment.setVisibility(View.GONE);

            LinearLayout social = createSocialFeature(i, addcomment, et_comment);

            photo.addView(postdesc);
            photo.addView(img);
            photo.addView(tv);
            photo.addView(showcomment);
            photo.addView(social);
            photo.addView(addcomment);

            homepage.addView(photo);
        }
    }

    private LinearLayout createPostDesc(int i){
        LinearLayout postdesc = new LinearLayout(context);
        postdesc.setOrientation(LinearLayout.VERTICAL);
        postdesc.setMinimumHeight(40);


        TextView uname = new TextView(context);
        uname.setText("@"+username.get(i));

        TextView timeupload = new TextView(context);
        timeupload.setText(date_upload.get(i));

        if(i>0){
            View separator = new View(context);
            separator.setMinimumHeight(1);
            separator.setBackgroundColor(Color.BLACK);
            separator.setPadding(0, 10, 0, 0);

            postdesc.addView(separator);
        }

        postdesc.addView(uname);
        postdesc.addView(timeupload);

        return postdesc;
    }

    private LinearLayout createSocialFeature(final int i, final LinearLayout addcomment, final EditText et_comment){
        LinearLayout social = new LinearLayout(context);
        social.setOrientation(LinearLayout.HORIZONTAL);
        social.setMinimumHeight(40);
        social.setPadding(0,10,10,0);

        TextView tv_comment = new TextView(context);
        tv_comment.setText("Add Comment");
        tv_comment.setPadding(0, 0, 15, 0);
        tv_comment.setClickable(true);
        tv_comment.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                addcomment.setVisibility(View.VISIBLE);

                et_comment.setFocusableInTouchMode(true);
                et_comment.setFocusable(true);

                et_comment.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN , 0, 0, 0));
                et_comment.dispatchTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP , 0, 0, 0)); 
            }
        });

        final TextView tv_like = new TextView(context);
        tv_like.setText("Like");
        tv_like.setClickable(true);
        tv_like.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                String like = tv_like.getText().toString();

                try{
                    AddLike lk = new AddLike(sessionUserid, like, photo_id.get(i));
                    lk.execute();
                }
                catch(Exception e){
                    CharSequence text = "Internet Connection Unstable. Please Try Again!";
                    int duration = Toast.LENGTH_SHORT;

                    Toast toast = Toast.makeText(context, text, duration);
                    toast.show();
                }

                if(like.equals("Like")){
                    tv_like.setText("Unlike");
                }
                else{
                    tv_like.setText("Like");
                }
            }
        });

        social.addView(tv_comment);
        social.addView(tv_like);

        return social;
    }

    private LinearLayout createAddComment(int i){
        LinearLayout addcomment = new LinearLayout(context);
        addcomment.setId(Integer.parseInt(photo_id.get(i)));
        addcomment.setOrientation(LinearLayout.HORIZONTAL);
        addcomment.setPadding(0,20,0,0);

        return addcomment;
    }
}

This asynchronous task used to call the rest service.

What is wrong with my code? And how can I solve the OutOfMemory error. Any help would be appreciated. Thanks in advance

pokopang
  • 507
  • 1
  • 11
  • 27
  • 1
    1) When dealing with dynamic images, always make sure you read and understood [this](http://developer.android.com/training/displaying-bitmaps/index.html), including all 5 lessons at the bottom. 2) You have posted a lot of code. You should try and narrow down the error to a particular section and come back with a more specific error. – Krishnabhadra Oct 16 '14 at 07:07
  • However this code has no loading of images that I can see. Only loading of the meta data of images. How many elements are we talking. You may want to look into adapter views, which don't require all your elements in memory. Rather than keep elements all in memory even if off screen, you can page from disk and preload and swap as needed – Greg Giacovelli Oct 16 '14 at 07:13

2 Answers2

2

You can use lazyloading to fix this and follow this url for lazy loading:

https://github.com/nostra13/Android-Universal-Image-Loader

Harsh Parikh
  • 3,845
  • 3
  • 14
  • 14
0

You can see my answer here.It will be useful to handle your bitmap efficiently.

How to make application more responsive which uses several bitmaps?

Community
  • 1
  • 1
Kailash Dabhi
  • 3,473
  • 1
  • 29
  • 47