如何在Android中使用SmsManager发送具有自定义线程ID的短信?

2024-01-01

我想创建一条带有自定义线程 ID(例如“10001”)的 SMS。我怎样才能做到这一点 ?原因是因为我需要实现删除短信功能,而删除特定短信线程的唯一方法是通过线程 ID 或电话号码,而此时获取电话号码并不完全可能,因此需要定义自定义线程 ID在我发送短信时。

到目前为止,我只能获得正常的短信工作代码,如下所示:

    SmsManager smsManager = SmsManager.getDefault();
    smsManager.sendTextMessage("+1 203 514 6584", null, "HI Greg! ", null, null);

预先感谢您的帮助!


The SmsObserver类是一个ContentObserver其自身注册在content://sms/ Uri并根据收件人地址和消息正文检查 SMS 表中的更改,以检索为传出 SMS 消息分配的线程 ID。该类提供了一个接口,您的发送类需要实现该接口,以便在确定线程 ID 时接收该 ID,因为这将异步发生。

public class SmsObserver extends ContentObserver {
    private static final Handler handler = new Handler();
    private static final Uri uri = Uri.parse("content://sms/");

    private final Context context;
    private final ContentResolver resolver;
    private final String address;
    private final String body;

    public interface OnSmsSentListener {
        public void onSmsSent(int threadId);
    }

    public SmsObserver(Context context, String address, String body) {
        super(handler);

        if (context instanceof OnSmsSentListener) {
            this.context = context;
            this.resolver = context.getContentResolver();
            this.address = address;
            this.body = body;
        }
        else {
            throw new IllegalArgumentException(
                "Context must implement OnSmsSentListener interface");
        }
    }

    public void start() {
        if (resolver != null) {
            resolver.registerContentObserver(uri, true, this);
        }
        else {
            throw new IllegalStateException(
                "Current SmsObserver instance is invalid");
        }
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        Cursor cursor = null;

        try {
            cursor = resolver.query(uri, null, null, null, null);

            if (cursor != null && cursor.moveToFirst()) {
                final int type = cursor.getInt(
                    cursor.getColumnIndex(Telephony.Sms.TYPE));

                if(type == Telephony.Sms.Sent.MESSAGE_TYPE_SENT) {
                    final String address = cursor.getString(
                        cursor.getColumnIndex(Telephony.Sms.ADDRESS));
                    final String body = cursor.getString(
                        cursor.getColumnIndex(Telephony.Sms.BODY));
                    final int threadId = cursor.getInt(
                        cursor.getColumnIndex(Telephony.Sms.THREAD_ID));

                    if (PhoneNumberUtils.compare(address, this.address) &&
                        body.equals(this.body)) {

                        ((OnSmsSentListener) context).onSmsSent(threadId);
                        resolver.unregisterContentObserver(this);
                    }
                }
            }
        }
        finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}

在发送消息之前需要启动该实例,并且线程 ID 将被传递到发送类的接口方法实现中。例如,如果您从Activity单击后Button:

public class MainActivity extends Activity
    implements SmsObserver.OnSmsSentListener {
    ...

    public void onClick(View v) {
        String address = "+1 234 567 8900";
        String body = "HI Greg! ";

        new SmsObserver(this, address, body).start();

        SmsManager smsManager = SmsManager.getDefault();
        smsManager.sendTextMessage(address, null, body, null, null);
    }

    @Override
    public void onSmsSent(int threadId) {
        // Here's the thread ID.
    }
}

请注意,您将需要READ_SMS也允许。


从 Lollipop 开始就有一个可能的替代方案。发送消息的 URI 将作为附件附加到String额外的Intent来自PendingIntent作为第四个参数传递sendTextMessage()方法。额外的会有钥匙"uri",并且可以解析为Uri,然后可以在查询中使用ContentResolver检索线程 ID,如上所示。

例如,如果使用BroadcastReceiver对于结果,sendTextMessage()调用会像这样:

Intent sentIntent = ...
PendingIntent sentPi = PendingIntent.getBroadcast(context, 0, sentIntent, 0);

SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(address, null, body, sentPi, null);

在接收器中检索额外的内容将如下所示:

public class SmsResultReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        ...

        String uriString = data.getStringExtra("uri");
        Uri uri = Uri.parse(uriString);

        // Query as shown above in the ContentObserver
        ...
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Android中使用SmsManager发送具有自定义线程ID的短信? 的相关文章

随机推荐

  • 注释 Mptt 模型的下降总数

    Question 给定下面的模型 我想获取所有页面的查询集 并用与页面关联的线程中的评论总数进行注释 包括与页面关联的评论线程树中的所有评论 我在用Django mptt https django mptt readthedocs io e
  • “对私有方法的致命错误调用”但方法受到保护

    第一次在 PHP 中扩展一个类 我收到一个致命错误 提示该方法是私有的 而实际上它不是 我确信这是基本的东西 但我研究过书籍和论坛 但我无法确定我做了什么来产生这个错误 非常感谢任何帮助 详情如下 错误信息 致命错误 从第 726 行 ro
  • Bootstrap v4 中的“p-N”及其变体代表什么?

    我发现 Bootstrap v4 中的命名不太直观 我知道他们希望最大限度地减少所有类使标记混乱的影响 但我无法得出合理的结论 我可以猜测 但我找不到具体的答案 p 1 p 2 p N Flexbox 相关 但是什么是p代表 d flex
  • 通过代理的 XMLDocument.Load(url)

    我有一些代码基本上使用 XMLDocument Load uri 方法读取 XML 文档 该方法运行良好 但如果通过代理进行调用 则效果不佳 我想知道是否有人知道通过代理进行此调用 或达到相同效果 的方法 这是我最终使用的代码 WebPro
  • 使用 php 绘制图表

    我需要制作图表 饼图和条形图 并使用 php 数据 数据是 JSON 编码的 生成图表的最佳方法是什么 我现在正在查看 Google Chart api 还有什么比这更好 读作 更容易 的吗 pChart http pchart sourc
  • +[NSObject初始化]内部的dispatch_once是否过度杀伤?

    如果我在其中创建一个单例 NSObject initialize 我需要将我的代码放入dispatch once像这样阻止 static NSObject Bar implementation Foo void initialize if
  • 命名管道:C# 服务器、C++ 客户端

    我编写了两对命名管道客户端 服务器程序 C NET 4 中的第一对 C 中的第二对 非托管 所有 4 个测试程序都使用相同的管道名称 pipe mypipe C 对彼此工作得很好 我从客户端发送一条消息 服务器接收该消息 C 对也可以很好地
  • 在 For 循环内使用 IF 条件检查时如何丢弃数据表中的空值

    在我的项目中 我根据数据库中的某些条件选择用户 ID 并将其保存在数据表中 并使用基于条件的用户输入的 ID 进行检查 只会获取 5 行 但在循环中和 IF 条件下 它正在检查第 6 行为空 因此它抛出异常 位置 6 处没有行 我的代码是
  • ie8 和 ie7 的 2 列 div

    我想要一行有 2 个单元格 该行和 2 个单元格必须以百分比表示 我曾尝试这样做 container width 100 display inline table sidebar1 float left width 30 mainConte
  • 如何在 Swift 中正确设置像 imageContacts 这样的圆形 imageView?

    我想在 imageView 中显示图片 就像图像联系人 在圆圈中 但是当我尝试显示它时 imageView 会重新调整其大小 并且在圆圈中无法正确显示 image layer borderWidth 1 0 image layer mask
  • 有哪些重构方法可以减少编译代码的大小?

    我有一个需要新功能的旧固件应用程序 应用程序的大小已经接近设备的有限闪存容量 而少数新功能和变量将其推向极限 打开编译器优化确实可以解决问题 但客户对此持谨慎态度 因为它们过去曾导致过失败 那么 在重构 C 代码以产生更小的输出时 需要注意
  • JOIN 或 WHERE 中的条件

    在 JOIN 子句中添加条件与在 WHERE 子句中添加条件之间是否有任何区别 性能 最佳实践等 例如 Condition in JOIN SELECT FROM dbo Customers AS CUS INNER JOIN dbo Or
  • 反应流与反应堆模式?

    我想知道反应流 由反应宣言定义 和反应器模式 https en wikipedia org wiki Reactor pattern https en wikipedia org wiki Reactor pattern 我读到 Proje
  • 从 Chrome 中打开的
    元素中删除蓝色边框?

    我正在升级我的网站以使用新的 HTML5details元素以获得更好的可访问性 一切正常 但不幸的是 当我单击打开元素时 Chrome 应用了丑陋的蓝色边框 有什么办法可以阻止 Chrome 这样做吗 我看不到任何显式的 CSS 样式被应用
  • 如何使用 apache POI 在 ms word doc 中使用 rowspan 和 colspan 创建表?

    我正在使用 APACHE POI 创建包含表的 Word 文档 表格如下所示 我想创建具有行跨度和列跨度的单元格 如图所示 可以使用 APACHE POI 吗 有没有其他java库可以实现同样的功能 任何帮助表示赞赏 你可以试试这个 pub
  • 在 Android 4.0.3 中插入​​错误 SqLite [重复]

    这个问题在这里已经有答案了 我的 Android 4 0 3v 平板电脑出现 Sqlite 问题 Error 07 28 14 28 18 495 6995 7125 com titan tablet E AndroidRuntime FA
  • 检测Python函数中的所有全局变量?

    我正在尝试分析一些混乱的代码 这些代码恰好在函数中大量使用全局变量 我正在尝试重构代码 以便函数仅使用局部变量 有没有办法检测函数内的全局变量 例如 def f x x x 1 z x y return z 这里的全局变量是y因为它不是作为
  • android活动截图如何?

    你好朋友我正在制作一个带有 webview 的应用程序 我想截取我的活动截图 目前我正在使用此代码来捕获图像 public Bitmap takeScreenshot View rootView findViewById android R
  • MySQLi 无法准备语句

    我在脚本中运行两个查询room php 两者都使用MySQLi准备好的语句 其代码如下 Get room name stmt mysqli gt prepare SELECT name FROM rooms WHERE r id stmt
  • 如何在Android中使用SmsManager发送具有自定义线程ID的短信?

    我想创建一条带有自定义线程 ID 例如 10001 的 SMS 我怎样才能做到这一点 原因是因为我需要实现删除短信功能 而删除特定短信线程的唯一方法是通过线程 ID 或电话号码 而此时获取电话号码并不完全可能 因此需要定义自定义线程 ID在