3

I am making an app that uses the internet to retrieve information. I get an NetworkOnMainThreadException as I tried to run it on 3.0 and above and have therefore tried to set it up using AsyncTask, but it still gives the exception and I don't know what is wrong. Oddly enough I read on this thread Android NetworkOnMainThreadException inside of AsyncTask that if you just removes the android:targetSdkVersion="10" statement from the manifest file it will be able to run. This works but I don't find it as the right solution to solve the problem this way.

So if anyone can tell me what I am doing wrong with the AsyncTask I will really appreciate it. Also if there is anybody that knows why removing the statement in the manifest makes it work, I am really interested in that also.

My code looks like this: EDIT: UPDATED CODE.

public class MainActivity extends Activity {

static ArrayList<Tumblr> tumblrs;
ListView listView;
TextView footer;
int offset = 0;
ProgressDialog pDialog;
View v;
String responseBody = null;
HttpResponse r;
HttpEntity e;
String searchUrl;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    final ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo();
    if (activeNetwork != null && activeNetwork.isConnected()) {

        setContentView(R.layout.main);

        try {
            tumblrs = getTumblrs();
            listView = (ListView) findViewById(R.id.list);
            View v = getLayoutInflater().inflate(R.layout.footer_layout,
                    null);
            footer = (TextView) v.findViewById(R.id.tvFoot);
            listView.addFooterView(v);
            listView.setAdapter(new UserItemAdapter(this, R.layout.listitem));

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        new GetChicks().execute();
        footer.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                new loadMoreListView().execute();
            }
        });

    } else {
        setContentView(R.layout.nonet);

    }

}

public class UserItemAdapter extends ArrayAdapter<Tumblr> {

    public UserItemAdapter(Context context, int imageViewResourceId) {
        super(context, imageViewResourceId, tumblrs);

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        if (v == null) {

            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = vi.inflate(R.layout.listitem, null);

        }

        Tumblr tumblr = tumblrs.get(position);
        if (tumblr != null) {

            ImageView image = (ImageView) v.findViewById(R.id.avatar);

            if (image != null) {
                image.setImageBitmap(getBitmap(tumblr.image_url));

            }
        }

        return v;
    }
}

public Bitmap getBitmap(String bitmapUrl) {
    try {
        URL url = new URL(bitmapUrl);
        return BitmapFactory.decodeStream(url.openConnection()
                .getInputStream());
    } catch (Exception ex) {
        return null;
    }
}

public ArrayList<Tumblr> getTumblrs() throws ClientProtocolException,
        IOException, JSONException {
    searchUrl = "http://api.tumblr.com/v2/blog/factsandchicks.com/posts?api_key=rTZsymOWtMudbb5tql2U20qQ5ooYLPYVNnL3COPpO2qBHDxJUu&limit=2&offset=0";

    ArrayList<Tumblr> tumblrs = new ArrayList<Tumblr>();
    return tumblrs;
}

private class GetChicks extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... unused) {
        // TODO Auto-generated method stub


                HttpClient client = new DefaultHttpClient();
                HttpGet get = new HttpGet(searchUrl);

                HttpResponse r = null;
                try {
                    r = client.execute(get);
                    int status = r.getStatusLine().getStatusCode();
                    if (status == 200) {
                        e = r.getEntity();
                        responseBody = EntityUtils.toString(e);
                    }
                } catch (ClientProtocolException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

                JSONObject jsonObject;
                try {
                    jsonObject = new JSONObject(responseBody);

                    JSONArray posts = jsonObject.getJSONObject("response")
                            .getJSONArray("posts");

                    for (int i = 0; i < posts.length(); i++) {
                        JSONArray photos = posts.getJSONObject(i)
                                .getJSONArray("photos");
                        for (int j = 0; j < photos.length(); j++) {
                            JSONObject photo = photos.getJSONObject(j);
                            String url = photo.getJSONArray("alt_sizes")
                                    .getJSONObject(0).getString("url");

                            Tumblr tumblr = new Tumblr(url);
                            tumblrs.add(tumblr);

                        }
                    }

                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



        return null;
    }

}

public class Tumblr {

    public String image_url;

    public Tumblr(String url) {

        this.image_url = url;

    }
}

private class loadMoreListView extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        // Showing progress dialog before sending http request
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage("More chicks coming up..");
        pDialog.setIndeterminate(true);
        pDialog.setCancelable(false);
        pDialog.show();
    }

    @Override
    protected Void doInBackground(Void... unused) {
        // TODO Auto-generated method stub

                // increment current page
                offset += 2;

                // Next page request
                tumblrs.clear();
                String searchUrl = "http://api.tumblr.com/v2/blog/factsandchicks.com/posts?api_key=rTZsymOWtMudbb5tql2U20qQ5ooYLPYVNnL3COPpO2qBHDxJUu&limit=2&offset="
                        + offset;

                HttpClient client = new DefaultHttpClient();
                HttpGet get = new HttpGet(searchUrl);

                HttpResponse r = null;
                try {
                    r = client.execute(get);
                    int status = r.getStatusLine().getStatusCode();
                    if (status == 200) {
                        HttpEntity e = r.getEntity();
                        responseBody = EntityUtils.toString(e);
                    }
                } catch (ClientProtocolException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }

                JSONObject jsonObject;
                try {
                    jsonObject = new JSONObject(responseBody);

                    JSONArray posts = jsonObject.getJSONObject("response")
                            .getJSONArray("posts");

                    for (int i = 0; i < posts.length(); i++) {
                        JSONArray photos = posts.getJSONObject(i)
                                .getJSONArray("photos");
                        for (int j = 0; j < photos.length(); j++) {
                            JSONObject photo = photos.getJSONObject(j);
                            String url = photo.getJSONArray("alt_sizes")
                                    .getJSONObject(0).getString("url");

                            Tumblr tumblr = new Tumblr(url);
                            tumblrs.add(tumblr);

                        }
                    }

                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                // Setting new scroll position
                listView.setSelectionFromTop(0, 0);



        return null;
    }

    protected void onPostExecute(Void unused) {
        pDialog.dismiss();

    }

}

@Override
public boolean onCreateOptionsMenu(android.view.Menu menu) {
    // TODO Auto-generated method stub
    super.onCreateOptionsMenu(menu);
    MenuInflater blowUp = getMenuInflater();
    blowUp.inflate(R.menu.cool_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // TODO Auto-generated method stub
    switch (item.getItemId()) {
    case R.id.aboutUs:
        Intent i = new Intent("com.example.example.ABOUT");
        startActivity(i);

        break;
    case R.id.refresh:
        Intent f = new Intent(MainActivity.this, MainActivity.class);
        startActivity(f);
        finish();
        break;
    case R.id.exit:
        finish();
        break;
    }
    return false;
}

}

The log looks like this:

 10-07 10:27:56.163: E/AndroidRuntime(923): FATAL EXCEPTION: AsyncTask #2
 10-07 10:27:56.163: E/AndroidRuntime(923): java.lang.RuntimeException: An error  occured while executing doInBackground()
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.os.AsyncTask$3.done(AsyncTask.java:278)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at  java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at  java.util.concurrent.FutureTask.run(FutureTask.java:137)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:208)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at  java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at java.lang.Thread.run(Thread.java:856)
 10-07 10:27:56.163: E/AndroidRuntime(923): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that  created a view hierarchy can touch its views.
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:3939)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:701)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.view.View.requestLayout(View.java:12555)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.view.View.requestLayout(View.java:12555)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.view.View.requestLayout(View.java:12555)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.view.View.requestLayout(View.java:12555)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.view.View.requestLayout(View.java:12555)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.widget.AbsListView.requestLayout(AbsListView.java:1690)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.widget.ListView.setSelectionFromTop(ListView.java:1928)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at com.fansheroid.facts.chicks.MainActivity$loadMoreListView.doInBackground(MainActivity.java:291)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at com.fansheroid.facts.chicks.MainActivity$loadMoreListView.doInBackground(MainActivity.java:1)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at android.os.AsyncTask$2.call(AsyncTask.java:264)
 10-07 10:27:56.163: E/AndroidRuntime(923):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
 10-07 10:27:56.163: E/AndroidRuntime(923):     ... 5 more
Community
  • 1
  • 1
STHOH
  • 261
  • 1
  • 12
  • 1
    It's difficult to `GetChicks` without the proper threads :) – Nate Oct 07 '12 at 10:02
  • Sorry, Fansher. It was a joke, that probably doesn't translate if English isn't your first language. The little ":)" at the end of the sentence means that someone is trying to be funny. It doesn't mean they've succeeded, though. – Nate Oct 07 '12 at 21:34
  • Haha, I got it now. At the moment i was too busy trying to find my mistake, so my humor was turned off ;) – STHOH Oct 08 '12 at 12:39
  • possible duplicate of [Android XML Parser Exception Caught](http://stackoverflow.com/questions/12742650/android-xml-parser-exception-caught) – rene Oct 08 '12 at 13:52
  • How can people with the same problem see what was the error if you update your **question** with the **answer** ??! – Mickäel A. Feb 08 '13 at 14:52

1 Answers1

5

You are calling runOnUiThread() method while AsyncTask used to run things in another thread to avoid intercepting the UI thread for long processes in doInBackground() method. I believe removing runOnUiThread() would do the job.

Hesham Saeed
  • 5,358
  • 7
  • 37
  • 57
  • Do i also have to remove the `public void run() {`or does this line have to stay? – STHOH Oct 07 '12 at 09:58
  • Yes you will have to remove it also, and don't forget the closing brackets. – Hesham Saeed Oct 07 '12 at 09:59
  • When i have removed thees two lines the app crashes whit the exception: `10-07 09:54:47.913: E/AndroidRuntime(723): Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. ` – STHOH Oct 07 '12 at 10:10
  • This log appears for which line exactly? – Hesham Saeed Oct 07 '12 at 10:17
  • I have updated the code in the question and added the log. When the app is launched it doesn't execute `GetChicks`, and the error occurs when i try to execute the `loadMoreListView`. – STHOH Oct 07 '12 at 10:34
  • `listView.setSelectionFromTop(0, 0);` put this at `onPostExecute()` method. Because you are dealing with `ListView` which is UI element in another thread. – Hesham Saeed Oct 07 '12 at 11:29
  • That fixed the error. But suddenly `GetChicks` isn't getting executed when the app is launched? – STHOH Oct 07 '12 at 11:58
  • How do you know it is not executed? there no `onPostExecute()` in that `AsyncTask` which means there is no output. (You didn't add dialog as loading for it too). – Hesham Saeed Oct 07 '12 at 12:07
  • Okay, now it works for version 2.2, but when i run it on 4.0 it fails to set the images in the listview and it only shows an empty list. Both from the `GetChicks`and from the `loadMoreListView`. – STHOH Oct 07 '12 at 12:39
  • Yes, this is another issue, compatibility, I prefer putting it in different question and saying that this code works for 2.2 but not 4.0. I think the problem is from how you are getting thing using HTTP maybe some of the functions you are using are deprecated and removed in 4.0 and so on, many aspects. – Hesham Saeed Oct 07 '12 at 12:45