Android开发读取通讯录信息

需求
通过搜索联系人的姓名获取相应的详细人信息,也可通过右侧字母条搜索相应的联系人信息。
主要代码如下:
MainActivity

public class MainActivity extends AppCompatActivity {
    private ListView sortListView;
    private SideLetterUtil sideLetterUtil;
    private TextView dialog;
    private SortAdapter adapter;
    private ClearEditText mClearEditText;
    private String mobile,//被授权人电话号码
            name;//被授权人姓名
    /**
     * 查询通讯录名字
     */
    private Uri contactsUrl = ContactsContract.Contacts.CONTENT_URI;
    private ContentResolver resolver;
    private List<ContactsBean> nameList;
    /**
     * 汉字转换成拼音的类
     */
    private CharacterParser characterParser;
    private List<ContactsBean> SourceDateList;

    /**
     * 根据拼音来排列ListView里面的数据类
     */
    private ContactsPinyinComparator pinyinComparator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getPersimmionInfo();
    }

    private void getPersimmionInfo() {
        if (Build.VERSION.SDK_INT >= 23) {
            //1. 检测是否添加权限   PERMISSION_GRANTED  表示已经授权并可以使用
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
                //手机为Android6.0的版本,权限未授权去i请授权
                //2. 申请请求授权权限
                //1. Activity
                // 2. 申请的权限名称
                // 3. 申请权限的 请求码
                ActivityCompat.requestPermissions(this, new String[]
                        {Manifest.permission.READ_CONTACTS//通话录
                        }, 1005);
            } else {//手机为Android6.0的版本,权限已授权可以使用
                // 执行下一步
                initContacts();
            }

        } else {//手机为Android6.0以前的版本,可以使用
            initContacts();
        }

    }

    //  重写方法    当权限申请后     执行 接收结果的作用
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // 先判断请求码 与 请求时的  是否一致
        if (requestCode == 1005) {
            //  判断请求结果长度     且  结果 为  允许访问  则 进行使用;第一次授权成功后
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 可以使用
                initContacts();
            } else {//未授权不可以使用
                // 摄像机或读写内存卡权限授权将不能使用以下功能。
                Toast.makeText(MainActivity.this, "未授权不可以使用", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void initContacts() {
        //实例化汉字转拼音类
        characterParser = CharacterParser.getInstance();
        pinyinComparator = new ContactsPinyinComparator();
        //右侧26个字母和#
        sideLetterUtil = (SideLetterUtil) findViewById(R.id.sidrbar);
        //中间显示字母
        dialog = (TextView) findViewById(R.id.dialog);
        sideLetterUtil.setTextView(dialog);
        //设置右侧触摸监听
        sideLetterUtil.setOnTouchingLetterChangedListener(new SideLetterUtil.OnTouchingLetterChangedListener() {

            @Override
            public void onTouchingLetterChanged(String s) {
                //该字母首次出现的位置
                int position = adapter.getPositionForSection(s.charAt(0));
                if (position != -1) {
                    sortListView.setSelection(position);
                }

            }
        });

        sortListView = (ListView) findViewById(R.id.lv_contacts_item);
        /**
         * 查询通讯录名字
         */
        nameList = new ArrayList<>();
        resolver = getContentResolver();
        //用于查询电话号码的URI
        Uri phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        // 查询的字段
        String[] projection = {ContactsContract.CommonDataKinds.Phone._ID,//Id
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,//通讯录姓名
                ContactsContract.CommonDataKinds.Phone.DATA1, "sort_key",//通讯录手机号
                ContactsContract.CommonDataKinds.Phone.CONTACT_ID,//通讯录Id
                ContactsContract.CommonDataKinds.Phone.PHOTO_ID,//手机号Id
                ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY};
        Cursor cursor = resolver.query(phoneUri, projection, null, null, null);
        while ((cursor.moveToNext())) {
            String name = cursor.getString(1);
            String phone = cursor.getString(2);
            nameList.add(new ContactsBean(name, phone));
        }
        SourceDateList = filledData(nameList);
        // 根据a-z进行排序源数据
        Collections.sort(SourceDateList, pinyinComparator);
        adapter = new SortAdapter(this, SourceDateList);
        sortListView.setAdapter(adapter);
        adapter.setOnCliker(new SortAdapter.OnClicker() {
            @Override
            public void onClik(String name1, String phone1) {
                //这里要利用adapter.getItem(position)来获取当前position所对应的对象
                mobile = phone1;
                if (MobileUtil.isMobileNO(mobile)) {
                    //无通讯姓名则为StrConfig.CONTACTS_NAME_NULL
                    name = (TextUtils.equals(name1, "未备注联系人"))
                            ? "null" : name1;
                    Toast.makeText(MainActivity.this,
                            name + mobile, Toast.LENGTH_SHORT).show();
                } else {
                    //该用户无手机号,或手机号格式不正确
                    Toast.makeText(MainActivity.this,
                            "该用户无手机号,或手机号格式不正确", Toast.LENGTH_SHORT).show();
                }
            }
        });
        mClearEditText = findViewById(R.id.filter_edit);
        //根据输入框输入值的改变来过滤搜索
        mClearEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                //当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表
                filterData(s.toString());
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                                          int after) {
            }

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }

    /**
     * 为ListView填充数据
     */
    private List<ContactsBean> filledData(List<ContactsBean> date) {
        List<ContactsBean> mSortList = new ArrayList<ContactsBean>();
        for (int i = 0; i < date.size(); i++) {
            ContactsBean contactsBean = new ContactsBean();
            contactsBean.setName(date.get(i).getName());
            contactsBean.setPhone(date.get(i).getPhone());
            //汉字转换成拼音
            String pinyin = characterParser.getSelling(date.get(i).getName());
            String sortString = pinyin.substring(0, 1).toUpperCase();

            // 正则表达式,判断首字母是否是英文字母
            if (sortString.matches("[A-Z]")) {
                contactsBean.setSortLetters(sortString.toUpperCase());
            } else {
                contactsBean.setSortLetters("#");
            }
            mSortList.add(contactsBean);
        }
        return mSortList;

    }

    /**
     * 根据输入框中的值来过滤数据并更新ListView
     *
     * @param filterStr
     */
    private void filterData(String filterStr) {
        List<ContactsBean> filterDateList = new ArrayList<ContactsBean>();

        if (TextUtils.isEmpty(filterStr)) {
            filterDateList = SourceDateList;
        } else {
            filterDateList.clear();
            for (ContactsBean contactsBean : SourceDateList) {
                String name = contactsBean.getName();
                if (name.indexOf(filterStr.toString()) != -1 || characterParser.getSelling(name).startsWith(filterStr.toString())) {
                    filterDateList.add(contactsBean);
                }
            }
        }
        // 根据a-z进行排序
        Collections.sort(filterDateList, pinyinComparator);
        adapter.updateListView(filterDateList);
    }
}

SortAdapter

public class SortAdapter extends BaseAdapter implements SectionIndexer {
    private List<ContactsBean> list = null;
    private Context mContext;
    private OnClicker onClicker;

    public SortAdapter(Context mContext, List<ContactsBean> list) {
        this.mContext = mContext;
        this.list = list;
    }

    /**
     * 当ListView数据发生变化时,调用此方法来更新ListView
     *
     * @param list
     */
    public void updateListView(List<ContactsBean> list) {
        this.list = list;
        notifyDataSetChanged();
    }

    public int getCount() {
        return this.list.size();
    }

    public Object getItem(int position) {
        return list.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View view, ViewGroup arg2) {
        ViewHolder viewHolder = null;
        final ContactsBean mContent = list.get(position);
        if (view == null) {
            viewHolder = new ViewHolder();
            view = LayoutInflater.from(mContext).inflate(R.layout.contacts_item, null);
            viewHolder.rlContacts = view.findViewById(R.id.rl_contacts);
            viewHolder.tvTitle = view.findViewById(R.id.tv_contacts_item_title);
            viewHolder.tvLetter = view.findViewById(R.id.tv_contacts_item_catalog);
            view.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) view.getTag();
        }
        //根据position获取分类的首字母的Char ascii值
        int section = getSectionForPosition(position);
        //如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现

        if (position == getPositionForSection(section)) {
            viewHolder.tvLetter.setVisibility(View.VISIBLE);
            viewHolder.tvLetter.setText(mContent.getSortLetters());
        } else {
            viewHolder.tvLetter.setVisibility(View.GONE);
        }
        final String mobile = this.list.get(position).getPhone()
                .replaceAll(" ", "")
                .replaceAll("\\+", "")
                .replaceAll("-", "");
        viewHolder.tvTitle.setText(this.list.get(position).getName());
        viewHolder.rlContacts.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onClicker.onClik(list.get(position).getName(), mobile);
            }
        });
        return view;

    }


    final static class ViewHolder {
        private TextView tvLetter,//首字母
                tvTitle;//名字
        private RelativeLayout rlContacts;
        //tvIsImpower;//是否授权
    }


    /**
     * 根据ListView的当前位置获取分类的首字母的Char ascii值
     */
    public int getSectionForPosition(int position) {
        return list.get(position).getSortLetters().charAt(0);
    }

    /**
     * 根据分类的首字母的Char ascii值获取其第一次出现该首字母的位置
     */
    public int getPositionForSection(int section) {
        for (int i = 0; i < getCount(); i++) {
            String sortStr = list.get(i).getSortLetters();
            char firstChar = sortStr.toUpperCase().charAt(0);
            if (firstChar == section) {
                return i;
            }
        }

        return -1;
    }

    public void setOnCliker(OnClicker onClicker) {
        this.onClicker = onClicker;
    }

    /**
     * 提取英文的首字母,非英文字母用#代替。
     *
     * @param str
     * @return
     */
    private String getAlpha(String str) {
        String sortStr = str.trim().substring(0, 1).toUpperCase();
        // 正则表达式,判断首字母是否是英文字母
        if (sortStr.matches("[A-Z]")) {
            return sortStr;
        } else {
            return "#";
        }
    }

    @Override
    public Object[] getSections() {
        return null;
    }

    public interface OnClicker {
        void onClik(String name, String phone);
    }
}

SideLetterUtil

public class SideLetterUtil extends View {
    // 触摸事件
    private OnTouchingLetterChangedListener onTouchingLetterChangedListener;
    public static String[] b = {"常用", "A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
            "W", "X", "Y", "Z", "#"};
    private int choose = -1;// 选中
    private Paint paint = new Paint();
    private TextView mTextDialog;
    private Context context;

    public void setTextView(TextView mTextDialog) {
        this.mTextDialog = mTextDialog;
        // this.mTextDialog.setTextColor(getResources().getColor(R.color.primary_green));
    }

    public SideLetterUtil(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
    }

    public SideLetterUtil(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public SideLetterUtil(Context context) {
        super(context);
        this.context = context;
    }

    /**
     * 重写这个方法
     */
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 获取焦点改变背景颜色.
        int height = getHeight();// 获取对应高度
        int width = getWidth(); // 获取对应宽度
        int singleHeight = height / b.length;// 获取每一个字母的高度

        for (int i = 0; i < b.length; i++) {
            paint.setColor(Color.rgb(33, 65, 98));
            paint.setColor(getResources().getColor(R.color.primary_green));
            paint.setTypeface(Typeface.DEFAULT_BOLD);
            paint.setAntiAlias(true);

            paint.setTextSize(DensityUtil.dp2px(context, 8));
            // 选中的状态
            if (i == choose) {
                paint.setColor(Color.parseColor("#3399ff"));
                paint.setFakeBoldText(true);
            }
            // x坐标等于中间-字符串宽度的一半.
            float xPos = width / 2 - paint.measureText(b[i]) / 2;
            float yPos = singleHeight * i + singleHeight;
            canvas.drawText(b[i], xPos, yPos, paint);
            paint.reset();// 重置画笔
        }

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        final int action = event.getAction();
        final float y = event.getY();// 点击y坐标
        final int oldChoose = choose;
        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;
        final int c = (int) (y / getHeight() * b.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.

        switch (action) {
            case MotionEvent.ACTION_UP:
                setBackgroundDrawable(new ColorDrawable(0x00000000));
                choose = -1;//
                invalidate();
                if (mTextDialog != null) {
                    mTextDialog.setVisibility(View.INVISIBLE);
                }
                break;

            default:
                setBackgroundResource(R.drawable.sidebar_background);
                if (oldChoose != c) {
                    if (c >= 0 && c < b.length) {
                        if (listener != null) {
                            listener.onTouchingLetterChanged(b[c]);
                        }
                        if (mTextDialog != null) {
                            mTextDialog.setText(b[c]);
                            mTextDialog.setVisibility(View.VISIBLE);
                        }
                        choose = c;
                        invalidate();
                    }
                }

                break;
        }
        return true;
    }

    /**
     * 向外公开的方法
     *
     * @param onTouchingLetterChangedListener
     */
    public void setOnTouchingLetterChangedListener(
            OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    }

    /**
     * 接口
     */
    public interface OnTouchingLetterChangedListener {
        public void onTouchingLetterChanged(String s);
    }

}

效果图
在这里插入图片描述

发布了22 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_36158551/article/details/83863989