如何从广播接收器发送短信并检查其状态?

发布于 2024-11-29 13:39:08 字数 946 浏览 2 评论 0原文

所以这是我的 BroadcastReceiver

public class IncomingSMSListener extends BroadcastReceiver {
private static final String SMS_EXTRA_NAME = "pdus";

@Override
public void onReceive(Context context, Intent intent) {
    SmsMessage[] messages = fetchSMSMessagesFromIntent(intent);
}

private SmsMessage[] fetchSMSMessagesFromIntent(Intent intent) {
    ArrayList<SmsMessage> receivedMessages = new ArrayList<SmsMessage>();
    Object[] messages = (Object[]) intent.getExtras().get(SMS_EXTRA_NAME);
    for (Object message : messages) {
        SmsMessage finalMessage = SmsMessage
                .createFromPdu((byte[]) message);
        receivedMessages.add(finalMessage);
    }
    return receivedMessages.toArray(new SmsMessage[0]);
}

}

我能够很好地读取传入的消息,但是假设从这里我想将消息转发到另一个电话号码并确保它已发送。我知道我可以执行 SmsManager.sendTextMessage() 但如何设置 PendingIntent 部分以通知短信是否已发送?

So this is my BroadcastReceiver

public class IncomingSMSListener extends BroadcastReceiver {
private static final String SMS_EXTRA_NAME = "pdus";

@Override
public void onReceive(Context context, Intent intent) {
    SmsMessage[] messages = fetchSMSMessagesFromIntent(intent);
}

private SmsMessage[] fetchSMSMessagesFromIntent(Intent intent) {
    ArrayList<SmsMessage> receivedMessages = new ArrayList<SmsMessage>();
    Object[] messages = (Object[]) intent.getExtras().get(SMS_EXTRA_NAME);
    for (Object message : messages) {
        SmsMessage finalMessage = SmsMessage
                .createFromPdu((byte[]) message);
        receivedMessages.add(finalMessage);
    }
    return receivedMessages.toArray(new SmsMessage[0]);
}

}

I'm being able to read the incoming message just fine and all, but let's say from here I want to forward the message to another phone number and make sure it got sent. I know I can do SmsManager.sendTextMessage() but how do I set up the PendingIntent part to be notified whether the SMS got sent or not?

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

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

发布评论

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

评论(2

凯凯我们等你回来 2024-12-06 13:39:08

好吧,最终找到了解决方案。由于传递到 BroadCastReceiver 中的 onReceive() 方法的上下文不允许我注册其他 BroadcastReceiver 来侦听“消息发送”事件,因此我最终掌握了应用程序上下文并执行以下操作

: :

SmsManager smsManager = SmsManager.getDefault();
    Intent intent = new Intent(SENT_SMS_FLAG);
    PendingIntent sentIntent = PendingIntent.getBroadcast(context, 0,
            intent, 0);
    SMSForwarderApp.getAppContext().registerReceiver(
            new MessageSentListener(),
            new IntentFilter(SENT_SMS_FLAG));
    smsManager.sendTextMessage("Here goes the destination of the SMS", null,
            "Here goes the content of the SMS", sentIntent, null);

SENT_SMS_FLAG 只是一个静态字符串,唯一标识我刚刚发出的意图。我的 MessageSentListener 看起来像这样:

public class MessageSentListener extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
    int resultCode = this.getResultCode();
    boolean successfullySent = resultCode == Activity.RESULT_OK;
    //That boolean up there indicates the status of the message
    SMSForwarderApp.getAppContext().unregisterReceiver(this);
            //Notice how I get the app context again here and unregister this broadcast
            //receiver to clear it from the system since it won't be used again
}

}

OK, ended up finding the solution in the end. Since the context passed in to the onReceive() method in the BroadCastReceiver doesn't let me register other BroadcastReceivers to listen for the "message sent" event, I ended up getting a grip of the app context and doing what follows:

In the BroadcastReceiver:

SmsManager smsManager = SmsManager.getDefault();
    Intent intent = new Intent(SENT_SMS_FLAG);
    PendingIntent sentIntent = PendingIntent.getBroadcast(context, 0,
            intent, 0);
    SMSForwarderApp.getAppContext().registerReceiver(
            new MessageSentListener(),
            new IntentFilter(SENT_SMS_FLAG));
    smsManager.sendTextMessage("Here goes the destination of the SMS", null,
            "Here goes the content of the SMS", sentIntent, null);

SENT_SMS_FLAG is simply a static string that uniquely identifies the intent I just made. My MessageSentListener looks like this:

public class MessageSentListener extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
    int resultCode = this.getResultCode();
    boolean successfullySent = resultCode == Activity.RESULT_OK;
    //That boolean up there indicates the status of the message
    SMSForwarderApp.getAppContext().unregisterReceiver(this);
            //Notice how I get the app context again here and unregister this broadcast
            //receiver to clear it from the system since it won't be used again
}

}

居里长安 2024-12-06 13:39:08

如果其他人像我一样并试图找出如何在 Kotlin 中执行此操作,这里有一些代码可能会对您的任务有所帮助:

只需注意几件事:

  1. 您可以通过以下方式测试 try/catch只需在模拟器中切换飞行模式即可。
  2. 您可以通过编写超出正常 SMS 字符限制的文本来在模拟器中测试失败的 SMS
  3. 因为这一切都在 try/catch 块中,所以请注意,由于 API 更改而可能出现的任何异常都不会在 Logcat 窗口中以红色突出显示。
  4. 另请注意,Google Play 最近对发送短信的应用程序收紧了要求,因此请注意,如果有人打算尝试将此类内容上传到 Google Play,他们可能需要 提供很多额外的理由

这是代码(很大程度上改编自 美国海军学院网站):

package com.example.texter

import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.telephony.SmsManager
import android.widget.Toast

class ClassTexter {
    fun mmSendText(mvText: String, mvNumber: String, mvApplicationContext: Context): Boolean {
        //Note: Because The Following Section is wrapped in a try/catch:
        //Exceptions might be trickier to spot in the Logcat since they aren't highlighted red.
        try {
            val mvSmsManager: SmsManager =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                    mvApplicationContext.getSystemService(SmsManager::class.java)
                } else {
                    SmsManager.getDefault()
                }
            val mvSentIntent = PendingIntent.getBroadcast(
                mvApplicationContext,
                0,
                Intent("SMS SENT"),
                PendingIntent.FLAG_IMMUTABLE
            )
            val mvDelvieredIntent = PendingIntent.getBroadcast(
                mvApplicationContext,
                0,
                Intent("SMS DELIVERED"),
                PendingIntent.FLAG_IMMUTABLE
            )

            val mvConfirmSentBroadcastReceiver: BroadcastReceiver =
                object : BroadcastReceiver() {
                    override fun onReceive(mvContext: Context, mvIntent: Intent) {
                        if (resultCode == Activity.RESULT_OK) {
                            Toast.makeText(
                                mvApplicationContext, "Text Dispatched!",
                                Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                        else
                        {
                            Toast.makeText(
                               mvApplicationContext, "Dispatch Failed!", //<-- This Part Can Be Tested By Exceeding SMS Character Limit
                               Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                    }
                }
            val mvConfirmDeliveryBroadcastReceiver: BroadcastReceiver =
                object : BroadcastReceiver() {
                    override fun onReceive(mvContext: Context, mvIntent: Intent) {
                        if (resultCode == Activity.RESULT_OK) {
                            Toast.makeText(
                                mvApplicationContext, "Text Delivered!",
                                Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                        else
                        {
                            Toast.makeText(
                                mvApplicationContext, "Delivery Failed!",
                                Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                    }
                }

            val mvSentIntentFilter = IntentFilter("SMS SENT")
            val mvDeliveredIntentFilter = IntentFilter("SMS DELIVERED")
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                mvApplicationContext.registerReceiver(
                    mvConfirmSentBroadcastReceiver,
                    mvSentIntentFilter,
                    Context.RECEIVER_EXPORTED
                )
                mvApplicationContext.registerReceiver(
                    mvConfirmDeliveryBroadcastReceiver,
                    mvDeliveredIntentFilter,
                    Context.RECEIVER_EXPORTED
                )
            } else {
                mvApplicationContext.registerReceiver(
                    mvConfirmSentBroadcastReceiver,
                    mvSentIntentFilter
                )
                mvApplicationContext.registerReceiver(
                    mvConfirmDeliveryBroadcastReceiver,
                    mvDeliveredIntentFilter
                )
            }


            mvSmsManager.sendTextMessage(
                mvNumber.filter { it.isDigit() },
                null,
                mvText,
                mvSentIntent,
                mvDelvieredIntent
            )

            //Confirm With Toast
                Toast.makeText(
                    mvApplicationContext, "Please stand by!",
                    Toast.LENGTH_SHORT
                ).show()

            return true

        } catch (mvEx: Exception) {
            Toast.makeText(
                mvApplicationContext, "Please try again!", //<-- This Part Can Be Tested With "Airplane Mode"
                Toast.LENGTH_LONG
            ).show()
            mvEx.printStackTrace()
            return false
        }
    }
}

If anyone else was like me and trying to find out how to do this in Kotlin, here's some code that might help in your quest:

Just a few things to note:

  1. You can test the try/catch by simply toggling Airplane Mode in the emulator.
  2. You can test a failed SMS in the emulator by composing a text that exceeds the normal SMS character limit.
  3. Because this is all in a try/catch block, please be aware that any exceptions that might arise due to API changes won't be highlighted in red in the Logcat window.
  4. Further note that Google Play has tightened requirements on apps that send SMS recently, so please be aware that if anyone intends to try to upload something like this to Google Play, they may be required to provide a lot of extra justification.

Here's the code (as heavily adapted from the US Naval Academy's site):

package com.example.texter

import android.app.Activity
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.telephony.SmsManager
import android.widget.Toast

class ClassTexter {
    fun mmSendText(mvText: String, mvNumber: String, mvApplicationContext: Context): Boolean {
        //Note: Because The Following Section is wrapped in a try/catch:
        //Exceptions might be trickier to spot in the Logcat since they aren't highlighted red.
        try {
            val mvSmsManager: SmsManager =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                    mvApplicationContext.getSystemService(SmsManager::class.java)
                } else {
                    SmsManager.getDefault()
                }
            val mvSentIntent = PendingIntent.getBroadcast(
                mvApplicationContext,
                0,
                Intent("SMS SENT"),
                PendingIntent.FLAG_IMMUTABLE
            )
            val mvDelvieredIntent = PendingIntent.getBroadcast(
                mvApplicationContext,
                0,
                Intent("SMS DELIVERED"),
                PendingIntent.FLAG_IMMUTABLE
            )

            val mvConfirmSentBroadcastReceiver: BroadcastReceiver =
                object : BroadcastReceiver() {
                    override fun onReceive(mvContext: Context, mvIntent: Intent) {
                        if (resultCode == Activity.RESULT_OK) {
                            Toast.makeText(
                                mvApplicationContext, "Text Dispatched!",
                                Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                        else
                        {
                            Toast.makeText(
                               mvApplicationContext, "Dispatch Failed!", //<-- This Part Can Be Tested By Exceeding SMS Character Limit
                               Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                    }
                }
            val mvConfirmDeliveryBroadcastReceiver: BroadcastReceiver =
                object : BroadcastReceiver() {
                    override fun onReceive(mvContext: Context, mvIntent: Intent) {
                        if (resultCode == Activity.RESULT_OK) {
                            Toast.makeText(
                                mvApplicationContext, "Text Delivered!",
                                Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                        else
                        {
                            Toast.makeText(
                                mvApplicationContext, "Delivery Failed!",
                                Toast.LENGTH_SHORT
                            ).show()
                            mvApplicationContext.unregisterReceiver(this) //<-- Otherwise, We'll Keep Displaying Previous Successes/Failures On Subsequent Ones
                        }
                    }
                }

            val mvSentIntentFilter = IntentFilter("SMS SENT")
            val mvDeliveredIntentFilter = IntentFilter("SMS DELIVERED")
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                mvApplicationContext.registerReceiver(
                    mvConfirmSentBroadcastReceiver,
                    mvSentIntentFilter,
                    Context.RECEIVER_EXPORTED
                )
                mvApplicationContext.registerReceiver(
                    mvConfirmDeliveryBroadcastReceiver,
                    mvDeliveredIntentFilter,
                    Context.RECEIVER_EXPORTED
                )
            } else {
                mvApplicationContext.registerReceiver(
                    mvConfirmSentBroadcastReceiver,
                    mvSentIntentFilter
                )
                mvApplicationContext.registerReceiver(
                    mvConfirmDeliveryBroadcastReceiver,
                    mvDeliveredIntentFilter
                )
            }


            mvSmsManager.sendTextMessage(
                mvNumber.filter { it.isDigit() },
                null,
                mvText,
                mvSentIntent,
                mvDelvieredIntent
            )

            //Confirm With Toast
                Toast.makeText(
                    mvApplicationContext, "Please stand by!",
                    Toast.LENGTH_SHORT
                ).show()

            return true

        } catch (mvEx: Exception) {
            Toast.makeText(
                mvApplicationContext, "Please try again!", //<-- This Part Can Be Tested With "Airplane Mode"
                Toast.LENGTH_LONG
            ).show()
            mvEx.printStackTrace()
            return false
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文