[英]How to get sms data in a Broadcast receiver
我需要为我的用户提供一个经过验证的电话号码,但是经过研究后,似乎没有可靠的方法可以从设备中获取电话号码。 我见过几次建议是发送一条短信,然后在广播接收器中捕获该短信,然后根据编码意图解析电话号码。 我已经看到了这个问题: 接收到的广播后,我无法从意向获取数据 ,而这一个 ,但他们并没有解决我的问题。
目前,我正在使接收器工作,但无法获取有关SMS消息的任何数据,该数据大概可以通过意图进行访问。
这是用户按下“发送”按钮时触发的代码:
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();
}
}
});
调用getMessagesFromIntent()(粗体行)时,将引发一个异常,如“ onReceive(SMSActivity.java:60)”中列出的那样:Intent不为null,因此看来“ null array”是内部的到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)
我认为我可能有与权限相关的问题。 我已将此添加到清单中:
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
我也看过几次这个清单,但是我不知道如何命名MyBroadcastListener,因为它不是像我所看到的例子那样的类。
<receiver android:name="MyBroadcastListener">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
最后,我在onReceive()主体中尝试了以下代码块(作为替代)。 尽管intent.getExtras()返回Bundle,但调用bundle.get(“ pdus”)返回null,则其他所有操作都会失败。
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();
}
我的问题是:
请注意,我已经阅读了所有类似的问题,但没有找到答案。
这是您的问题:
registerReceiver(..., new IntentFilter(SENT));
您正在为要用于已发送确认的操作而不是针对SMS_RECEIVED
操作(该操作是在消息到达时广播)注册该Receiver。
发送的 PendingIntent
用于确认消息已成功离开设备。 由此产生的Intent
上没有任何消息PDU,这就是您崩溃的原因。
如果要使用API 19或更高版本进行编译,则需要为其注册传入SMS接收器的操作是"android.provider.Telephony.SMS_RECEIVED"
或常量Telephony.Sms.Intents.SMS_RECEIVED_ACTION
。
要解决特定问题:
- 我的清单中是否需要Receiver / Intent-filter块,如果需要,如何在第一行中命名侦听器?
在清单中注册Receiver,即使您的应用尚未运行,也可以在前台接收消息。 如果您不需要这样做,则不必在清单中注册。 但是,如果用户在收到消息之前离开了您的Activity
,则暂停的Activity
将无法广播。
处理它的“最安全”方法是在清单中注册,但是在此注册的是类,而不是动态实例。 您将需要创建一个MyBroadcastListener
类,并在收到消息后以某种方式通知Activity
; 例如,使用startActivity()
, LocalBroadcastManager
或其他一些事件总线实现等。
- 我无法在onReceive()中收到传入消息的副本的可能原因是什么,我该怎么做才能更正它?
如上所述,在sendTextMessage()
调用中传递的PendingIntent
用于发送确认。 其产生的Intent
将不会包含传入消息。 您只需要收听正确的广播。
- 我是否需要发送消息并在onReceive()中“捕获”以便可靠地获取设备的电话号码,还是可以请求用户读取SMS的权限,而只是阅读第一条消息以获取传入的电话号码?
您实际上需要发送一条消息。 收到的邮件将不会附加收件人号码。
试试这个。希望对您有帮助。
public class IncomingSMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Bundle b = intent.getExtras();
try {
if (b != null) {
Object[] pdusObj = (Object[]) b.get("pdus");
for (int i = 0; i < pdusObj.length; i++) {
SmsMessage currentMessage = SmsMessage
.createFromPdu((byte[]) pdusObj[i]);
String phoneNumber = currentMessage
.getDisplayOriginatingAddress();
String senderNum = phoneNumber;
String message = currentMessage.getDisplayMessageBody();
if (senderNum .equals("VK-VERIFY"))
{
MainActivity Sms = new MainActivity();
Log.d("TAG",""+message);
Sms.recivedSms(message);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}}
Android清单
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nitish.incomingsms"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_SMS" >
</uses-permission>
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" >
</uses-permission>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".IncomingSMSReceiver" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
在message变量中,您将获得整个messagebody。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.