如何在Android中读取彩信数据?

2024-03-03

我想读取彩信数据 我已经在中看到了零件表mmssms.db彩信条目的存储位置;我正在使用光标,我想知道合适的URI;我正在使用“content://mms-sms/conversations”并且列名称图像的“地址”(发送至)、“文本”或“主题”和“数据”列名称。

我看过的架构mmssms.db及其零件表的列。


找到这方面的文档有点困难,所以我将在这里收集我找到的所有信息。如果您很着急或只是不喜欢阅读,请跳至如何从短信中获取数据部分。

内容://mms-sms/对话

这是 URI彩信和短信提供商 http://android.git.kernel.org/?p=platform/packages/providers/TelephonyProvider.git;a=blob;f=src/com/android/providers/telephony/MmsSmsProvider.java;h=e379c454ee203cb02aee59737b58bea24ac405cf;hb=HEAD...这允许我们同时查询 MMS 和 SMS 数据库,并将它们混合在一个线程中(称为对话).

为什么 URI 很重要?嗯,这是获取彩信和短信的标准方式;例如,当您收到短信并点击通知栏时,它会发送如下广播意图:content://mms-sms/conversations/XXX, where XXX是对话的 id。

获取所有对话的列表

您唯一要做的就是查询content://mms-sms/conversations Uri:

ContentResolver contentResolver = getContentResolver();
final String[] projection = new String[]{"*"};
Uri uri = Uri.parse("content://mms-sms/conversations/");
Cursor query = contentResolver.query(uri, projection, null, null, null);

Note:通常,当你打电话时query并想要返回所有可以传递的列null as the projection范围。但是,您无法通过此提供程序执行此操作,因此这就是我使用的原因*.

现在您可以循环遍历Cursor照常。这些是您想要使用的更重要的列:

  • _id是消息的 ID。队长明显要来救援吗?并不真地。此 ID 可用于检索详细信息,使用content://sms or content://mms.
  • date无需解释。
  • thread_id是对话的ID
  • body此对话的最后一条短信的内容。如果是彩信,即使有文本部分,这也会是null.

Note:如果你查询content://mms-sms/conversations它将返回不同对话的列表,其_id是每次对话中的最后一条短信或彩信。如果您查询content://mms-sms/conversations/xxx它将返回 ID 为 的对话中的每条短信和/或彩信xxx.

如何区分短信和彩信

通常,您会想知道您正在处理哪种类型的消息。文档说:

虚拟专栏,MmsSms.TYPE_DISCRIMINATOR_COLUMN, 可能 在预测中要求 询问。它的值是“mms”或 “短信”,取决于是否 该行代表的消息是 彩信或短信, 分别。

我认为它指的是...但是我没能让它发挥作用。如果您有,请告诉我如何或编辑这篇文章。

到目前为止,这就是我所做的,它似乎有效,但必须有更好的方法:

ContentResolver contentResolver = getContentResolver();
final String[] projection = new String[]{"_id", "ct_t"};
Uri uri = Uri.parse("content://mms-sms/conversations/");
Cursor query = contentResolver.query(uri, projection, null, null, null);
if (query.moveToFirst()) {
    do {
        String string = query.getString(query.getColumnIndex("ct_t"));
        if ("application/vnd.wap.multipart.related".equals(string)) {
            // it's MMS
        } else {
            // it's SMS
        }
    } while (query.moveToNext());
}

如何从短信中获取数据

现在你已经有了短信的ID,那么你唯一要做的就是:

String selection = "_id = "+id;
Uri uri = Uri.parse("content://sms");
Cursor cursor = contentResolver.query(uri, null, selection, null, null);
String phone = cursor.getString(cursor.getColumnIndex("address"));
int type = cursor.getInt(cursor.getColumnIndex("type"));// 2 = sent, etc.
String date = cursor.getString(cursor.getColumnIndex("date"));
String body = cursor.getString(cursor.getColumnIndex("body"));

如何从彩信数据中获取数据?

彩信有点不同。它们可以由不同的部分(文本、音频、图像等)构建;所以这里将看看如何分别检索每种数据。

所以我们假设彩信 ID 位于mmsId多变的。我们可以通过使用以下方式获取有关此彩信的详细信息content://mms/提供者:

Uri uri = Uri.parse("content://mms/");
String selection = "_id = " + mmsId;
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);

然而,唯一有趣的专栏是read这是1如果该消息已被阅读。

如何从彩信中获取文本内容

这里我们必须使用content://mms/part... 例如:

String selectionPart = "mid=" + mmsId;
Uri uri = Uri.parse("content://mms/part");
Cursor cursor = getContentResolver().query(uri, null,
    selectionPart, null, null);
if (cursor.moveToFirst()) {
    do {
        String partId = cursor.getString(cursor.getColumnIndex("_id"));
        String type = cursor.getString(cursor.getColumnIndex("ct"));
        if ("text/plain".equals(type)) {
            String data = cursor.getString(cursor.getColumnIndex("_data"));
            String body;
            if (data != null) {
                // implementation of this method below
                body = getMmsText(partId);
            } else {
                body = cursor.getString(cursor.getColumnIndex("text"));
            }
        }
    } while (cursor.moveToNext());
}

它可以包含文本的不同部分……但通常只有一个部分。因此,如果你想删除循环,它在大多数情况下都会起作用。这就是如何getMmsText方法如下:

private String getMmsText(String id) {
    Uri partURI = Uri.parse("content://mms/part/" + id);
    InputStream is = null;
    StringBuilder sb = new StringBuilder();
    try {
        is = getContentResolver().openInputStream(partURI);
        if (is != null) {
            InputStreamReader isr = new InputStreamReader(is, "UTF-8");
            BufferedReader reader = new BufferedReader(isr);
            String temp = reader.readLine();
            while (temp != null) {
                sb.append(temp);
                temp = reader.readLine();
            }
        }
    } catch (IOException e) {}
    finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {}
        }
    }
    return sb.toString();
}

如何从彩信中获取图像

这与获取文本部分相同...唯一的区别是您将寻找不同的 mime 类型:

String selectionPart = "mid=" + mmsId;
Uri uri = Uri.parse("content://mms/part");
Cursor cPart = getContentResolver().query(uri, null,
    selectionPart, null, null);
if (cPart.moveToFirst()) {
    do {
        String partId = cPart.getString(cPart.getColumnIndex("_id"));
        String type = cPart.getString(cPart.getColumnIndex("ct"));
        if ("image/jpeg".equals(type) || "image/bmp".equals(type) ||
                "image/gif".equals(type) || "image/jpg".equals(type) ||
                "image/png".equals(type)) {
            Bitmap bitmap = getMmsImage(partId);
        }
    } while (cPart.moveToNext());
}

这就是如何getMmsImage方法如下:

private Bitmap getMmsImage(String _id) {
    Uri partURI = Uri.parse("content://mms/part/" + _id);
    InputStream is = null;
    Bitmap bitmap = null;
    try {
        is = getContentResolver().openInputStream(partURI);
        bitmap = BitmapFactory.decodeStream(is);
    } catch (IOException e) {}
    finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {}
        }
    }
    return bitmap;
}

如何获取发件人地址

您将需要使用content://mms/xxx/addr提供者,在哪里xxx是彩信的 ID:

private String getAddressNumber(int id) {
    String selectionAdd = new String("msg_id=" + id);
    String uriStr = MessageFormat.format("content://mms/{0}/addr", id);
    Uri uriAddress = Uri.parse(uriStr);
    Cursor cAdd = getContentResolver().query(uriAddress, null,
        selectionAdd, null, null);
    String name = null;
    if (cAdd.moveToFirst()) {
        do {
            String number = cAdd.getString(cAdd.getColumnIndex("address"));
            if (number != null) {
                try {
                    Long.parseLong(number.replace("-", ""));
                    name = number;
                } catch (NumberFormatException nfe) {
                    if (name == null) {
                        name = number;
                    }
                }
            }
        } while (cAdd.moveToNext());
    }
    if (cAdd != null) {
        cAdd.close();
    }
    return name;
}

最后的想法

  • 无法理解为什么 Google 花费了数千万美元,却不付钱给学生或其他人来记录这个 API。您必须检查源代码才能知道它是如何工作的,更糟糕​​的是,他们没有公开数据库列中使用的那些常量,因此我们必须手动编写它们。
  • 对于彩信中的其他类型的数据,您可以应用上面学到的相同想法......这只是了解 mime 类型的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Android中读取彩信数据? 的相关文章

随机推荐

  • 使用 PHPUnit 测试 PHP 标头

    我正在尝试使用 PHPunit 来测试输出一些自定义标头的类 问题是在我的机器上
  • Android Studio:根据构建类型切换 URL? (用于调试/发布中的测试)

    我一直在阅读一些有关变体和构建类型的内容 我不知道我是否理解正确 但我想存储一个用于 locahost 测试 的 URL 和一个用于生产的 URL 互联网上的实时站点 我需要根据哪种构建类型来切换它们 这是正确的方法吗 或者还有其他选择吗
  • Swift switch 语句中使用 `let` 时出现编译错误

    在 Swift 中 您可以使用范围运算符获取数组的切片 如下所示 let list String first middle last let cdr list 1 list endIndex assert cdr middle last 我
  • 如何从 JSON 对象流中获取第一个元素?

    Example name bar thing true new key 0 name baz thing false new key 0 如果我跑 name我得到的输出为 bar baz 我想要的只是bar 您可以使用first 1 htt
  • 带有文档的 Maven 发布

    我正在尝试将文档包含到 Maven 发布中 该出版物本身运作良好 我还可以使用以下设置将源和 javadoc 发布到 gitlab 包 我可以下载并打开包含这些类的注释 文档的javadoc jar 和sources jar 然而 当我将该
  • 如何使用 FXML 在 JavaFX 中动态创建选项卡?

    如何使用 JavaFX FXML 创建新选项卡 我已经在 FXML 中创建了一个选项卡 但我想单击一个按钮来显示一个新选项卡 这是我的 FXML
  • MySQL如何更改innodb日志文件大小

    根据mysql文档 Docs http dev mysql com doc refman 5 5 en innodb data log reconfiguration html 为了在步骤 4中更改innodb log file size
  • 一个普通的类可以实现多个接口吗?

    我知道接口之间的多重继承是可能的 例如 public interface C extends A B Where A B and C are Interfaces 但是是否可以让一个常规类继承多个接口 如下所示 public class A
  • 有什么方法可以区分未设置的属性和设置为未定义的属性吗? [复制]

    这个问题在这里已经有答案了 说我有对象testObject a undefined 如果我那么console log testObject a 我变得不确定 但如果我也会发生同样的情况console log testObject b 它不存
  • Excel - 多列求和

    如果同一行中的其他单元格符合预定义的条件 我需要对几列的值求和 仅 3 列的工作公式如下 SUM SUMIFS Sheet1 W W Sheet1 B B Sales Sheet1 C C gt 4 SUMIFS Sheet1 X X Sh
  • Plupload - 仅限一个文件

    我在 plupload API 文档中没有看到有关将上传文件数量限制为任意数量 甚至是 1 的选项 博士失败了 或功能失败 如果它不存在 如果有人需要它 我会努力实现这一点 这是一个功能失败 我围绕 jQuery API 做了一个包装器 这
  • GNU Awk 4.2 中 FS = " " 的行为是什么?

    The first week of October Arnold Robbins announced Beta release of gawk 4 2 0 now available in the GNU announce bug gawk
  • Rails,如何在绝对最低级别访问原始请求数据?

    铁轨什么时候出request请求生命周期中最早可用的对象 本质上 请求何时首次作为请求对象可用 以及在哪个对象中 ActionDispatch 您可以从以下位置访问请求参数吗Tester Application 如果是这样 怎么办 如果没有
  • 在 docker 容器中导入 keycloak 的领域配置时出错

    我通过以下命令在 docker 上部署了 keycloak docker run e KEYCLOAK ADMIN admin e KEYCLOAK ADMIN PASSWORD admin p 8080 8080 quay io keyc
  • ReferenceError:Rx 未定义

    我刚刚开始学习 Angular2 我正在尝试使用 Angular2 做 RxJ 示例 如果有人帮助我 我将不胜感激 RxJs 代码 var obs Rx Observable interval 500 take 5 do i gt cons
  • Linq 到对象

    我有两个来自不同服务器的数据库 我无法链接数据库 从数据库中检索数据如下 DB1 Client ID Engagement ID 启用说明 600 10 真实公司1 600 20 虚假公司2 700 10 真实公司3 DB2 Client
  • Fortran 95 数组中具有一维变量的二维数组

    我想在代码中将一些内容存储在二维数组中 然后想扫描该数组 有N 1 行 第一个索引的数量 比如说i 在数组中 然而 对于给定值i 数量j尽管我知道最大可能值 但值不是固定的j 说它是N 2 我当然可以创建大小的数组 N 1 N 2 来存储我
  • IIS会回收asp.net core进程吗?

    我需要在我的 asp net core 应用程序中运行长时间运行的后台任务 我了解 Azure Webjobs 和其他进程外技术 但我宁愿保持解决方案简单并直接在 asp net core 进程中运行这些任务 我使用 Kestrel 该应用
  • 使 VSCodium 的 python 代码突出显示等于 VSCode

    因为 微软不好 而从 VSCode 迁移到 VSCodium 发展python应用程序似乎缺少一些代码颜色 例如 Dark 主题中绿松石色的模块或浅蓝色的局部变量 在下面的比较中可见 Left VSCodium Right VSCode 正
  • 如何在Android中读取彩信数据?

    我想读取彩信数据 我已经在中看到了零件表mmssms db彩信条目的存储位置 我正在使用光标 我想知道合适的URI 我正在使用 content mms sms conversations 并且列名称图像的 地址 发送至 文本 或 主题 和