Android开发学习日记--读取通讯录联系人和获取最新短信验证码

一、读取通讯录联系人

public class ReadContacts extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_read_contacts);
        findViewById(R.id.query).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
     readContacts(getContentResolver());
    }

    @SuppressLint("Range")
    private void readContacts(ContentResolver resolver) {
        //先查询让raw_contacts表,再根据让raw_contacts_id查data表
        Cursor cursor = resolver.query(ContactsContract.RawContacts.CONTENT_URI,new String[]{ContactsContract.RawContacts._ID},
                null,null);
        while(cursor.moveToNext()){
             int rawContactId=cursor.getInt(0);
            Uri uri = Uri.parse("content://com.android.contacts/contacts/"+rawContactId+"/data");
            Cursor datacursor = resolver.query(uri,new String[]{Contacts.Data.MIMETYPE,Contacts.Data.DATA1,Contacts.Data.DATA2},
                    null,null);
            Contact contact=new Contact();
            while(datacursor.moveToNext()){
                 String data1=datacursor.getString(datacursor.getColumnIndex(Contacts.Data.DATA1));
                 String mimeType=datacursor.getString(datacursor.getColumnIndex(Contacts.Data.MIMETYPE));
                 Log.i("mimeType",mimeType);
                 switch (mimeType){
                     case CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE:
                        contact.name=data1;
                        break;
                     case CommonDataKinds.Phone.CONTENT_ITEM_TYPE:
                        contact.phone=data1;
                        break;
                     case CommonDataKinds.Email.CONTENT_ITEM_TYPE:
                        contact.email=data1;
                        break;
                 }
            }
            datacursor.close();;
            if(contact.name!=null)
                Log.i("联系人",contact.toString());
        }
        cursor.close();
    }

    class Contact{
        String name;   //姓名
        String phone;  //电话
        String email;  //邮箱

        @Override
        public String toString() {
            return "Contact{" +
                    "姓名='" + name + '\'' +
                    ", 电话='" + phone + '\'' +
                    ", 邮箱='" + email + '\'' +
                    '}';
        }
    }
}
raw_contacts 表:

 data表:

        记录了用户的通讯录所有数据,包括手机号,显示名称等,但是里面的mimetype_id表示不同的数据类型,这与表mimetypes表中的id相对应,raw_contact_id 与下面的 raw_contacts表中的 id 相对应。

 mimetypes表:

二、监听短信

        ContentResolver获取数据采用的是主动查询方式,有查询就有数据,没查询就没数据。然而有时不但 要获取以往的数据,还要实时获取新增的数据,最常见的业务场景是短信验证码。电商App 经常在用户 注册或付款时发送验证码短信,为了替用户省事,App 通常会监控手机刚收到的短信验证码,并自动填 写验证码输入框。这时就用到了内容观察器ContentObserver ,事先给目标内容注册一个观察器,目标 内容的数据一旦发生变化,就马上触发观察器的监听事件,从而执行开发者预先定义的代码。
        内容观察器的用法与内容提供器类似,也要从ContentObserver派生一个新的观察器,然后通过ContentResolver对象调用相应的方法注册或注销观察器。下面是内容解析器与内容观察器之间的交互方法说明。
  • registerContentObserver:内容解析器要注册内容观察器。
  • unregisterContentObserver:内容解析器要注销内容观察器。
  • notifyChange:通知内容观察器发生了数据变化,此时会触发观察器的onChange方法。
public class MonitorSMS extends AppCompatActivity {

    private TextView tv_text;
    private SmsGetObserver smsGetObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_monitor_sms);
        tv_text = findViewById(R.id.tv_text);
        // 给指定Uri注册内容观察器,一旦发生数据变化,就触发观察器的onChange方法
        Uri uri= Uri.parse("content://sms");
        // notifyForDescendents:
        // false :表示精确匹配,即只匹配该Uri,true :表示可以同时匹配其派生的Uri
        // 假设UriMatcher 里注册的Uri共有一下类型:
        // 1.content://AUTHORITIES/table
        // 2.content://AUTHORITIES/table/#
        // 3.content://AUTHORITIES/table/subtable
        // 假设我们当前需要观察的Uri为content://AUTHORITIES/student:
        // 如果发生数据变化的 Uri 为 3。
        // 当notifyForDescendents为false,那么该ContentObserver会监听不到,但是当notifyForDescendents 为ture,能捕捉该Uri的数据库变化。
        smsGetObserver = new SmsGetObserver(this);
        getContentResolver().registerContentObserver(uri,true, smsGetObserver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getContentResolver().unregisterContentObserver(smsGetObserver);
    }

    class SmsGetObserver extends ContentObserver{

        private final Context mContext;

        public SmsGetObserver(Context context) {
            super(new Handler(Looper.getMainLooper()));
            this.mContext=context;
        }

        @SuppressLint("Range")
        @Override
        public void onChange(boolean selfChange,Uri uri) {
            super.onChange(selfChange,uri);
            // onChange会多次调用,收到一条短信会调用两次onChange
            // mUri===content://sms/raw/20
            // mUri===content://sms/inbox/20
            // 安卓7.0以上系统,点击标记为已读,也会调用一次
            // mUri===content://sms
            // 收到一条短信都是uri后面都会有确定的一个数字,对应数据库的_id,比如上面的20
            if(uri==null)
                return;
            //因为调用三次,那么我们排除两种情况,保留'content://sms/inbox/xxx'这种情况
            if(uri.toString().contains("content://sms/raw")||
                    uri.toString().equals("content://sms"))
                return;
            // 通过内容解析器获取符合条件的结果集游标,时间戳降序获得最新的一条短信
            Cursor cursor=mContext.getContentResolver().query(uri,new String[]{"address","body","date"},
                    null,null,"date DESC");
            if(cursor.moveToNext()){
                //发送人的号码
                String sender=cursor.getString(cursor.getColumnIndex("address"));
                //短信内容
                String content=cursor.getString(cursor.getColumnIndex("body"));
                //时间戳
                String date=cursor.getString(cursor.getColumnIndex("date"));
                tv_text.setText("发送人:"+sender+"\n内容:"+content+"\ndate:"+date);
            }
            cursor.close();
        }
    }
}

         

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值