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 arrayW/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.