0

I try to fetch stringBuilder object to the my main activity. I check my json file or parsing codes they works well. However when I try to fetch stringbuilder it gave an error: A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks. java.lang.Throwable: Explicit termination method 'close' not called

code for Server.java is as below

`

public class Server extends Activity {

     static StringBuilder stringBuilder = new StringBuilder();
public Server(){
    try {
        JSONObject obj = new JSONObject(loadJSONFromAsset());
        JSONArray project = obj.getJSONArray("project");

        for (int i = 0; i < project.length(); i++) {
            JSONObject ss = project.getJSONObject(i);
            stringBuilder.append(ss.getString("title") + "\n");
            JSONArray post = ss.getJSONArray("posts");

            for(int j = 0; j < post.length();j++){
                JSONObject posts = post.getJSONObject(j);
                stringBuilder.append(posts.getString("id") +"\n");
                JSONArray tag = posts.getJSONArray("tags");

                for(int k = 0; k < tag.length();k++){
                    stringBuilder.append(tag.getString(k) +"\n");
                }
            }
        }
    }
    catch (JSONException e) {
        stringBuilder.append("error");
        e.printStackTrace();
    }

}

public String getString(){

    return stringBuilder.toString();
}


public String loadJSONFromAsset() {
    String json = null;
    try {

        InputStream is = getAssets().open("cat.json");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        json = new String(buffer, "UTF-8");

    } catch (IOException ex) {
        ex.printStackTrace();
        return null;
    }
    return json;
}}

and here is my MainActivity.java

public class MainActivity extends Activity  {


TextView jsonDataTextView;


@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    jsonDataTextView = (TextView) findViewById(R.id.textView);

    Server s = new Server();
    jsonDataTextView.setText(s.stringBuilder.toString());} }

Is there any solution?

karan
  • 8,637
  • 3
  • 41
  • 78
  • 2
    I haven't tested it myself, but I guess you are closing an I/O stream in a `try` block. If an exception occurs, then the stream is not closed. You should try to add a `finally` block and inside it, write `is.close();`. – MC Emperor Jan 22 '15 at 14:13
  • 2
    Why does your Server class extend Activity ? – Gorcyn Jan 22 '15 at 14:13
  • getAssets wants it @Gorcyn – Tunahan Kunt Jan 22 '15 at 14:26
  • @TunahanKunt Just saw that while answering. But why not just pass the MainActivity as a parameter and save it as a `Context` property? – Gorcyn Jan 22 '15 at 14:50
  • Actually I'm a beginner in Android dev. so i cannot understand what you mean. Also interestingly when I restart to android studio it stops the give previous error but now it gives a nullpointerexception at `is = getAssets().open("cat.json");` However I already run my codes at another project in the `MainActivity` and it works well. Also i try to get the string with getter but it also not works. – Tunahan Kunt Jan 22 '15 at 14:58

1 Answers1

2

The InputStream may not be closed in the try block of your loadJSONFromAsset method, and it should.

public String loadJSONFromAsset() {
    String json = null;
    InputStream is = null;
    try {
        is = getAssets().open("cat.json");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        json = new String(buffer, "UTF-8");
    }
    catch (IOException ex) {
        ex.printStackTrace();
    }
    finally {
        if (is != null) {
            try {
                is.close();
            }
            catch (IOException ex) {
                // Do you want to handle this exception?
            }
        }
    }
    return json;
}

Note: Something bothers me in your Server constructor, in the catch block you try to append "error" to your StringBuilder. Do you know that here, the StringBuilder may not be empty. Indeed in the try block, one (or more) attempt(s) to append some string to it may work before something goes wrong at some point.

Note 2: Server as a non Activity

public class Server {

    private Context mContext;
    public Server(Context context) {
        mContext = context;
        ...
    }
    ...
    public String loadJSONFromAsset() {
        ...
            mContext.getAssets().open("cat.json");
    }
}

then in your MainActivity

Server s = new Server(this);
Gorcyn
  • 2,807
  • 1
  • 20
  • 22
  • When I try to put is.close(); in finally it gave an error and public String loadJSONFromAsset() needs a throws IOException . When did it now JSONObject obj = new JSONObject(loadJSONFromAsset()); gave an error and i need a catch (IOException e) { e.printStackTrace(); } after that when I run it keeps continue to gave an error. – Tunahan Kunt Jan 22 '15 at 14:39
  • Edited. It is ugly, I know... but you'll see a lot of exception handling in `finally` blocks when you'll dive into IO streams. Check this out : http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/1.4/org/apache/commons/io/IOUtils.java#IOUtils.closeQuietly%28java.io.InputStream%29 – Gorcyn Jan 22 '15 at 15:01
  • Yesterday I was working on it 8hours. Thank you Gorcyn now it works. However i cannot understand what context do. Can u explain briefly. – Tunahan Kunt Jan 23 '15 at 07:01
  • I don't have enough space in the comment box to do better than this: http://stackoverflow.com/questions/3572463/what-is-context-in-android – Gorcyn Jan 23 '15 at 08:58