I need to have a verified phone number for my users, but after researching, there doesn't appear to be a reliable way to get the phone# from the device. One suggestion I've seen a couple of times is to send a text message, then catch it in a Broadcast receiver and parse the phone number from the inco ming intent. I have seen this question: I could not get data from Intent after broadcast received, and this one, but they do not address my problem.
Currently, I have the receiver working, but I can't get any data about the SMS message, which presumably is accessible through the intent.
Here's the code that fires when the user presses the SEND button:
btnSend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
String SENT = "sent";
String DELIVERED = "delivered";
Intent sentIntent = new Intent(SENT);
/*Create Pending Intents*/
PendingIntent sentPI = PendingIntent.getBroadcast(
getApplicationContext(), 0, sentIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
/* Register for SMS send action */
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
try {
---> **SmsMessage[] smsMessage = Telephony.Sms.Intents.getMessagesFromIntent(intent);**
String messageBody = smsMessage[0].getMessageBody();
} catch (Exception e) {
e.printStackTrace();
}
int resultcode = getResultCode();
Log.d(" RESULT=", Integer.toString(resultcode));
}
}, new IntentFilter(SENT));
SmsManager smsManager = SmsManager.getDefault();
if ((ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.SEND_SMS) !=
PackageManager.PERMISSION_GRANTED) ||
(ContextCompat.checkSelfPermission(getApplicationContext(),
Manifest.permission.RECEIVE_SMS) !=
PackageManager.PERMISSION_GRANTED)){
ActivityCompat.requestPermissions(SMSActivity.this,
new String[] {
Manifest.permission.SEND_SMS, Manifest.permission.RECEIVE_SMS
}, 1);
}
smsManager.sendTextMessage(phoneNo.getText().toString(), null,
msg.getText().toString(), sentPI, null);
} catch (Exception ex) {
Toast.makeText(getApplicationContext(),
ex.getMessage(), Toast.LENGTH_LONG)
.show();
ex.printStackTrace();
}
}
});
When the call to getMessagesFromIntent() is made (line in bold), an exception is thrown as listed here at "onReceive(SMSActivity.java:60):" The Intent is not null, so it appears that "null array" is internal to getMessagesFromIntent.
W/System.err: java.lang.NullPointerException: Attempt to get length of null array
W/System.err: at android.provider.Telephony$Sms$Intents.getMessagesFromIntent(Telephony.java:1345)
W/System.err: at com.jdot.jsontest.SMSActivity$1$1.onReceive(SMSActivity.java:60)
W/System.err: at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:993)
W/System.err: at android.os.Handler.handleCallback(Handler.java:739)
W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err: at android.os.Looper.loop(Looper.java:158)
W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7224)
W/System.err: at java.lang.reflect.Method.invoke(Native Method)
W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
I assume I may have a permissions related issue. I've added this to my manifest:
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
I've also seen this manifest addition a few times, but I don't know how to name MyBroadcastListener, since it it isn't a class like the examples I've seen.
<receiver android:name="MyBroadcastListener">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Finally, I tried the following block of code (as an alternative) in the the body of onReceive(). Though intent.getExtras() returns a Bundle, the call bundle.get("pdus") returns null so everything else fails.
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null) {
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
}
//---display the new SMS message---
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
My questions are:
- Do I need the Receiver/Intent-filter block in my manifest, and if so, how do I name the listener in the first line?
- What is the likely reason I can not receive a copy of the incoming message in onReceive(), and what should I do to correct it?
- Do I need to send a message and "catch it" in onReceive() in order to reliably get the devices phone number, or can I request permission to read SMS from the user, and just read the first message to get the incoming phone number?
Please note that I have read through all similar questions and have not found an answer.