关于Android系统短信读取的疑问解答
- 行业动态
- 2025-03-02
- 1
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 { // 未找到对应联系人的电话号码,可以给出相应提示或处理 }