android学习笔记25--------------短信的各种操作操作
2887 点击·0 回帖
![]() | ![]() | |
![]() | 1.注册广播接收器 [java] <receiver Android:name="SMSReceiver"> <intent-filter> <action Android:name="Android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> <receiver Android:name="SMSReceiver"> <intent-filter> <action Android:name="Android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> [java] import Android.content.BroadcastReceiver; import Android.content.Context; import Android.content.Intent; import Android.os.Bundle; import Android.telephony.SmsMessage; import Android.widget.Toast; public class SMSReceiver extends BroadcastReceiver { public static final String SMS_RECEIVED = "Android.provider.Telephony.SMS_RECEIVED"; @Override public void onReceive(Context context, Intent intent) { if (SMS_RECEIVED.equals(intent.getAction())) { Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); final SmsMessage[] messages = new SmsMessage[pdus.length]; String msg = ""; for (int i = 0; i < pdus.length; i++) { messages = SmsMessage.createFromPdu((byte[]) pdus); msg += messages.getMessageBody(); } Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); } } } } import Android.content.BroadcastReceiver; import Android.content.Context; import Android.content.Intent; import Android.os.Bundle; import Android.telephony.SmsMessage; import Android.widget.Toast; public class SMSReceiver extends BroadcastReceiver { public static final String SMS_RECEIVED = "Android.provider.Telephony.SMS_RECEIVED"; @Override public void onReceive(Context context, Intent intent) { if (SMS_RECEIVED.equals(intent.getAction())) { Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdus = (Object[]) bundle.get("pdus"); final SmsMessage[] messages = new SmsMessage[pdus.length]; String msg = ""; for (int i = 0; i < pdus.length; i++) { messages = SmsMessage.createFromPdu((byte[]) pdus); msg += messages.getMessageBody(); } Toast.makeText(context, msg, Toast.LENGTH_LONG).show(); } } } } 2.添加权限 [java] <uses-permission Android:name="Android.permission.RECEIVE_SMS"></uses-permission> <uses-permission Android:name="Android.permission.RECEIVE_SMS"></uses-permission> 二、读取收件箱中的短信 1.从数据库中读取,URI为"content://sms/inbox" [java] import Android.app.Activity; import Android.content.ContentResolver; import Android.database.Cursor; import Android.net.Uri; import Android.os.Bundle; import Android.widget.TextView; public class MySMSManager extends Activity { private TextView textview; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); textview = (TextView) findViewById(R.id.textview); readShortMessage(); } public void readShortMessage() { ContentResolver cr = getContentResolver(); Cursor cursor = cr.query(Uri.parse("content://sms/inbox"), null, null, null, null); String msg = ""; while(cursor.moveToNext()) { int phoneColumn = cursor.getColumnIndex("address"); int smsColumn = cursor.getColumnIndex("body"); msg += cursor.getString(phoneColumn) + ":" + cursor.getString(smsColumn) + "n"; } textview.setText(msg); } } import Android.app.Activity; import Android.content.ContentResolver; import Android.database.Cursor; import Android.net.Uri; import Android.os.Bundle; import Android.widget.TextView; public class MySMSManager extends Activity { private TextView textview; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); textview = (TextView) findViewById(R.id.textview); readShortMessage(); } public void readShortMessage() { ContentResolver cr = getContentResolver(); Cursor cursor = cr.query(Uri.parse("content://sms/inbox"), null, null, null, null); String msg = ""; while(cursor.moveToNext()) { int phoneColumn = cursor.getColumnIndex("address"); int smsColumn = cursor.getColumnIndex("body"); msg += cursor.getString(phoneColumn) + ":" + cursor.getString(smsColumn) + "n"; } textview.setText(msg); } } 2.添加权限 [java] <uses-permission Android:name="Android.permission.READ_SMS"></uses-permission> <uses-permission Android:name="Android.permission.READ_SMS"></uses-permission> 附:其它短信的URI和数据库表字段 [java] String SMS_URI_ALL = "content://sms/"; String SMS_URI_INBOX = "content://sms/inbox"; String SMS_URI_SENT = "content://sms/sent"; String SMS_URI_DRAFT = "content://sms/draft"; String SMS_URI_OUTBOX = "content://sms/outbox"; String SMS_URI_FAILED = "content://sms/failed"; String SMS_URI_QUEUED = "content://sms/queued"; String SMS_URI_ALL = "content://sms/"; String SMS_URI_INBOX = "content://sms/inbox"; String SMS_URI_SENT = "content://sms/sent"; String SMS_URI_DRAFT = "content://sms/draft"; String SMS_URI_OUTBOX = "content://sms/outbox"; String SMS_URI_FAILED = "content://sms/failed"; String SMS_URI_QUEUED = "content://sms/queued"; content://sms/inbox 收件箱 content://sms/sent 已发送 content://sms/draft 草稿 content://sms/outbox 发件箱 content://sms/failed 发送失败 content://sms/queued 待发送列表 检索数据方法很简单: Uri uri = Uri.parse("content://sms/inbox"); Cursor cur = this.managedQuery(uri, null, null, null, null); if (cur.moveToFirst()) { do { for(int j = 0; j < cur.getColumnCount(); j++) { info = "name:" + cur.getColumnName(j) + "=" + cur.getString(j); Log.i("====>", info); } }while(cur.moveToNext()); } -------------------------------------------------------------------------------- [java] /* _id => 短消息序号 如100 thread_id => 对话的序号 如100 address => 发件人地址,手机号.如+8613811810000 person => 发件人,返回一个数字就是联系人列表里的序号,陌生人为null date => 日期 long型。如1256539465022 protocol => 协议 0 SMS_RPOTO, 1 MMS_PROTO read => 是否阅读 0未读, 1已读 status => 状态 -1接收,0 complete, 64 pending, 128 failed type => 类型 1是接收到的,2是已发出 body => 短消息内容 service_center => 短信服务中心号码编号。如+8613800755500 */ /* _id => 短消息序号 如100 thread_id => 对话的序号 如100 address => 发件人地址,手机号.如+8613811810000 person => 发件人,返回一个数字就是联系人列表里的序号,陌生人为null date => 日期 long型。如1256539465022 protocol => 协议 0 SMS_RPOTO, 1 MMS_PROTO read => 是否阅读 0未读, 1已读 status => 状态 -1接收,0 complete, 64 pending, 128 failed type => 类型 1是接收到的,2是已发出 body => 短消息内容 service_center => 短信服务中心号码编号。如+8613800755500 */ 其中,delete方法中支持的协议为: SMS_ALL 根据参数中的条件删除sms表数据 SMS_ALL_ID 根据_id删除sms表数据 SMS_CONVERSATIONS_ID 根据thread_id删除sms表数据,可以带其它条件 SMS_RAW_MESSAGE 根据参数中的条件删除 raw表 SMS_STATUS_PENDING 根据参数中的条件删除 sr_pending表 SMS_SIM 从Sim卡上删除数据 试一下SMS_CONVERSATIONS_ID:"content://sms/conversations/3 ",删除thread_id="3", _id="5"的数据 在eclipse中的Emulator Control中,以13800给模拟器发送三条数据,然后以13900发送一条 this.getContentResolver().delete(Uri.parse("content://sms/conversations/3"), "_id=?", new String{"5"}); 成功删除一条数据。 在数据库中每个发送者的thread_id虽然一样,但不是固定的,如果把一个发送者的全部数据删除掉, 然后换一个新号码发送短信时,thread_id是以数据库中最大的id+1赋值的。 三、打开发送短信界面 [java] Uri uri = Uri.parse("smsto:13800138000"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); it.putExtra("sms_body", "The SMS text"); startActivity(it); Uri uri = Uri.parse("smsto:13800138000"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); it.putExtra("sms_body", "The SMS text"); startActivity(it); 四、发送短信 1.通过SmsManager的sendTextMessage(destinationAddress, scaddress, text, sentIntent, deliveryIntent)方法发送 [java] String msg ="hello"; String number = "1234565678"; SmsManager sms = SmsManager.getDefault(); PendingIntent pi = PendingIntent.getBroadcast(this,0,new Intent(),0); sms.sendTextMessage(number,null,msg,pi,null); String msg ="hello"; String number = "1234565678"; SmsManager sms = SmsManager.getDefault(); PendingIntent pi = PendingIntent.getBroadcast(this,0,new Intent(),0); sms.sendTextMessage(number,null,msg,pi,null); 2.添加权限 [java] <uses-permission Android:name="Android.permission.SEND_SMS"></uses-permission> <uses-permission Android:name="Android.permission.SEND_SMS"></uses-permission> 五、直接向数据库写短信 [java] ContentResolver cr = getContentResolver(); ContentValues cv = new ContentValues(); cv.put("address", "13800138000"); cv.put("body", "hello!"); cr.insert(Uri.parse("content://sms/inbox"), cv); ContentResolver cr = getContentResolver(); ContentValues cv = new ContentValues(); cv.put("address", "13800138000"); cv.put("body", "hello!"); cr.insert(Uri.parse("content://sms/inbox"), cv); 权限: [java] <uses-permission Android:name="Android.permission.WRITE_SMS"></uses-permission> <uses-permission Android:name="Android.permission.WRITE_SMS"></uses-permission> 六、监听短信数据库变化 使用ContentObserver ,观察"content://sms"的变化,调用重写的onChange方法,可以监听到短信记录的 变化,这样可以监听发短信,同样也是可以监听收短信的。 [java] import Android.database.ContentObserver; import Android.os.Handler; import Android.util.Log; public class SMSObserver extends ContentObserver { public SMSObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { Log.i("sms", "sms"); } } import Android.database.ContentObserver; import Android.os.Handler; import Android.util.Log; public class SMSObserver extends ContentObserver { public SMSObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange) { Log.i("sms", "sms"); } } 然后在Acitivty或Service里注册这个观察者 [java] getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SMSObserver(new Handler())); getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SMSObserver(new Handler())); Smsmessage.getTimestampMillis() 获得短信发送时间 System.currentTimeMillis()获得系统当前时间 一般短信软件都是获取当前时间 System.currentTimeMillis()改为Smsmessage.getTimestampMillis() 就能读到短信发送时间。 在做读取短信的时候,读取到date字段,需要转换成例如7/21 或者 8:21这种格式,不用手动转换 通过调用相应的类来实现 SimpleDateFormat sfd = new SimpleDateFormat("yyyy-MM-dd hh:mms");// 这里我们可以指定可是 例如 MM-DD就是只显示月和日 。。。。 Date date = new Date(Long.parseLong(cursor.getString(cursor.getColumnIndex("date"))));//从短信中获得时间 String time = sfd.format(date); //转换完成的字符串 很简单 dataTextView.setText(time); //显示出来就行了 使用前: ![]() 使用后: ![]() /** * 通过电话号码获取姓名 */ public String getContactNameFromPhoneNum(Context context, String phoneNum) { String contactName = ""; ContentResolver cr = context.getContentResolver(); Cursor pCur = cr.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.NUMBER + " = ?", new String[] { phoneNum }, null); if (pCur.moveToFirst()) { contactName = pCur .getString(pCur .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); pCur.close(); } return contactName; } /** * 通过电话号码获取姓名 */ public String getContactNameFromPhoneNum(Context context, String phoneNum) { String contactName = ""; ContentResolver cr = context.getContentResolver(); Cursor pCur = cr.query( ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.NUMBER + " = ?", new String[] { phoneNum }, null); if (pCur.moveToFirst()) { contactName = pCur .getString(pCur .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)); pCur.close(); } return contactName; } Android系统源码数据库(mmssms.db)中几个表之前的关系. 首先明了未接信息的数据库的位置在系统 /data/data/com.Android.providers.telephony/databases/mmssms.db 包下。 希望大家能够结合源码中的 1. Telephony.java (主要讲这些表里有哪些字段) 2. MmsSmsProvider.java (ContentProvider被重写) 3. MmsProvider.java (ContentProvider被重写) 4. SmsProvider.java (ContentProvider被重写) 5. Conversation.java 描述 mmssms数据库的Threads表 当我们查询mmssms.db数据库时,这其中涉及到以下几张表: 1. threads表 2. 存放短信的表(sms表) 3. 存放彩信的表(pdu表,part表) 4. 存放phone number的表( Canonical_address表) threads表字段说明: _id: 用于区分不同的电话号码,系统会为不同的电话号码分配不同的_id. date: 收到信息的时间(如果收到来自同一个phone number多条信息,并且有对于一条信息未读,那么date表示收到的最后一条信息时的时间) message_count: 收到的信息的数目(sms+mms) snippet: 如果来自某个phone number,仅仅有一条信息,那么会是如下情况 如果是未接短信,代表未接短信的内容 如果是未接彩信,代表未接彩信的subject. 如果来自某个phone number,仅仅有多条信息,那么则是如下情况 如果是最后一条是未接短信,代表最后一条未接短信的内容 如果是最后一条是未接彩信,代表最后一条未接彩信的subject. 然而这个字段存储的仅仅是一条短信内容或者彩信subject的部分内容,其余内容用省略号表示。 read: 0. 代表未读。 1.代表 已读 has_attchment: 代表来自该phone number的信息是否包含有附件。 依据上面的表结构,也许会有人问,phone number 呢?有这样的疑问是非常正常的,别着急,学过数据库的人都知道,表结构之间并不是孤立的,而是相互关联的。 phone number 会在另外几张表中出现。 Sms表 查询该表时的uri : URI_SMS_INBOX = Uri.parse("content://sms/inbox") _id thread_id address date read subject body locked Sms表字段说明 _id: 区分不同的短信。 threads_id: (外键)threads表的_id. date: 该条短信接收的时间 read: 0表未读,1表已读 body: 表示具体的短信内容,(注意,虽然在thread表的snippet字段已经存储了一部分body,但是那里的并不全,仅仅是一部分body) locked: 该字段我也不是很清楚,用到的不多,不过如果我标识某条信息为locked时,当我再删除这条信息时,系统会提示我“是否删除locked信息”。 很明显以上:_id为4.或5的短信,来自同一个phone number,也就是说他们的thread_id是相同的. Pdu表: URI_MMS_INBOX = Uri.parse("content://mms/inbox"); _id Thread_id date Msg_box read M_id sub Ct_l m_type Pdu表字段说明: _id: 区分不同的彩信 thread_id : 外键 (thread表的_id) msg_box: 区分彩信的收件箱,发件箱,草稿箱等. 很明显1.代表收件箱 read:是否已读,0 未读,1.已读 sub: 彩信的subject ct_l: 如果彩信太大,或者由于网络原因,也又是由于手机设备原因,dowload失败,彩信看不了,这个字段就会有彩信的网址(我曾经见到过一次,http://格式的,就是一个网址) | |
![]() | ![]() |