kev kev - 10 days ago 5
Android Question

Crashes when sending sms (NullPointerException) What should I do?

I have an app that send sms to other android or non-android phones. You can select or input your contacts. But the problem is, that it keeps crashing when I get to the part where it sends SMS.

btnRecipient.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
startActivityForResult(intent, CONTACT_PICKER_RESULT);
}
});
}

@Override
public void onActivityResult(int reqCode, int resultCode, Intent data) {
super.onActivityResult(reqCode, resultCode, data);

switch (reqCode) {
case (CONTACT_PICKER_RESULT):
if (resultCode == Activity.RESULT_OK) {
Uri contactData = data.getData();
Cursor c = managedQuery(contactData, null, null, null, null);
if (c.moveToFirst()) {
String name = c.getString(c.getColumnIndexOrThrow(Contacts.DISPLAY_NAME));
editTextRecipient.setText(name);
}
}
break;
}

btnSend.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String phoneNo = editTextRecipient.getText().toString();
String message = editTextNewMessage.getText().toString();

if (phoneNo.length()>0 && message.length()>0)
sendSMS(phoneNo, message);
else
Toast.makeText(getBaseContext(),
"Please enter both phone number and message.",
Toast.LENGTH_SHORT).show();
}
});
}

private void sendSMS(String phoneNo, String message)
{
String SENT = "SMS_SENT";
String DELIVERED = "SMS_DELIVERED";

PendingIntent sentPI = PendingIntent.getBroadcast(this, 0,
new Intent(SENT), 0);

PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0,
new Intent(DELIVERED), 0);

registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), "SMS sent",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
Toast.makeText(getBaseContext(), "Generic failure",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NO_SERVICE:
Toast.makeText(getBaseContext(), "No service",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_NULL_PDU:
Toast.makeText(getBaseContext(), "Null PDU",
Toast.LENGTH_SHORT).show();
break;
case SmsManager.RESULT_ERROR_RADIO_OFF:
Toast.makeText(getBaseContext(), "Radio off",
Toast.LENGTH_SHORT).show();
break;
}
}
}, new IntentFilter(SENT));

registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
switch (getResultCode())
{
case Activity.RESULT_OK:
Toast.makeText(getBaseContext(), "SMS delivered",
Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
Toast.makeText(getBaseContext(), "SMS not delivered",
Toast.LENGTH_SHORT).show();
break;
}
}
}, new IntentFilter(DELIVERED));

SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNo, null, message, sentPI, deliveredPI);
}
}


and heres the LogCat:

10-26 12:23:29.633: E/AndroidRuntime(11986): FATAL EXCEPTION: main
10-26 12:23:29.633: E/AndroidRuntime(11986): java.lang.NullPointerException
10-26 12:23:29.633: E/AndroidRuntime(11986): at com.android.internal.telephony.gsm.SmsMessage.getSubmitPduHead(SmsMessage.java:663)
10-26 12:23:29.633: E/AndroidRuntime(11986): at com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(SmsMessage.java:339)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.telephony.SmsMessage.getSubmitPdu(SmsMessage.java:613)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.telephony.SmsManager.sendTextMessage(SmsManager.java:228)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.telephony.SmsManager.sendTextMessage(SmsManager.java:107)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.telephony.gsm.SmsManager.sendTextMessage(SmsManager.java:79)
10-26 12:23:29.633: E/AndroidRuntime(11986): at com.example.KAHTextApp.KAHTextApp.sendSMS(KAHTextApp.java:136)
10-26 12:23:29.633: E/AndroidRuntime(11986): at com.example.KAHTextApp.KAHTextApp.access$0(KAHTextApp.java:78)
10-26 12:23:29.633: E/AndroidRuntime(11986): at com.example.KAHTextApp.KAHTextApp$2.onClick(KAHTextApp.java:69)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.view.View.performClick(View.java:2532)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.view.View$PerformClick.run(View.java:9293)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.os.Handler.handleCallback(Handler.java:587)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.os.Handler.dispatchMessage(Handler.java:92)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.os.Looper.loop(Looper.java:143)
10-26 12:23:29.633: E/AndroidRuntime(11986): at android.app.ActivityThread.main(ActivityThread.java:4277)
10-26 12:23:29.633: E/AndroidRuntime(11986): at java.lang.reflect.Method.invokeNative(Native Method)
10-26 12:23:29.633: E/AndroidRuntime(11986): at java.lang.reflect.Method.invoke(Method.java:507)
10-26 12:23:29.633: E/AndroidRuntime(11986): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-26 12:23:29.633: E/AndroidRuntime(11986): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-26 12:23:29.633: E/AndroidRuntime(11986): at dalvik.system.NativeStart.main(Native Method)


what is the problem here? and how can to resolve this?

Answer

This looks very similar to the issue described here.

If you replace the method call sendTextMessage with sendMultipartTextMessage does it work? Can you log how long your variable message is at that point?

EDIT:

So it seems that if you try to send a single sms message that exceeds 160 characters, you get a null pointer exception. To avoid this, split the message into multiple parts. Here is some test code I wrote:

public void textSingle(View view) {
    sendSMS("XXXXXXXXXX", "Test", false);
}

public void textSingleLong(View view) {
    sendSMS("XXXXXXXXXX",
            "TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest",
            false);
}

public void textMulti(View view) {
    sendSMS("XXXXXXXXXX",
            "TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest",
            true);
}

private void sendSMS(String phoneNo, String message, boolean split) {
    ...

    SmsManager sms = SmsManager.getDefault();
    if (!split) {
        Log.d("SMSTest", "Sending single message: " + message);
        sms.sendTextMessage(phoneNo, null, message, sentPI, deliveredPI);
    } else {
        Log.d("SMSTest", "Sending '" + message + "' in multiple parts.");
        ArrayList<String> parts = sms.divideMessage(message);
        Log.d("SMSTest", parts.size() + " parts:");
        for (String string : parts) {
            Log.d("SMSTest", string);
        }
        ArrayList<PendingIntent> sentList = new ArrayList<PendingIntent>();
        ArrayList<PendingIntent> deliveredList = new ArrayList<PendingIntent>();
        for (int i = 0; i < parts.size(); i++) {
            sentList.add(sentPI);
            deliveredList.add(deliveredPI);
        }
        sms.sendMultipartTextMessage(phoneNo, null, parts, sentList,
                deliveredList);
    }
}

I hooked up buttons to each of these methods, and they work correctly for me, with a NullPointerException when I try to send a single long message. I don't really know why you get such an unhelpful message when you do that, but that seems to be how it is.