当前位置:首页 > 行业动态 > 正文

关于Android系统短信读取的疑问解答

Android读取短信需申请权限,使用ContentResolver查询Sms/Mms内容提供者。

Android短信读取

在Android应用开发中,读取短信是一项常见需求,无论是为了实现短信备份、短信过滤还是其他功能,了解如何读取短信都是非常有用的,本文将详细介绍如何在Android中读取短信。

一、权限申请

要在Android应用中读取短信,首先需要在AndroidManifest.xml文件中声明读取短信的权限:

<uses-permission android:name="android.permission.READ_SMS" />

从Android 6.0(API级别23)开始,还需要在运行时请求权限,可以在Activity中通过以下代码请求权限:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS)
        != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_SMS}, 1);
}

二、读取短信

获取短信内容主要通过ContentResolver查询短信数据库来实现,短信数据库的URI主要有以下几种:

URI 说明
content://sms/ 所有短信
content://sms/inbox 收件箱
content://sms/sent 已发送
content://sms/draft 草稿
content://sms/outbox 发件箱
content://sms/failed 发送失败
content://sms/queued 待发送列表

以下是一个简单的示例代码,用于读取所有短信并显示在TextView中:

import android.app.Activity;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.widget.ScrollView;
import android.widget.TextView;
public class SmsReadActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView tv = new TextView(this);
        tv.setText(getSmsInPhone());
        ScrollView sv = new ScrollView(this);
        sv.addView(tv);
        setContentView(sv);
    }
    public String getSmsInPhone() {
        final String SMS_URI_ALL = "content://sms/";
        StringBuilder smsBuilder = new StringBuilder();
        Uri uri = Uri.parse(SMS_URI_ALL);
        String[] projection = new String[]{"_id", "address", "person", "body", "date", "type"};
        Cursor cur = getContentResolver().query(uri, projection, null, null, "date desc");
        if (cur.moveToFirst()) {
            int index_Address = cur.getColumnIndex("address");
            int index_Person = cur.getColumnIndex("person");
            int index_Body = cur.getColumnIndex("body");
            int index_Date = cur.getColumnIndex("date");
            int index_Type = cur.getColumnIndex("type");
            do {
                String strAddress = cur.getString(index_Address);
                int intPerson = cur.getInt(index_Person);
                String strbody = cur.getString(index_Body);
                long longDate = cur.getLong(index_Date);
                int intType = cur.getInt(index_Type);
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                Date d = new Date(longDate);
                String strDate = dateFormat.format(d);
                String strType = intType == 1 ? "接收" : "发送";
                smsBuilder.append("[ ");
                smsBuilder.append(strAddress + ", ");
                smsBuilder.append(intPerson + ", ");
                smsBuilder.append(strbody + ", ");
                smsBuilder.append(strDate + ", ");
                smsBuilder.append(strType);
                smsBuilder.append(" ]
");
            } while (cur.moveToNext());
        }
        if (!cur.isClosed()) {
            cur.close();
            cur = null;
        }
        return smsBuilder.toString();
    }
}

上述代码中,getSmsInPhone方法通过ContentResolver查询短信数据库,获取所有短信的相关信息,并将其拼接成一个字符串返回,然后在onCreate方法中,将该字符串设置为TextView的文本,并通过ScrollView显示出来。

三、短信数据库字段说明

短信数据库中的字段及其含义如下:

字段名 类型 说明
_id integer 短信的唯一标识,从1开始自增
thread_id integer 同一发信人的短信ID相同
address text 发件人手机号码
person integer 联系人列表中的序号,陌生人为null
date integer 发件日期(以毫秒为单位的时间戳)
protocol integer 协议类型,如0表示SMS_RPOTO,1表示MMS_PROTO
read integer 是否已读,0表示未读,1表示已读
status integer 短信状态,如-1表示接收,0表示complete,64表示pending,128表示failed
type integer 短信类型,如1表示接收,2表示发送等
body text 短信内容
service_center text 短信服务中心号码编号,如+8613800755500
subject text 短信的主题
reply_path_present integer 是否包含回复路径,0表示不包含,1表示包含
locked integer 是否加锁,0表示未加锁,1表示加锁

四、相关问题与解答

问题1:如何只读取收件箱中的短信?

答:可以将查询URI改为content://sms/inbox,即:

final String SMS_URI_INBOX = "content://sms/inbox";
Uri uri = Uri.parse(SMS_URI_INBOX);

这样ContentResolver就会只查询收件箱中的短信。

问题2:如何根据联系人姓名读取短信?

答:可以根据联系人姓名先获取其对应的电话号码,然后根据电话号码进行查询。

String contactName = "张三"; // 联系人姓名
String phoneNumber = getPhoneNumberByContactName(contactName); // 假设这是一个自定义方法,用于根据联系人姓名获取电话号码
if (phoneNumber != null) {
    Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_FILTER_URL, Uri.encode(phoneNumber));
    Cursor cur = getContentResolver().query(uri, projection, null, null, "date desc");
    // 然后按照前面的逻辑处理Cursor即可
} else {
    // 未找到对应联系人的电话号码,可以给出相应提示或处理
}
0