很难找到这方面的文档,所以我将在这里收集我找到的所有信息。如果您赶时间或只是不喜欢阅读,请跳至如何从 SMS 中获取数据部分。
content://mms-sms/conversations
这是 Mms and SMS provider... 的 URI,它允许我们同时查询 MMS 和 SMS 数据库,并将它们混合在一个线程中(称为 conversations) .
为什么 URI 很重要?嗯,这是获取 MMS 和 SMS 消息的标准方式;例如,当您收到一条短信并单击通知栏时,它会发送一个广播意图,如下所示:content://mms-sms/conversations/XXX,其中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);
注意: 通常,当您调用query 并希望返回所有列时,您可以将null 作为projection 参数传递。但是,您不能使用此提供程序执行此操作,所以这就是我使用 * 的原因。
现在您可以像往常一样循环访问Cursor。这些是您想要使用的更重要的列:
-
_id 是消息的 ID。 船长显然是要救援的? 不是真的。此 ID 可用于使用content://sms 或content://mms 检索详细信息。
-
date 无需解释。
-
thread_id 是对话的 ID
-
body此对话的最后一条短信内容。如果是彩信,即使有文字部分,也是null。
注意:如果您查询content://mms-sms/conversations,它将返回一个不同对话的列表,其中_id 是每个对话中的最后一条短信或彩信。如果您查询content://mms-sms/conversations/xxx,它将返回ID 为xxx 的对话中的每条短信和/或彩信。
如何区分短信和彩信
通常,您会想知道您正在处理哪种类型的消息。文档说:
一个虚拟列,
MmsSms.TYPE_DISCRIMINATOR_COLUMN,可能
被要求在投影中
询问。其值为“mms”或
“短信”,取决于是否
该行表示的消息是
彩信或短信,
分别。
我认为它指的是this variable...但是我无法让它工作。如果你有请告诉我如何或编辑这篇文章。
到目前为止,这是我所做的,它似乎有效,但必须有更好的方法:
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());
}
如何从 SMS 中获取数据
所以你有了短信的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"));
如何从彩信数据中获取数据?
彩信有点不同。它们可以用不同的部分(文本、音频、图像等)构建;所以这里将看看如何分别检索每种数据。
假设我们在mmsId 变量中有彩信ID。我们可以使用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-type:
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。您必须检查源代码才能知道它是如何工作的,更糟糕的是,它们不会公开数据库列中使用的那些常量,因此我们必须手动编写它们。
- 对于 MMS 中的其他类型的数据,您可以应用上面学到的相同想法......这只是知道 mime 类型的问题。