0

I have noticed a problem on some devices where a crash occurs in an AsyncTask. It works without issue on my tablet and smartphone, but my friend had an issue on his device.

Here is an example of the body of one of my AsyncTasks:

protected String doInBackground(String... params) {
    String result = "";
    HttpClient httpclient = GlobalValues.getHttpClient();
    HttpPost httppost = new HttpPost(String.format(GlobalValues.getServiceUrl() + "%s", params[0]));

    try {
        HttpResponse response = httpclient.execute(httppost, GlobalValues.getLocalContext());
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();
            result = GlobalValues.convertStreamToString(instream);
            Log.i(params[0], params[0] + ": " + result);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return result;
}

LOG:

FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
...
Caused by: java.lang.NullPointerException
...

The error occurs in the line:

HttpResponse response = httpclient.execute(httppost, GlobalValues.getLocalContext());

httppost contains the server url, which is set inside the method, with help from GlobalValues.getServiceUrl() and params[]. The session cookie is stored in an HttpContext, which is retrieved from GlobalValues.getLocalContext(), set when the application is first launched and shared by all of my AsyncTasks. I don't understand where a NullPointerException might be thrown.

I've looked at other questions/answers, but haven't found a solution.

  • The LocalContext is shared
  • The InputStream is closed in the HttpResponse response = httpclient.execute(httppost, GlobalValues.getLocalContext()).

Has anyone encountered this before &/ know what might be the problem?

EDIT:

Launcher Activity -

private DefaultHttpClient httpclient;
private HttpContext localContext;

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

    httpclient = new DefaultHttpClient();
    localContext = new BasicHttpContext();

    CookieStore cookieStore = new BasicCookieStore();
    localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

    GlobalValues.setHttpClient(httpclient);
    GlobalValues.setLocalContext(localContext);

GlobalValues -

protected static DefaultHttpClient httpclient;
protected static HttpContext localContext;

public static final DefaultHttpClient getHttpClient() {
    return httpclient;
}

public static final HttpContext getLocalContext() {
    return localContext;
}

public static final void setHttpClient(DefaultHttpClient httpclient) {
    GlobalValues.httpclient = httpclient;
}

public static final void setLocalContext(HttpContext localContext) {
    GlobalValues.localContext = localContext;
}

UPDATE: I've discovered that the issue only happens when someone tries to restore the application. I've stopped the application from crashing by adding "if(null) re-instantiate variable" in GlobalValues.getHttpClient() and GlobalValues.getLocalContext(). However, the session cookie stored in LocalContext is lost. Any ideas how to re-instantiate the values or the variables without loss of data?

lgdroid57
  • 699
  • 14
  • 29
  • The `NullPointerException` in that line means that `httpclient` has been `null` - which from your code points to `GlobalValues.getHttpClient()`. Can you give us the source of that, too? – dst Aug 30 '13 at 21:33
  • I forgot about HttpClient - I've added the code segments as you requested – lgdroid57 Aug 30 '13 at 21:55

2 Answers2

1

The NullPointerException in that line means that httpclient has been null - which from your code points to GlobalValues.getHttpClient(), which reads from a static field.

You instanciate your static field in the onCreate method of another activity. This will not work, as android might kill your app and re-create only the visible activity. In that case, your initialization code is not called.


Quick Fix: Change your GlobalValues class to do initialization work:

protected static DefaultHttpClient httpclient = new DefaultHttpClient();

Your GlobalValues class seems a bit like you tried a "Singleton Pattern", see an answer about singleton patterns in general, and move all your construction code into the GlobalValues constructor. That way all your construction code is called before your static features are used.

Community
  • 1
  • 1
dst
  • 3,307
  • 1
  • 20
  • 27
  • Thanks for your suggestion - I'm going to give it a try. – lgdroid57 Aug 30 '13 at 22:13
  • @lgdroid57 what issues? Logcat? – dst Aug 31 '13 at 04:21
  • Same issue - java.lang.NullPointerException at 'HttpResponse response = httpclient.execute(httppost, GlobalValues.getLocalContext());' – lgdroid57 Aug 31 '13 at 04:24
  • @lgdroid57 maybe try cleaning and rebuilding? Also, log `httpclient` in the line before, so we know for sure it really is `null` (and thus causing the exception), maybe log `GlobalValues.getLocalContext()`, too (in case the `NullPointerException` is thrown somewhere in the android code and logcat somehow doesn't display it in its stacktrace). – dst Aug 31 '13 at 04:29
  • I can't see my friends log at the moment, but I did get a useful tidbit of information from him - it sounds like the app is only crashing when he tries to resume the application. I've considered adding a line that says if(HttpClient/LocalContext == null), then re-configure HttpClient/LocalContext, but I presume setting a new context will lose the session cookie, am I correct? – lgdroid57 Aug 31 '13 at 17:44
  • It seems like you use your singleton (`GlobalValue`) to store the session cookie currently? This is a bad idea, as Android will wipe all types of singletons from time to time (often when resuming the application). You should store the Session cookie in a persistent way, if you need to maintain one ([`SharedPreferences`](http://developer.android.com/guide/topics/data/data-storage.html#pref) or something). Your singleton should then use the stored session cookie to re-initialize itself. – dst Sep 01 '13 at 10:44
  • Thank you! I solved the problem by defining my own Activity class that extends Activity, overriding onCreate to check the client and context. If they are null, then they get re-instantiated from the shared preferences. – lgdroid57 Sep 02 '13 at 14:55
0

IS it possible that your GlobalValues is getting stepped on by another async process?

Also, not all Androids are the same. Your friend may have a phone from a manufacturer that implements AsyncTask differently enough to cause issues

Martin
  • 4,711
  • 4
  • 29
  • 37