android dev day8

来源:互联网 发布:熙然 内地网络男歌手 编辑:程序博客网 时间:2024/06/07 08:52
短信相关权限<!--  发送消息--><uses-permission android:name="android.permission.SEND_SMS"/><!--  阅读消息--><uses-permission android:name="android.permission.READ_SMS"/><!--  写入消息--><uses-permission android:name="android.permission.WRITE_SMS" /><!-- 接收消息 --><uses-permission android:name="android.permission.RECEIVE_SMS" />系统的短信库存在data/data/com.android.providers.telephony/databases/mmssms.db  但真机不可读URI:content://mms-sms/conversations  相关重要列thread_id :这个字段很重要,同一个会话中他们的thread_id是一样的,也就是说通过thread_id就可以知道A与B在聊天 还是 A与C在聊天date :这条消息发送或接收的时间read:  0 表示未读 1表示已读type : 1表示接收 2 表示发出body  表示 消息的内容//////////////////////////////////////////////////////////////////////**发送与接收的广播**/  String SENT_SMS_ACTION = "SENT_SMS_ACTION";  String DELIVERED_SMS_ACTION = "DELIVERED_SMS_ACTION";  //注册两个用于监控短信情况的广播public void registerSmsReceiver(){// 注册广播 发送消息      registerReceiver(sendMessage, new IntentFilter(SENT_SMS_ACTION));      registerReceiver(receiver, new IntentFilter(DELIVERED_SMS_ACTION));  }public void unRegisterSmsReceiver(){// 注销广播 发送消息      unregisterReceiver(sendMessage);      unregisterReceiver(receiver);  }private BroadcastReceiver sendMessage = new BroadcastReceiver() {  @Override  public void onReceive(Context context, Intent intent) {  //判断短信是否发送成功  switch (getResultCode()) {  case Activity.RESULT_OK:  Toast.makeText(context, "短信发送成功", Toast.LENGTH_SHORT).show();  break;  default:  Toast.makeText(mContext, "发送失败", Toast.LENGTH_LONG).show();  break;  }  } }; private BroadcastReceiver receiver = new BroadcastReceiver() {  @Override  public void onReceive(Context context, Intent intent) {  //表示对方成功收到短信  Toast.makeText(mContext, "对方接收成功",Toast.LENGTH_LONG).show();  }};    /**  * 参数说明  * destinationAddress:收信人的手机号码  * scAddress:发信人的手机号码   * text:发送信息的内容   * sentIntent:发送是否成功的回执,用于监听短信是否发送成功。  * DeliveryIntent:接收是否成功的回执,用于监听短信对方是否接收成功。  */  private void sendSMS(String phoneNumber, String message) {  // ---sends an SMS message to another device---  // 获得短信管理器SmsManager sms = SmsManager.getDefault();  // create the sentIntent parameter  // 监控短信是否发送成功的Action和PendingIntentIntent sentIntent = new Intent(SENT_SMS_ACTION);  PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, sentIntent,  0);  // create the deilverIntent parameter  // 监控对方是否收到短信的Action和PendingIntentIntent deliverIntent = new Intent(DELIVERED_SMS_ACTION);  PendingIntent deliverPI = PendingIntent.getBroadcast(this, 0,  deliverIntent, 0);  //如果短信内容超过70个字符 将这条短信拆成多条短信发送出去  if (message.length() > 70) {  ArrayList<String> msgs = sms.divideMessage(message);  for (String msg : msgs) {  sms.sendTextMessage(phoneNumber, null, msg, sentPI, deliverPI);  }  } else {  sms.sendTextMessage(phoneNumber, null, message, sentPI, deliverPI);  }  } //发送指定的短信,并保存public void saveSms(String saveNumber, String saveText){/** 拿到输入的手机号码 **/String number = saveNumber;/** 拿到输入的短信内容 **/String text = saveText;/** 手机号码 与输入内容 必需不为空 **/if (!TextUtils.isEmpty(number) && !TextUtils.isEmpty(text)) {//发送短信sendSMS(number, text);/**将发送的短信插入数据库**/ContentValues values = new ContentValues();//发送时间values.put("date", System.currentTimeMillis());//阅读状态values.put("read", 0);//1为收 2为发values.put("type", 2);//送达号码values.put("address", number);//送达内容values.put("body", text);//插入短信库getContentResolver().insert(Uri.parse("content://sms"),values);}}///////////////////////////////////////////////////////////////////////判断短信是否发送成功,完整的状态case Activity.RESULT_OK:                    message = "Message sent!";                    error = false;                    break;                case SmsManager.RESULT_ERROR_GENERIC_FAILURE:                    message = "Error.";                    break;                case SmsManager.RESULT_ERROR_NO_SERVICE:                    message = "Error: No service.";                    break;                case SmsManager.RESULT_ERROR_NULL_PDU:                    message = "Error: Null PDU.";                    break;                case SmsManager.RESULT_ERROR_RADIO_OFF:                    message = "Error: Radio off.";                    break;//另一个将短信写入发件箱的方法ContentValues cv = new ContentValues();        cv.put("address", destinationAddress);        cv.put("person", "");        cv.put("protocol", "0");        cv.put("read", "1");        cv.put("status", "-1");        cv.put("body", text);        this.getContentResolver().insert(Uri.parse("content://sms/sent"), cv);        Log.e("sms", "短信已经保存");SMS不能直接访问数据库,只能通过协议来访问数据,相关的协议:       content://sms/inbox        收件箱content://sms/sent        已发送content://sms/draft        草稿content://sms/outbox        发件箱content://sms/failed        发送失败content://sms/queued        待发送列表在模拟器上Outbox可能没有数据。数据库中sms相关的字段如下:   _id               一个自增字段,从1开始thread_id    序号,同一发信人的id相同address      发件人手机号码person        联系人列表里的序号,陌生人为null(不一定有联系人就有值)date            发件日期protocol      协议,分为: 0 SMS_RPOTO, 1 MMS_PROTO read           是否阅读 0未读, 1已读 status         状态 -1接收,0 complete, 64 pending, 128 failedtype    ALL    = 0;    INBOX  = 1;    SENT   = 2;    DRAFT  = 3;    OUTBOX = 4;    FAILED = 5;    QUEUED = 6;body                     短信内容service_center     短信服务中心号码编号subject                  短信的主题reply_path_present     TP-Reply-Pathlocked是否加锁/////////////////////////////////////////////////////////////////////android的源代码,sms支持的协议有:sURLMatcher.addURI("sms", null, SMS_ALL);sURLMatcher.addURI("sms", "#", SMS_ALL_ID);sURLMatcher.addURI("sms", "inbox", SMS_INBOX);sURLMatcher.addURI("sms", "inbox/#", SMS_INBOX_ID);sURLMatcher.addURI("sms", "sent", SMS_SENT);sURLMatcher.addURI("sms", "sent/#", SMS_SENT_ID);sURLMatcher.addURI("sms", "draft", SMS_DRAFT);sURLMatcher.addURI("sms", "draft/#", SMS_DRAFT_ID);sURLMatcher.addURI("sms", "outbox", SMS_OUTBOX);sURLMatcher.addURI("sms", "outbox/#", SMS_OUTBOX_ID);sURLMatcher.addURI("sms", "undelivered", SMS_UNDELIVERED);sURLMatcher.addURI("sms", "failed", SMS_FAILED);sURLMatcher.addURI("sms", "failed/#", SMS_FAILED_ID);sURLMatcher.addURI("sms", "queued", SMS_QUEUED);sURLMatcher.addURI("sms", "conversations", SMS_CONVERSATIONS);sURLMatcher.addURI("sms", "conversations/*", SMS_CONVERSATIONS_ID);sURLMatcher.addURI("sms", "raw", SMS_RAW_MESSAGE);sURLMatcher.addURI("sms", "attachments", SMS_ATTACHMENT);sURLMatcher.addURI("sms", "attachments/#", SMS_ATTACHMENT_ID);sURLMatcher.addURI("sms", "threadID", SMS_NEW_THREAD_ID);sURLMatcher.addURI("sms", "threadID/*", SMS_QUERY_THREAD_ID);sURLMatcher.addURI("sms", "status/#", SMS_STATUS_ID);sURLMatcher.addURI("sms", "sr_pending", SMS_STATUS_PENDING);sURLMatcher.addURI("sms", "sim", SMS_ALL_SIM);sURLMatcher.addURI("sms", "sim/#", SMS_SIM);/////////////////////////////////////////////////////////////////////其中,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卡上删除数据//删除thread_id="3", _id="5"的数据//SMS_CONVERSATIONS_ID:"content://sms/conversations/3"this.getContentResolver().delete(Uri.parse("content://sms/conversations/3"), "_id=?", new String[]{"5"}); 在数据库中每个发送者的thread_id虽然一样,但不是固定的,如果把一个发送者的全部数据删除掉,然后换一个新号码发送短信时,thread_id是以数据库中最大的id+1赋值的。/////////////////////////////////////////////////////////////////////update支持的协议有很多:SMS_RAW_MESSAGE   SMS_STATUS_PENDING   SMS_ALL   SMS_FAILED   SMS_QUEUED   SMS_INBOX   SMS_SENT   SMS_DRAFT   SMS_OUTBOX   SMS_CONVERSATIONS   SMS_ALL_ID   SMS_INBOX_ID   SMS_FAILED_ID   SMS_SENT_ID   SMS_DRAFT_ID   SMS_OUTBOX_ID   SMS_CONVERSATIONS_ID   SMS_STATUS_IDSMS_INBOX_ID测试:   ContentValues cv = new ContentValues();   cv.put("thread_id", "2");   cv.put("address", "00000");   cv.put("person", "11");   cv.put("date", "11111111");   this.getContentResolver().update(Uri.parse("content://sms/inbox/4"), cv, null, null);    可以更新thread_id(但有可能混乱)/////////////////////////////////////////////////////////////////////insert支持的协议:SMS_ALL   SMS_INBOX   SMS_FAILED   SMS_QUEUED   SMS_SENT   SMS_DRAFT   SMS_OUTBOX   SMS_RAW_MESSAGE   SMS_STATUS_PENDING   SMS_ATTACHMENT   SMS_NEW_THREAD_ID 向sms表插入数据时,type是根据协议来自动设置,   如果传入的数据中没有设置date时,自动设置为当前系统时间;非SMS_INBOX协议时,read标志设置为1   SMS_INBOX协议时,系统会自动查询并设置PERSON   threadId为null或者0时,系统也会自动设置   一直为造不了"发送失败"的邮件而发愁,现在来做一个:   content://sms/failed ContentValues cv = new ContentValues();   cv.put("_id", "99");   cv.put("thread_id", "0");   cv.put("address", "9999");   cv.put("person", "888");   cv.put("date", "9999");cv.put("protocol", "0");cv.put("read", "1");cv.put("status", "-1");//cv.put("type", "0");cv.put("body", "短信内容");this.getContentResolver().insert(Uri.parse("content://sms/failed"), cv);//插入短信是否设置了检验?type    ALL    = 0;    INBOX  = 1;    SENT   = 2;    DRAFT  = 3;    OUTBOX = 4;    FAILED = 5;    QUEUED = 6;type是否被设置成了5?///////////////////////////////////////////////////////////////////////////////////希望读取彩信的同学,请参考这里尊重别人的劳动:http://www.cnblogs.com/lycoris/archive/2011/04/27/2030714.html代码主要实现一个读取彩信列表的功能,原本功能是点击某条彩信记录,显示相关包括文本、图片(该处并没有对音频附件处理)等,该处就把他们整合到一起了。public class SmsPage extends ListActivity{        private final String TAG="SmsPage";         private final Uri CONTENT_URI = Uri.parse("content://mms/inbox"); //查询彩信收件箱        private final Uri CONTENT_URI_PART = Uri.parse("content://mms/part"); //彩信附件表        public void onCreate(Bundle savedInstanceState){        super.onCreate(savedInstanceState);        setContentView(R.layout.smslist);            Cursor cursor = getContentResolver().query(CONTENT_URI, null, null,null, null);        if(cursor.getCount()>0){            MyAdapter adapter = new MyAdapter(this,R.layout.smsitem,cursor,new String[]{},new int[]{});            setListAdapter(adapter);        }    }        public class MyAdapter extends SimpleCursorAdapter{        private String name="";        public MyAdapter(Context context, int layout, Cursor c, String[] from,                int[] to) {            super(context, layout, c, from, to);        }                @Override        public void bindView(View view, Context context, Cursor cursor) {            TextView address = (TextView)view.findViewById(R.id.sms_address);            TextView body = (TextView)view.findViewById(R.id.sms_body);            TextView date = (TextView)view.findViewById(R.id.sms_date);            TextView sub = (TextView)view.findViewById(R.id.sms_sub);            ImageView image = (ImageView)view.findViewById(R.id.sms_image);            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            Date time=new Date(cursor.getLong(cursor.getColumnIndex("date"))*1000);//彩信时间            int id = cursor.getInt(cursor.getColumnIndex("_id"));//彩信Id            String subject = cursor.getString(cursor.getColumnIndex("sub"));//彩信主题            Cursor cAdd =null;            Cursor cPhones=null;            Cursor cPeople=null;            Cursor cPart=null;            try {                //根据彩信id从addr表中查出发送人电话号码,其中外键msg_id映射pdu表的id;                String selectionAdd = new String("msg_id=" + id + ");                Uri uriAddr = Uri.parse("content://mms/" + id + "/addr");                cAdd = getContentResolver().query(uriAddr, null, selectionAdd, null, null);                                //根据addr表中的电话号码在phones表中查出PERSON_ID,外键PERSON_ID映射people表中的_id                if(cAdd.moveToFirst()){//该处会得到2条记录,第一条记录为发件人号码,第二条为本机号码                    String number= cAdd.getString(cAdd.getColumnIndex("address"));                    cPhones = getContentResolver().query(Contacts.Phones.CONTENT_URI, new String[]{Contacts.Phones.PERSON_ID},Contacts.Phones.NUMBER +"=?",new String[]{number}, null);                    if(cPhones.getCount()>0){//根据phones表中的PERSON_ID查出 people 表中联系人的名字                        while (cPhones.moveToNext()) {                            String pId = cPhones.getString(cPhones.getColumnIndex(Contacts.Phones.PERSON_ID));                            Uri uriPeo = Uri.parse(Contacts.People.CONTENT_URI+"/"+pId);                            cPeople = getContentResolver().query(uriPeo, null,null,null, null);                            if(cPeople.getCount()>0){                                String str="";                                while (cPeople.moveToNext()) {                                    if(str == ""){                                        str = cPeople.getString(cPeople.getColumnIndex(Contacts.People.DISPLAY_NAME));                                    }else{                                        str += ","+cPeople.getString(cPeople.getColumnIndex(Contacts.People.DISPLAY_NAME));                                    }                                }                                name=number+"/"+str;//如果通讯录中存在,则以 ‘电话号码/名字’ 形式显示                            }else{                                name=number;//如果是陌生人直接显示电话号码                            }                        }                    }else{                        name=number;//如果是陌生人直接显示电话号码                    }                    }                                //根据彩信ID查询彩信的附件                String selectionPart = new String("mid="+id);//part表中的mid外键为pdu表中的_id                cPart = getContentResolver().query(CONTENT_URI_PART, null,selectionPart,null, null);                            String bodyStr="";                String[] coloumns = null;                 String[] values = null;                 while(cPart.moveToNext()){                     coloumns = cPart.getColumnNames();                     if(values == null)                         values = new String[coloumns.length];                     for(int i=0; i< cPart.getColumnCount(); i++){                         values[i] = cPart.getString(i);                     }                     if(values[3].equals("image/jpeg") || values[3].equals("image/bmp") || values[3].equals("image/gif") || values[3].equals("image/jpg") || values[3].equals("image/png")){  //判断附件类型                        image.setImageBitmap(getMmsImage(values[0]);//该处只会显示一张图片,如果有需求的朋友可以根据自己的需求将ImageView换成Gallery,修改一下方法                        image.setVisibility(View.VISIBLE);                    }else if(values[3].equals("text/plain")){                        /**该处详细描述一下                        *发现一个版本问题,之前用的2.1版本的多台手机测试通过,结果用1.6的G2报异常                        *经过调试发现,1.6版本part表中根本就没有"text"列,也就是values[13],所以就                        *报错了,好像在1.6版本(我只测过G2,嘿嘿),就算是文本信息也是以一个附件形                        *式存在_date里面也就是values[12]里面,与图片类似,但在2.1里面却不是这样存                        *的,文本信息被存在了"text"这个字段中,且"_date"为null*/                        if(values[12]!=null){//所以该处需判断一下,如果_date为null,可直接设置内容为"text"                            bodyStr=getMmsText(values[0]);                        }else{                            bodyStr = values[13];                        }                    }                }                if(!"".equals(subject) && subject != null){                    try {                        sub.setText(new String(subject.getBytes("iso-8859-1"),"UTF-8"));//设置彩信主题的编码格式                    } catch (UnsupportedEncodingException e) {                        e.printStackTrace();                    }                }                if(!"".equals(bodyStr)){                    body.setText(bodyStr);                }                address.setText(name);                 date.setText(format.format(time));            } catch (RuntimeException e) {                Log.e(TAG, e.getMessage());            }finally{                if(cAdd != null){                    cAdd.close();                }                if(cPart != null){                    cPart.close();                }                if(cPeople != null){                    cPeople.close();                }                if(cPhones != null){                    cPhones.close();                }            }            super.bindView(view, context, cursor);        }    }    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){                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8"));                String temp = reader.readLine();                while (temp != null) {                    sb.append(temp);                    temp=reader.readLine();//在网上看到很多把InputStream转成string的文章,没有这关键的一句,几乎千遍一律的复制粘贴,该处如果不加上这句的话是会内存溢出的                }            }        }catch (IOException e) {             e.printStackTrace();              Log.v(TAG, "读取附件异常"+e.getMessage());        }finally{             if (is != null){                 try {                     is.close();                 }catch (IOException e){                    Log.v(TAG, "读取附件异常"+e.getMessage());                }            }         }        return sb.toString();    }    private Bitmap getMmsImage(String _id){ //读取图片附件        Uri partURI = Uri.parse("content://mms/part/" + _id );         //ByteArrayOutputStream baos = new ByteArrayOutputStream();         InputStream is = null;         Bitmap bitmap=null;        try {             is = getContentResolver().openInputStream(partURI);             //byte[] buffer = new byte[256];              //int len = -1;            //while ((len = is.read(buffer)) != -1) {            //    baos.write(buffer, 0, len);            //}            //bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0, baos.toByteArray().length);           bitmap = BitmapFactory.decodeStream(is);     }catch (IOException e) {             e.printStackTrace();              Log.v(TAG, "读取图片异常"+e.getMessage());        }finally{             if (is != null){                 try {                     is.close();                 }catch (IOException e){                    Log.v(TAG, "读取图片异常"+e.getMessage());                }            }         }        return bitmap;    }}/////////////////////////////////////////////////////////////////////////////////////扩展参考http://labs.ywlx.net/?p=899http://www.cnblogs.com/not-code/archive/2011/12/01/2270903.htmlhttp://www.cnblogs.com/not-code/archive/2011/11/27/2265287.html///////////////////////////////////////////////////////////////////////////////////
原创粉丝点击