安卓。使用服务拦截与条件匹配的短信

发布于 2025-01-03 08:44:15 字数 3531 浏览 0 评论 0原文

我的运营商(我住在委内瑞拉)不断向我发送短信,其中有些是垃圾,有些是我关心的,我真的不想从市场上下载短信应用程序,因为我正在做一些非常具体和简单的事情。

基本思想:我有一个 BroadcastReceiver 来捕获 SMS 接收的意图,为了对操作系统友好,我在这里不进行任何处理(我希望能够构建尽可能复杂的规则考虑并且没有长时间运行的问题,可能使用数据库或其他无法在 BroadcastReceiver 中完成的异步任务),而是将相同的 Bundle 发送到处理的 IntentService这短信。

一般来说,这工作得很好,如果我想避免系统通知我收到了短信,我可以停止广播,并且 IntentService 可以完美地处理短信。

问题:

我如何在服务中处理短信,然后决定是否希望系统注意到我收到了短信?

我强烈希望避免这样做在 BroadcastReceiver 内部进行处理。 (这对您在 onReceive(Context, Intent) 中可以执行的操作有重要影响) 实现:任何需要异步操作的东西都不可用,因为您需要从函数返回来处理异步操作,但此时 BroadcastReceiver 不再活动,因此系统可以在异步操作完成。

我曾考虑过处理短信,如果不符合我的标准,我可以重新发出短信接收广播,并在捆绑包中添加额外的内容,以检查它之前是否已被验证。但我无法让它发挥作用。

代码:

public class SmsReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        if(!intent.getExtras().getBoolean("previouslyChecked",false)){
            this.abortBroadcast();
            Intent serviceIntent = new Intent(context, SmsRecievedServices.class);
            serviceIntent.putExtras(intent);
            context.startService(serviceIntent);
        }
    }
}

public class SmsRecievedServices extends IntentService {

    public SmsRecievedServices() {
        super("SmsRecievedServices");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle bundle = intent.getExtras();     
        if(!smsMatchesCriteria(bundle)){
            Intent intent2 = new Intent("android.provider.Telephony.SMS_RECEIVED");
            bundle.putBoolean("previouslyChecked",true);
            intent2.putExtras(bundle);
            sendOrderedBroadcast(intent2,"android.permission.RECEIVE_SMS");
        }           
    }
}

广播接收方收到意图并且不会取消广播,但系统不会接收短信。有什么想法吗?

编辑(回应 Blundell 的评论):

我想到了这样一个事实,也许我添加一个额外的内容会毁掉它,所以我尝试了以下操作:

public class SmsReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {           
        int randomNum = (int)Math.ceil(Math.random()*100);
        if(randomNum > 20){ 
            this.abortBroadcast();
            Intent serviceIntent = new Intent(context, SmsRecievedServices.class);
            serviceIntent.putExtras(intent);
            context.startService(serviceIntent);
        }
    }
}

public class SmsRecievedServices extends IntentService {

    public SmsRecievedServices() {
        super("SmsRecievedServices");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("SMSManager","Forwarding intent");
    Bundle bundle = intent.getExtras();
    Intent intent2 = new Intent("android.provider.Telephony.SMS_RECEIVED");
    intent2.putExtras(bundle);
    sendOrderedBroadcast(intent2, "android.permission.RECEIVE_SMS");
        }
}

LogCat 输出是:

02-10 22:06:24.632: I/SMSManager(424): RandomNumber: 74
02-10 22:06:24.673: I/SMSManager(424): Forwarding intent
02-10 22:06:24.683: I/SMSManager(424): RandomNumber: 64
02-10 22:06:24.803: I/SMSManager(424): Forwarding intent
02-10 22:06:24.824: I/SMSManager(424): RandomNumber: 28
02-10 22:06:24.832: I/SMSManager(424): Forwarding intent
02-10 22:06:24.854: I/SMSManager(424): RandomNumber: 14

如您所见,该消息对系统隐藏了 3 次,第四次我没有调用中止广播,因为随机数低于 20。操作系统没有在收件箱或通知栏中显示新的短信。

My carrier (I live in Venezuela) is constantly sending me SMS, some of it is crap, some of it I care about, I dont really want to download an SMS app from the market since im doing something very specific and simple.

Basic idea: I have a BroadcastReceiver that captures the SMS recived intent, in order to be nice to the OS, I dont do any processing here (I want to be able to build rules as complex as I can think of and not have long running issues, maybe using DB or other Asynchronous tasks that cant be done in a BroadcastReceiver), instead I send the same Bundle to an IntentService that processes the SMS.

This works fine in general, I can stop the broadcast if I want to avoid having the System notice I got an SMS, and the IntentService processes the SMS perfectly.

Issue:

How do I process the SMS in the service and then decide wether or not I wanted the System to notice I got an SMS?

I strongly would like to avoid doing the procesing inside the BroadcastReceiver. (This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.)

I had though of processing the SMS, and if didnt match my criteria, I could re-issue the SMS Recive broadcast with an aditional extra in the bundle to check wether or not it had been previously verified. But I cant get this to work.

Code:

public class SmsReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {
        if(!intent.getExtras().getBoolean("previouslyChecked",false)){
            this.abortBroadcast();
            Intent serviceIntent = new Intent(context, SmsRecievedServices.class);
            serviceIntent.putExtras(intent);
            context.startService(serviceIntent);
        }
    }
}

public class SmsRecievedServices extends IntentService {

    public SmsRecievedServices() {
        super("SmsRecievedServices");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle bundle = intent.getExtras();     
        if(!smsMatchesCriteria(bundle)){
            Intent intent2 = new Intent("android.provider.Telephony.SMS_RECEIVED");
            bundle.putBoolean("previouslyChecked",true);
            intent2.putExtras(bundle);
            sendOrderedBroadcast(intent2,"android.permission.RECEIVE_SMS");
        }           
    }
}

The broadcast reciever gets the intent and doesnt cancel the broadcast, but the system doesnt pick up on the SMS. Any ideas?

Edit (In response to Blundell's comment):

I thought about the fact that maybe me adding an extra would ruin it, so I tried the following:

public class SmsReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent) 
    {           
        int randomNum = (int)Math.ceil(Math.random()*100);
        if(randomNum > 20){ 
            this.abortBroadcast();
            Intent serviceIntent = new Intent(context, SmsRecievedServices.class);
            serviceIntent.putExtras(intent);
            context.startService(serviceIntent);
        }
    }
}

public class SmsRecievedServices extends IntentService {

    public SmsRecievedServices() {
        super("SmsRecievedServices");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("SMSManager","Forwarding intent");
    Bundle bundle = intent.getExtras();
    Intent intent2 = new Intent("android.provider.Telephony.SMS_RECEIVED");
    intent2.putExtras(bundle);
    sendOrderedBroadcast(intent2, "android.permission.RECEIVE_SMS");
        }
}

LogCat output is:

02-10 22:06:24.632: I/SMSManager(424): RandomNumber: 74
02-10 22:06:24.673: I/SMSManager(424): Forwarding intent
02-10 22:06:24.683: I/SMSManager(424): RandomNumber: 64
02-10 22:06:24.803: I/SMSManager(424): Forwarding intent
02-10 22:06:24.824: I/SMSManager(424): RandomNumber: 28
02-10 22:06:24.832: I/SMSManager(424): Forwarding intent
02-10 22:06:24.854: I/SMSManager(424): RandomNumber: 14

As you can see, the message was hidden from the system three times, the fourth time im not calling abort broadcast as the randomNumber is lower than 20. The OS does not show a new SMS, neither in inbox or notification bar.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深者入戏 2025-01-10 08:44:15

消息传递应用程序中 android.provider.Telephony.SMS_RECEIVED Intent 的接收器受到保护,并且只会处理平台发送的 Intent(它会丢弃欺骗的 Intent)。

避免在广播接收器中进行处理的唯一方法是将 android.permission.WRITE_SMS 权限添加到您的应用程序并自行将 SMS 写入数据库。

由于 SMS/MMS 提供商不是已发布的 API,它可能因版本和供应商而异 - 因此与其集成可能会很糟糕。

通常,如果您希望能够取消消息,则应在接收器中完成消息的处理。任何耗时的操作(例如列出大量联系信息)都应该通过应用程序中的缓存机制来解决。

The receiver for the android.provider.Telephony.SMS_RECEIVED intent in the messaging application is protected and will only process Intents sent by the platform (it drops spoofed Intents).

The only way to avoid doing the processing in the broadcast receiver is to add the android.permission.WRITE_SMS permission to your application and write the SMS to the database yourself.

Since the SMS / MMS provider is not a published API it may vary between versions and vendors - thus integrating with it will likely suck.

Typically processing of the message should be done in the receiver if you want to be able to cancel it. Any time consuming actions (such as listing a lot of contact information) should be solved by a caching mechanism in your application.

寄与心 2025-01-10 08:44:15

我昨天在调查推送时读到了这篇文章。这里的文章指向一个可用于拦截 SMS 的 API(在 SMS 部分下)。可能有帮助吗?

http://tokudu.com/2010/how-to-实现-push-notifications-for-android/

I was reading about this yesterday when investigating push. Article here points to an API which is available for intercepting SMS (under SMS section). It may help?

http://tokudu.com/2010/how-to-implement-push-notifications-for-android/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文