【问题标题】:using SMS BroadcastReceiver for both Kitkat and old versions对 Kitkat 和旧版本使用 SMS BroadcastReceiver
【发布时间】:2021-05-13 12:59:01
【问题描述】:

我正在开发一个需要接收短信的应用程序,并且不允许任何其他应用程序接收短信。

应用必须在 Kitkat 和旧版本上都能正常运行。(我在 kitkat 中将我的应用设为默认短信应用)

这是我在 manifast 文件中尝试的内容(不是全部):

    <receiver android:name=".SmsReceiver"
            android:permission="android.permission.BROADCAST_SMS">
        <intent-filter android:priority="2147483647" >
            <action android:name="android.provider.Telephony.SMS_DELIVER" />
        </intent-filter>
    </receiver>



    <receiver android:name=".SmsReceiver" android:enabled="true">
        <intent-filter android:priority="2147483647">
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>

第一个接收器用于 kitkat 让我的应用成为默认短信应用(当我删除这部分 kitkat 时,不要让我的应用成为默认短信应用),第二个接收器用于旧版本

在 kitkat 上,问题是我所有的代码都运行了两次(因为我有两个接收器)

在旧版本上,我的应用程序运行一次 onReceive 方法,但我从 Go SMS Pro 收到了新消息通知,但我只需要我的应用程序接收短信

这是我的 SmsReceiver 类:

public class SmsReceiver extends BroadcastReceiver 
{

    @Override
    public void onReceive(Context context, Intent intent) 
    {
        Bundle bundle = intent.getExtras();
        if (bundle != null) 
        {
            Object[] pdus = (Object[]) bundle.get("pdus");
            if (pdus.length == 0) 
            {
                return;
            }
            SmsMessage[] messages = new SmsMessage[pdus.length];
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < pdus.length; i++) 
            {
                messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                sb.append(messages[i].getMessageBody());
            }
            String sender = messages[0].getOriginatingAddress();
            String message = sb.toString();

            abortBroadcast();// prevent any other broadcast receivers from receiving broadcast

            // things I need to do on SMS

        }
    }// on Rec

}

【问题讨论】:

  • 记录您看到的每次调用的操作。
  • 你可以测试广播是否被订购。我希望不再订购新的SMS_RECEIVED_ACTION,因为它不可中止。

标签: android broadcastreceiver


【解决方案1】:

为了支持旧版和新版 Android 的 SMS 处理,我建议使用两种不同的 BroadcastReceiver 类:一种用于新的 SMS_DELIVER_ACTION,另一种注册用于原始的 SMS_RECEIVED 操作,应该是在 KitKat(API 级别 19)及更高版本上禁用,这样您就不会收到两次相同的消息。每个 Receiver 都可以简单地将检索到的消息传递给一个公共处理组件——例如,背景Service——这样你就不会重复代码。

我们可以使用资源bool 来影响版本启用/禁用,默认情况下true,但false 在以KitKat 开头的版本上。例如:

res/values/booleans.xml:

<resources>
    <bool name="isPreKitKat">true</bool>
</resources>

res/values-v19/booleans.xml:

<resources>
    <bool name="isPreKitKat">false</bool>
</resources>
<receiver
    android:name=".SmsReceiver"
    android:permission="android.permission.BROADCAST_SMS">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_DELIVER" />
    </intent-filter>
</receiver>

<receiver
    android:name=".OldSmsReceiver"
    android:enabled="@bool/isPreKitKat"
    android:permission="android.permission.BROADCAST_SMS">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

SMS_DELIVER_ACTION 在 KitKat 之前的版本上不存在,因此 Receiver 永远不应该在这些版本上运行,尽管您可能希望类似地启用/禁用 SmsReceiver,如果只是出于安全原因。


在较新的版本中,您根本无法中止 SMS_RECEIVED_ACTION 广播,因为现在从 KitKat 开始完全不允许这样做。 (Source)

请注意,从 Android 4.4 开始,您的应用尝试中止 SMS_RECEIVED_ACTION 广播的任何尝试都将被忽略,因此所有感兴趣的应用都有机会收到它。

但是,如果其他 SMS/消息应用程序的行为符合建议,他们认为您不应该再收听 SMS_RECEIVED_ACTION 广播。如果他们不是默认的,他们将不会得到SMS_DELIVER_ACTION 一个。

因此,除了这些应用程序之外,任何其他能够侦听 SMS 的应用程序都希望仅在必要时才这样做,并且仅用于有效目的,因为在 KitKat 及更高版本上您实际上无法采取任何措施来阻止它。


至于您在 KitKat 之前的版本上使用 GO SMS Pro 的问题,您可能无能为力。在其他来源中,this post thread 建议您可以通过确保在 GO SMS Pro 之前安装您的应用程序来解决该问题。但是,您可以从 cmets 看到这不是一个有保证的解决方案。您可能会建议您的用户关闭 GO SMS Pro 的“禁用其他消息通知”选项,以便您的应用至少可以接收相关广播,即使它无法中止它们。请注意,环聊通常会导致同样的问题。

【讨论】:

  • 我的主要问题是,在 kitkat 上,onReceive 方法将在我的应用程序中执行两次(因为我为旧版本添加了另一个接收器,它也将在 kitkat 上执行),我只想执行只有一次
  • 我不明白为什么他们添加了一个新的广播来替换之前的广播并修改之前的广播行为,而不是简单地添加一个不会中止的新广播。在我看来,这会使过渡更容易。
  • @MikeM。我是初学者,我该怎么做?
  • @AJW 哦,好的,我想我明白了。您的应用只是在监控某些短信的传入?无论如何,在 KitKat+ 上,如果您的应用不是默认的 SMS 应用,它永远不会收到 SMS_DELIVER 广播,因此您不需要单独的接收器。你只需要一个SMS_RECEIVED,它仍然像往常一样工作(除了它是无序的,不能再中止了)。
  • @Mike M。是的,监视具有来自应用程序的另一个用户的密码的 SMS 消息,然后传送数据。关于 SMS_RECEIVED 的理解。感谢您的回复和您的专业知识,干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多