1

I have a WakefulBroadcastReceiver in my Android application, which successfully receives incoming SMS to the device. Following this, what I am attempting to do, is to submit a request to my web server, using the Google Volley library. The issue, is that Volley makes this web request asynchronously. As a result, the "onReceive" method code in the BroadcastReceiver is completed before the asynchronous web request is completed. I understand that this is an issue when using the BroadcastReceiver with asynchronous requests, but I'm making that request through a service, (instead of directly in the BroadcastReceiver), so I don't understand why this is happening.

I receive the below NULLPOINTEREXCEPTION, which I'm assuming is because the context of the BroadcastReceiver has already been destroyed before the request is completed:


11-04 19:13:43.465  32385-32441/com.niiche.pinch E/Volley﹕ [5542] NetworkDispatcher.run: Unhandled exception java.lang.NullPointerException
java.lang.NullPointerException
        at libcore.net.UriCodec.encode(UriCodec.java:132)
        at java.net.URLEncoder.encode(URLEncoder.java:57)
        at com.android.volley.Request.encodeParameters(Request.java:456)
        at com.android.volley.Request.getBody(Request.java:442)
        at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:236)
        at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:210)
        at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:106)
        at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
        at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:110)

Below is the code for the WakefulBroadcastReceiver (SmsReceiver):

public void onReceive(Context context, Intent intent) {
    //retrieve the SMS PDUs, from the intent extras
    Bundle pdusBundle = intent.getExtras();
    Object[] pdus = (Object[])pdusBundle.get("pdus");

    //create sms message object from the PDU
    SmsMessage message = SmsMessage.createFromPdu((byte[])pdus[0]);

    Intent service = new Intent(context, SmsIntentService.class);
    service.putExtra(SmsIntentService.EXTRA_SMS_MESSAGE, message.getMessageBody());

    //start the service, keeping the device awake while it is launching
    startWakefulService(context, service);
    setResultCode(Activity.RESULT_OK);
}//End method

Below is the code for the IntentService (SmsIntentService):

protected void onHandleIntent(Intent intent) {
    if (intent != null) {
        Bundle extras = intent.getExtras();

        if(!extras.isEmpty()){ // has the effect of unparcelling the bundle
            String smsMessage = extras.getString(EXTRA_SMS_MESSAGE);

            submitVolleyServerRequestAsync(smsMessage);
        }//End if
    }//End if

    // Release the wake lock provided by the WakefulBroadcastReceiver
    SmsReceiver.completeWakefulIntent(intent);
}//End method

Any assistance that can be provided here is greatly appreciated. Thanks in advance!

CP17
  • 481
  • 4
  • 6
  • 3
    I do not know Volley, but you need to do your HTTP call **synchronously** from the background thread provided by `IntentService`. Otherwise, the service will complete and your `WakeLock` will be released before your HTTP call is done. – CommonsWare Nov 05 '14 at 00:30

1 Answers1

0

Thanks for the pointers @Aun and @CommonsWare. My issue was actually with how I was creating the Volley request. Volley apparently does not handle input parameter values, (i.e. HTTP Get/Post Params), being passed as null. I had to check therefore whether each param was null, before adding it to the param map for the request:

Map<String, String> mapPostArgs = new HashMap<String, String>();
if(name != null) {
        mapPostArgs.put("name", name);
    }

GsonRequest<APIResponse<Integer>> request = new GsonRequest<APIResponse<Integer>>(
            uri,
            new TypeToken<APIResponse<Integer>>(){}.getType(),
            getRequestHeaders(),
            mapPostArgs,
            listener,
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    handleError(error);
                }//End method
            });

Thanks alot for the guidance!

CP17
  • 481
  • 4
  • 6