1

I'm trying to develop a widget that updates itself every minute by a json resource, my problem is that when i try to launch it on jellybean it crashes, while with gingerbread works.

I saw here that i must move all internet connection to the main thread, right? At the moment i've a class called HttpRequest:

public class HttpRequest {    
    private String url;

    public HttpRequest(String url)
    {       
        this.url = url;
    }

    public String GetContent() throws ClientProtocolException, IOException
    {
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(url);
        HttpResponse response = client.execute(request);

        String html = "";
        InputStream in = response.getEntity().getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        StringBuilder str = new StringBuilder();
        String line = null;
        while((line = reader.readLine()) != null)
        {
            str.append(line);
        }
        in.close();
        html = str.toString();
        return html;
    }
}

Every minute is called updateAppWidget() that is a method of WidgetProvider class. Inside updateAppWidget() there is:

HttpRequest r = new HttpRequest("http://www.hwlogos.com/test.json");
remoteViews.setTextViewText(R.id.ip, r.GetContent());

Can you tell me how solve it steep by steep? thanks

Community
  • 1
  • 1
filippo
  • 839
  • 2
  • 13
  • 25
  • 1
    No, you need to move OFF the main thread. – Codo Oct 13 '12 at 14:38
  • I've written about this exception and why it is thrown in Android 3.0 and above. Check out this [**post**](http://www.androiddesignpatterns.com/2012/06/app-force-close-honeycomb-ics.html) for more information. – Alex Lockwood Oct 13 '12 at 14:54

3 Answers3

2

As proposed, AsyncTask is the way to go. Change your code like this:

private class HttpRequestTask extends AsyncTask<Context, Void, String> {

    private Context context;

    protected String doInBackground(Context... contextParam) {
        context = contextParam[0];
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet("http://www.hwlogos.com/test.json");
        HttpResponse response = client.execute(request);

        String html = "";
        InputStream in = response.getEntity().getContent();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        StringBuilder str = new StringBuilder();
        String line = null;
        while((line = reader.readLine()) != null)
        {
            str.append(line);
        }
        in.close();
        html = str.toString();
        return html;
     }

     protected void onPostExecute(String html) {
         AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
         RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
         remoteViews.setTextViewText(R.id.ip, html);
         appWidgetManager.updateAppWidget(new ComponentName(context, WidgetProvider .class), remoteViews);
     }
}

Note the code in onPostExecute that does the extra work required to update an app widget.

Then start the asynchronous task like this:

 new HttpRequestTask().execute(context);
Codo
  • 75,595
  • 17
  • 168
  • 206
  • The easiest solution is to make *HttpRequestTask* class an inner class of the *WidgetProvider* class. Another solution is to add *remoteView* as an instance variable of *HttpRequestTask* and set it via a *setRemoteView* method before you call *execute*. – Codo Oct 13 '12 at 15:30
  • I tried in this way: http://pastebin.com/e2wDyBPW and Log.i("ERROR", "RECEIVED ID: " + remoteViews.toString()); every time is called prints a different id... I tried to give the remoteViews object through the constructor of Downloader class and there is the same problem. – filippo Oct 13 '12 at 17:05
  • You are creating a new *remoteViews* instance every time you call *Downloader*. Is this really what you want? Shouldn't you create the *remoteViews* instance once and call the *Downlader* many times? – Codo Oct 13 '12 at 17:50
  • No, should be 1 remoteView for each widget... What is wrong whit this code? I get the id when i need it... – filippo Oct 13 '12 at 17:57
  • I've changed my code and added the required code to update the app widget from the async task. – Codo Oct 14 '12 at 09:25
  • thanks, it works! p.s. AppWidgetManager.getWidget(context); should be getIstance – filippo Oct 14 '12 at 15:25
  • now there is another problem... when i add 2 or more widget, when onPostExecute( is called, all widget are updated with the same html! – filippo Oct 14 '12 at 15:45
  • You better start a new question for this problem. There you can post the relevant code. – Codo Oct 14 '12 at 17:27
0

You'll need to move your network connections off of the main thread and onto a background thread. Later versions of Android will crash the app if you use the network on the main thread.

The most straightforward solution will be to use an AsyncTask, which will do some work on a separate thread (doing your network fetches) and then enable you to do subsequent work on the main thread when it's done.

There's an example in this post, and many others can be found on SO or Google.

Community
  • 1
  • 1
acj
  • 4,821
  • 4
  • 34
  • 49
0

Call your function from bellow code [ from thread ]

Step 1 :

Instead of this two lines

HttpRequest r = new HttpRequest("http://www.hwlogos.com/test.json");
remoteViews.setTextViewText(R.id.ip, r.GetContent());

Call bellow Lines of code,

    Thread thread = new Thread()
    {
      @Override
      public void run() {
          try {

            // CALL YOUR FUNCTION FROM HERE
            HttpRequest r = new HttpRequest("http://www.hwlogos.com/test.json");            
            remoteViews.setTextViewText(R.id.ip, r.GetContent());

          } catch (Exception e) {
              e.printStackTrace();
          }
      }
    };

thread.start();

Step 2:

if above function do not work for you then

use this Reference Link.

i hope this will work for you. Thanks.

VISHAL VIRADIA
  • 1,388
  • 1
  • 15
  • 34