Android - приемник SMS-трансляции
Я пытался заставить эту программу работать, но пока безуспешно. Я не могу найти, где я делаю неправильно. Я не уверен, что что-то не так с кодом или отладкой.
Я пытаюсь получить уведомление, если приходит новое SMS.
Вот моя программа:
package Technicaljar.SMSBroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
public class SMSBroadcastReceiver extends BroadcastReceiver {
private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
private static final String TAG = "SMSBroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "Intent recieved: " + intent.getAction());
if (intent.getAction() == SMS_RECEIVED) {
Bundle bundle = intent.getExtras();
if (bundle != null) {
Object[] pdus = (Object[])bundle.get("pdus");
final SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
}
if (messages.length > -1) {
Log.i(TAG, "Message recieved: " + messages[0].getMessageBody());
}
}
}
}
}
И файл манифеста:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="Technicaljar.SMSBroadcastReceiver"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true" >
<receiver android:name=".SMSBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.telephony.SMS_RECEIVED"></action>
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
</manifest>
Я отправляю SMS через Telnet, и я не вижу сообщений о полученных намерениях в logcat. Вот мой logcat со времени установки.
D/AndroidRuntime( 478):
D/AndroidRuntime( 478): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<
D/AndroidRuntime( 478): CheckJNI is ON
D/AndroidRuntime( 478): --- registering native functions ---
D/AndroidRuntime( 478): Shutting down VM
D/dalvikvm( 478): Debugger has detached; object registry had 1 entries
I/AndroidRuntime( 478): NOTE: attach of thread 'Binder Thread #3' failed
D/Mms:app ( 220): getSmsNewMessageNotificationInfo: count=14, first addr=12345, thread_id=4
D/dalvikvm( 151): GC_EXPLICIT freed 391 objects / 22552 bytes in 65ms
D/dalvikvm( 220): GC_EXPLICIT freed 926 objects / 44840 bytes in 73ms
Таким образом, кажется, что эмулятор получил SMS-сообщение, но похоже, что нет смысла стрелять. Что я здесь не так делаю? После установки мне нужно как-то "запустить" этот ресивер? Потому что при установке я получаю
[2010-11-07 21:24:41 - SMSBroadcastReceiver] No Launcher activity found!
[2010-11-07 21:24:41 - SMSBroadcastReceiver] The launch will only sync the application package on the device!
Поэтому мне интересно, если что-то здесь не так.
10 ответов
android.provider.Telephony.SMS_RECEIVED
имеет капитал T
и твой в манифесте нет.
Пожалуйста, имейте в виду, что это Intent
действие не задокументировано.
Я попробовал ваш код и обнаружил, что он не работает.
Я должен был изменить
if (intent.getAction() == SMS_RECEIVED) {
в
if (intent.getAction().equals(SMS_RECEIVED)) {
Теперь это работает. Это просто проблема с проверкой равенства Java.
Также обратите внимание, что приложение Hangouts в настоящее время блокирует мой BroadcastReceiver от получения SMS-сообщений. Мне пришлось отключить функцию SMS в приложении Hangouts (Настройки->SMS-> Включить SMS), прежде чем мой SMS BroadcastReceived начал срабатывать.
Редактировать: Похоже, что некоторые приложения будут 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>
Подробнее см. Здесь: Включение поддержки SMS в Hangouts 2.0 отключает BroadcastReceiver SMS_RECEIVED в моем приложении
intent.getAction().equals(SMS_RECEIVED)
Я попробовал это успешно.
Наткнулся сегодня на это. Для тех, кто сегодня кодирует получателя SMS, используйте этот код вместо устаревшего в OP:
SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent);
SmsMessage smsMessage = msgs[0];
Одна важная вещь, которая должна быть упомянута в этой теме, это описание aboud pdu
PDU - это "блок описания протокола", который является отраслевым форматом для сообщения SMS. потому что SMSMessage читает / пишет их, вам не нужно разбирать их.
Большое сообщение может быть разбито на многие, поэтому это массив объектов.
Обновленный код:
private class SMSReceiver extends BroadcastReceiver {
private Bundle bundle;
private SmsMessage currentSMS;
private String message;
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")) {
bundle = intent.getExtras();
if (bundle != null) {
Object[] pdu_Objects = (Object[]) bundle.get("pdus");
if (pdu_Objects != null) {
for (Object aObject : pdu_Objects) {
currentSMS = getIncomingMessage(aObject, bundle);
String senderNo = currentSMS.getDisplayOriginatingAddress();
message = currentSMS.getDisplayMessageBody();
Toast.makeText(OtpActivity.this, "senderNum: " + senderNo + " :\n message: " + message, Toast.LENGTH_LONG).show();
}
this.abortBroadcast();
// End of loop
}
}
} // bundle null
}
}
private SmsMessage getIncomingMessage(Object aObject, Bundle bundle) {
SmsMessage currentSMS;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String format = bundle.getString("format");
currentSMS = SmsMessage.createFromPdu((byte[]) aObject, format);
} else {
currentSMS = SmsMessage.createFromPdu((byte[]) aObject);
}
return currentSMS;
}
старый код был:
Object [] pdus = (Object[]) myBundle.get("pdus");
messages = new SmsMessage[pdus.length];
for (int i = 0; i < messages.length; i++)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String format = myBundle.getString("format");
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i], format);
}
else {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
strMessage += "SMS From: " + messages[i].getOriginatingAddress();
strMessage += " : ";
strMessage += messages[i].getMessageBody();
strMessage += "\n";
}
Простой синтаксис кода:
private class SMSReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
SmsMessage[] smsMessages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
for (SmsMessage message : smsMessages) {
// Do whatever you want to do with SMS.
}
}
}
}
Ваш вещатель должен указать android:exported="true"
получать трансляции, созданные вне вашего собственного приложения. Мой широковещательный приемник определяется в манифесте следующим образом:
<receiver
android:name=".IncomingSmsBroadcastReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
Как отмечено ниже, exported="true" является значением по умолчанию, поэтому вы можете опустить эту строку. Я оставил это так, чтобы комментарии обсуждения имели смысл.
Я недавно столкнулся с такой проблемой. Хотя код был правильным, я не включил разрешения в настройках приложения. Таким образом, все разрешения не установлены по умолчанию на эмуляторах, поэтому вы должны сделать это самостоятельно.
Для Android 19+ вы можете получить его в Telephony.Sms.Intents.SMS_RECEIVED_ACTION)
, Есть больше в Intent
класс, который стоит посмотреть
android.provider.telephony.SMS_RECEIVED
не правильно, потому что телефония является классом, и она должна быть капиталом, как в android.provider.Telephony.SMS_RECEIVED