我希望我的应用能够捕获传入的短信。这方面有一些例子。看起来我们只需要这样做:
// 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.");
....
}
}
这是对的吗?我正在给手机发送一些短信,但日志声明永远不会被打印出来。我确实在手机上安装了一些其他短信应用程序,当收到短信时显示弹出窗口 - 他们是否以某种方式阻止意图传递给我的应用程序,他们只是完全消耗它?
由于
答案 0 :(得分:30)
您还需要在清单文件中指定使用权限:
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
以下教程应该有所帮助:
答案 1 :(得分:9)
这些答案还没有提到的另一件事 - 您应该要求权限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>
答案 2 :(得分:9)
路上有一些陷阱。您可以在stackoverflow上找到所有需要的信息。为方便起见,我已收集了此答案中的所有信息。
"android.provider.Telephony.SMS_RECEIVED"
"android.permission.RECEIVE_SMS"
才能接收短信。在android 6及更高版本中,您还需要在运行时请求权限。adb shell am broadcast
无效。使用telnet连接到模拟器来测试短信接收。最重要的是有可能向设备发送虚假短信,因此我们可以测试代码。
为此,我们将使用虚拟设备和telnet连接。
现在使用telnet连接到模拟器标题栏中显示的端口号
$ telnet localhost 5554
如果您看到:Android Console: Authentication required
,则需要使用此命令验证连接:
auth xxxxxx
使用从xxxxxx
文件中读取的令牌替换上面的~/.emulator_console_auth_token
。
现在您应该能够运行所有命令。要发送短信,请输入以下命令:
sms send 555 "This is a message"
您可以使用发件人电话号码和自己的信息替换555.
要获取广播,您需要注册BroadcastReceiver
对象。您可以在manifest.xml OR 中调用registerReceiver
函数执行此操作。我会告诉你后者,因为它更容易推理,而且更灵活。
将广播接收器与主要活动连接
数据流是一种方式。从广播接收器到主要活动。因此,让他们说话的最简单方法是使用功能界面。活动将实现这样的功能,广播接收器将把活动实例作为构造函数中的参数传递。
文件SmsHandler.java:
package ...
interface SmsHandler {
void handleSms(String sender, String message);
}
实施广播接收器
广播接收器将获得回调意图。我们将使用函数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);
}
}
}
最后请记住将RECEIVE_SMS权限添加到清单xml
<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<application>
...
</application>
</manifest>
答案 3 :(得分:3)
另请注意,环聊应用程序目前会阻止我的BroadcastReceiver接收短信。在我的SMS BroadcastReceived开始被解雇之前,我不得不在环聊应用中禁用短信功能(设置 - &gt;短信 - &gt;开启短信)。
编辑:似乎某些应用程序将在意图上abortBroadcast(),这将阻止其他应用程序接收意图。解决方案是增加android:priority
标记中的intent-filter
属性:
<receiver android:name="com.company.application.SMSBroadcastReceiver" >
<intent-filter android:priority="500">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
在此处查看更多详情:Enabling SMS support in Hangouts 2.0 breaks the BroadcastReceiver of SMS_RECEIVED in my app
答案 4 :(得分:2)
您是否尝试使用emulator?
在模拟器中部署应用程序后,您可以通过DDMS或通过连接telnet通过命令行发送SMS等事件:
telnet localhost <port_emulator>
send sms <incoming_tel_number> <sms_content>
port_emulator通常是5554
答案 5 :(得分:1)
您应该以编程方式阅读本文关于发送和接收短信的内容。 http://mobiforge.com/developing/story/sms-messaging-android
答案 6 :(得分:0)
Android Messenger( SMS 客户端)具有“聊天”功能,可通过WiFi而不是SMS传输消息。
如果要测试的人也使用Messenger,则需要在一个或两个设备上禁用此功能,否则实际上不会收到SMS消息:
要关闭聊天功能,请执行以下操作:
- 打开消息消息徽标回合。
- 点击“更多”,然后点击“设置”。
- 点击“高级”,然后点击“聊天”功能。
- 打开或关闭启用聊天功能。