BroadcastReceiver + SMS_RECEIVED
我希望我的应用能够收到传入的短信。 这里有几个例子。 看起来我们只需要这样做:
// AndroidManifest.xml <receiver android:name=".SMSReceiver"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> // SMSReceiver.java public class SMSReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "SMS received."); .... } }
它是否正确? 我正在给我的手机发送一些短信,但是日志logging永远不会被打印出来。 我在手机上安装了一些其他短信应用程序,当收到短信时会显示一个popup窗口 – 是否阻止了传递到我的应用程序的意图,他们只是完全消耗它?
谢谢
您还需要在清单文件中指定一个uses-permission:
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
以下教程应该有所帮助:
响应传入的短信
Android中的短信
还有一件事,这些答案没有提到 – 你应该要求的权限android.permission.BROADCAST_SMS。 如果你不这样做,任何应用程序都可以欺骗你的应用程序的消息。
<receiver android:name=".SMSReceiver" android:exported="true" android:permission="android.permission.BROADCAST_SMS"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver>
路上有几个陷阱。 你可以find所有需要的信息在计算器上。 为了方便,我收集了这个答案中的所有信息。
事情要注意
- 我假设android kitkat和以上。
- 收集短信的意图是
"android.provider.Telephony.SMS_RECEIVED"
- 您可以更改意向filter的优先级,但不是必需的。
- 您需要清单xml中的此权限
"android.permission.RECEIVE_SMS"
,以便接收短信。 在Android 6及以上版本中,您还需要在运行时询问权限。 - 您不需要在意向filter中设置MIMEtypes的数据。 如果没有设置MIMEtypes,意向filter应该只传递空数据,但幸运的是它仍然可以在没有MIME的情况下工作。
-
adb shell am broadcast
将无法正常工作。 使用telnet连接模拟器来testing短信接收。 - 长短信息被分成小短信块。 我们需要连接它们。
如何发送短信到模拟器
最重要的是有可能发送假的短消息到设备,所以我们可以testing代码。
为此,我们将使用一个虚拟设备和一个telnet连接到它。
- 在android studio中创build一个虚拟设备并运行模拟器
- 看看模拟器窗口中的标题栏。 有设备名称和端口号 。 我们需要在接下来的步骤中知道这个端口号。
-
现在用telnet连接到模拟器标题栏中显示的端口号
$ telnet localhost 5554
-
如果您看到:
Android Console: Authentication required
,那么您需要使用此命令validation连接:auth xxxxxx
用从
~/.emulator_console_auth_token
文件中读取的标记replace上面的xxxxxx
。 -
现在你应该可以运行所有的命令。 要发送短信,请input以下命令:
sms send 555 "This is a message"
在哪里可以用发件人的电话号码和自己的留言来代替555。
如何收听SMS_RECEIVED广播
要获得广播,您需要注册一个BroadcastReceiver
对象。 您可以在manifest.xml中执行此操作, 或者只调用registerReceiver
函数。 我会告诉你后者,因为它更容易推理,更灵活。
将广播接收机连接到主要活动
数据stream是一种方式。 从广播接收机到主要活动。 所以最简单的方法就是使用一个函数接口。 该活动将实现这样的function,广播接收者将具有作为参数在构造函数中传递的活动实例。
文件SmsHandler.java:
package ... interface SmsHandler { void handleSms(String sender, String message); }
实现广播接收机
广播接收器将获得callback的意图。 我们将使用Telephony.Sms.Intents.getMessagesFromIntent(intent)
函数来获取短信息。 注意构造函数中的SmsHandler参数。 这将是我们将发送收到的短信的活动。
文件SmsInterceptor.java:
package ... import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.provider.Telephony; import android.telephony.SmsMessage; public class SmsInterceptor extends BroadcastReceiver { private SmsHandler handler; /* Constructor. Handler is the activity * * which will show the messages to user. */ public SmsInterceptor(SmsHandler handler) { this.handler = handler; } @Override public void onReceive(Context context, Intent intent) { /* Retrieve the sms message chunks from the intent */ SmsMessage[] rawSmsChunks; try { rawSmsChunks = Telephony.Sms.Intents.getMessagesFromIntent(intent); } catch (NullPointerException ignored) { return; } /* Gather all sms chunks for each sender separately */ Map<String, StringBuilder> sendersMap = new HashMap<>(); for (SmsMessage rawSmsChunk : rawSmsChunks) { if (rawSmsChunk != null) { String sender = rawSmsChunk.getDisplayOriginatingAddress(); String smsChunk = rawSmsChunk.getDisplayMessageBody(); StringBuilder smsBuilder; if ( ! sendersMap.containsKey(sender) ) { /* For each new sender create a separate StringBuilder */ smsBuilder = new StringBuilder(); sendersMap.put(sender, smsBuilder); } else { /* Sender already in map. Retrieve the StringBuilder */ smsBuilder = sendersMap.get(sender); } /* Add the sms chunk to the string builder */ smsBuilder.append(smsChunk); } } /* Loop over every sms thread and concatenate the sms chunks to one piece */ for ( Map.Entry<String, StringBuilder> smsThread : sendersMap.entrySet() ) { String sender = smsThread.getKey(); StringBuilder smsBuilder = smsThread.getValue(); String message = smsBuilder.toString(); handler.handleSms(sender, message); } } }
主要活动
最后,我们需要在主活动中实现SmsHandler接口,并在onCreate
函数中添加注册广播接收者和权限检查。
文件MainActivity.java:
package ... import ... public class MainActivity extends AppCompatActivity implements SmsHandler { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /* Register the broadcast receiver */ registerSmsListener(); /* Make sure, we have the permissions */ requestSmsPermission(); } /* This function will be called by the broadcast receiver */ @Override public void handleSms(String sender, String message) { /* Here you can display the message to the user */ } private void registerSmsListener() { IntentFilter filter = new IntentFilter(); filter.addAction("android.provider.Telephony.SMS_RECEIVED"); /* filter.setPriority(999); This is optional. */ SmsInterceptor receiver = new SmsInterceptor(this); registerReceiver(receiver, filter); } private void requestSmsPermission() { String permission = Manifest.permission.RECEIVE_SMS; int grant = ContextCompat.checkSelfPermission(this, permission); if ( grant != PackageManager.PERMISSION_GRANTED) { String[] permission_list = new String[1]; permission_list[0] = permission; ActivityCompat.requestPermissions(this, permission_list, 1); } } }
最后记得给你的manifest xml添加RECEIVE_SMS权限
<?xml version="1.0" encoding="utf-8"?> <manifest ...> <uses-permission android:name="android.permission.RECEIVE_SMS"/> <application> ... </application> </manifest>
另外请注意,环聊应用程序目前会阻止我的BroadcastReceiver接收短信。 我必须在环聊应用程序(设置 – >短信 – >打开短信)中禁用短信function,然后再开始短信广播接收。
编辑:它看起来好像有些应用程序将abortBroadcast()的意图,这将阻止其他应用程序接收意图。 解决方法是增加intent-filter
标记中的android:priority
属性:
<receiver android:name="com.company.application.SMSBroadcastReceiver" > <intent-filter android:priority="500"> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver>
在此处查看更多详情: 在环聊2.0中启用短信支持会在我的应用中打破SMS_RECEIVED的BroadcastReceiver
你用模拟器试过了吗?
在模拟器中部署应用程序之后,可以通过DDMS或者通过连接telnet的命令行发送类似SMS的事件:
telnet localhost <port_emulator> send sms <incoming_tel_number> <sms_content>
port_emulator通常是5554
你应该阅读这个关于发送和接收短信的程序。 http://mobiforge.com/developing/story/sms-messaging-android
- Android / FBReaderJ / gen已经存在,但不是源文件夹。 转换到源文件夹或重命名它
- Android的AsyncTaskLoader不启动loadInBackground?
- adb拉多个文件
- Android:如何在模拟器中使用摄像头?
- Android Google Maps API V2缩放至当前位置
- 如何在Android 6上请求位置权限
- Android:长按一下ExpandableListView的子视图?
- 使用跟踪代码pipe理器的Android内容实验在几天后不会显示会话
- java.lang.NoClassDefFoundError:android中的javax.activation.DataHandler