【问题标题】:Android - SMS Broadcast receiverAndroid - 短信广播接收器
【发布时间】:2011-05-06 06:51:23
【问题描述】:

我一直试图让this 程序工作,但到目前为止还没有运气。我找不到我做错的地方。不知道是不是代码有问题,或者调试有问题。

我正在尝试收到新短信时的通知。

这是我的程序:

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> 

我正在通过 Telnet 发送 SMS,但我在 logcat 中看不到任何 Intent 接收消息。这是我安装时的 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

所以模拟器似乎收到了短信,但看起来没有意图正在触发。 我在这里做错了什么?安装后,我是否必须以某种方式“启动”这个接收器? 因为当我安装时,我得到了

 [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!

所以我想知道这里是否有问题。

【问题讨论】:

标签: android sms android-intent broadcastreceiver


【解决方案1】:

今天偶然发现了这个。对于现在编写 SMS 接收器的任何人,请使用此代码而不是 OP 中已弃用的代码:

SmsMessage[] msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent);
SmsMessage smsMessage = msgs[0];

【讨论】:

  • 您需要为此启用运行时权限吗?
【解决方案2】:

另外请注意,环聊应用目前会阻止我的 BroadcastReceiver 接收 SMS 消息。在我的 SMS BroadcastReceived 开始被触发之前,我必须在环聊应用程序中禁用 SMS 功能(设置-> SMS-> 打开 SMS)。

编辑:似乎某些应用程序将在意图上中止Broadcast(),这将阻止其他应用程序接收该意图。解决方法是在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>

在此处查看更多详细信息:Enabling SMS support in Hangouts 2.0 breaks the BroadcastReceiver of SMS_RECEIVED in my app

【解决方案3】:

我最近遇到了这样的问题。虽然代码是正确的,但我没有在应用设置中打开权限。所以,模拟器上默认没有设置所有权限,所以你应该自己做。

【讨论】:

    【解决方案4】:

    更新后的代码是:

     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.
                }
            }
        }
    }
    

    【讨论】:

    • 你能把整个项目放到github上吗?
    【解决方案5】:

    对于 android 19+,您可以在 Telephony.Sms.Intents.SMS_RECEIVED_ACTION) 中获取它。 Intents 类中还有更多值得一看的 在

    【讨论】:

      【解决方案6】:

      您的广播接收器必须指定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" 是默认值,因此您可以省略此行。我把它留在里面是为了让讨论变得有意义。

      【讨论】:

      • 不。当接收器具有意图过滤器时,它会自动导出。见developer.android.com/guide/topics/manifest/…
      • 公平评论。我怀疑这可能在最新版本的 Android 中发生了变化,我的代码最初是针对 Android 4.0 开发的。我会更新答案。
      【解决方案7】:

      android.provider.telephony.SMS_RECEIVED 不正确,因为 Telephony 是一个类,它应该是 android.provider.Telephony.SMS_RECEIVED 中的大写字母

      【讨论】:

        【解决方案8】:

        intent.getAction().equals(SMS_RECEIVED)

        我已经尝试成功了。

        【讨论】:

          【解决方案9】:

          我试过你的代码,发现它不起作用。

          我不得不改变

          if (intent.getAction() == SMS_RECEIVED) {
          

          if (intent.getAction().equals(SMS_RECEIVED)) {
          

          现在它正在工作。这只是 java 检查相等性的问题。

          【讨论】:

          • 仅供参考:从非空字符串调用 .equals(..) 总是更好。例如 - if (SMS_RECEIVED.equals(intent.getAction())) {
          【解决方案10】:

          android.provider.Telephony.SMS_RECEIVED 有一个大写 T,而你在清单中没有。

          请记住,此Intent 操作未记录在案。

          【讨论】:

          • 非常感谢 CommonsWare。这就是问题所在。它现在工作正常。谢谢你。另外,我能问一下为什么没有记录这个 Intent 吗?
          • 我不知道它没有记录。我看到很多人使用这个意图,我从没想过它没有记录。谢谢你的信息。
          • @Janusz:不,很遗憾。处理传入 SMS 所需的 99% 的代码存在于 SDK 中,而该常量不存在,这一事实表明该常量不太可能改变。但是,我不记得有任何官方声明,尽管有足够的机会这样做,但他们肯定没有将其放入 SDK 中。 SMS 客户端的开发人员只需要注意这个问题并像鹰一样观看新的 Android 版本。
          • @CommonsWare 发现“T”是鹰眼的工作!赞一个!
          猜你喜欢
          • 1970-01-01
          • 2022-01-08
          • 1970-01-01
          • 1970-01-01
          • 2022-11-28
          • 2012-11-14
          • 1970-01-01
          相关资源
          最近更新 更多