Android-获取手机通讯录的实战施用(含SIM卡中的联系人)

Android-获取手机通讯录的实战应用(含SIM卡中的联系人)

前言:
像获取SIM卡中的联系人问题,当时困扰了一两天,到处找资料,有的地方能找到只字片语,有的地方能提供一小段代码,但这些对一个初学者来说都是不够。。。我觉得初学者还是更喜欢拿来主义(我也一样 ),嘿嘿,一个运行的通的源码比什么都好~
其实后来这个功能实现后,其实感觉就是一层窗户纸,一捅破其实很简单,往往很多问题都是知者容易,未知者难如上擎天。。。
为后来人少走弯路,特献上处子原创实例讲解贴~

效果图:

Android-获取手机通讯录的实战施用(含SIM卡中的联系人)
正题:
本实例包含几下实际应用:
1. 获取手机通讯录(包括SIM卡中的联系人)
2. 几种Intent的传值应用
3. Adapter的自定义使用
4. AutoCompleteTextView应用
5. TextWatcher应用(带正则应用)
6. AsyncTask应用
7. 防止手机横屏时页面重新加载
8. 通讯录联系人按拼音重排序

(注:以下代码都是针对标题节选的关键代码,甚至有些不是同一文件中,详情请参考工程)
一.获取手机通讯录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
 
//从本机中取号
private void GetLocalContact(){
  //读取手机中手机号
  Cursor cursor = getContentResolver().query(People.CONTENT_URI, null,
    null, null, null);
  while (cursor.moveToNext()) {
   ContactInfo cci = new ContactInfo();
   //取得联系人名字
   int nameFieldColumnIndex = cursor.getColumnIndex(People.NAME);
   cci.contactName = cursor.getString(nameFieldColumnIndex);
   //取得电话号码
   int numberFieldColumnIndex = cursor.getColumnIndex(People.NUMBER);
   cci.userNumber = cursor.getString(numberFieldColumnIndex);
   cci.userNumber = GetNumber(cci.userNumber);
   cci.isChecked = false;
   if (IsUserNumber(cci.userNumber)) {
    if (!IsContain(contactList, cci.userNumber)) {
     if(IsAlreadyCheck(wNumStr, cci.userNumber)){
      cci.isChecked = true;
      numberStr += "," + cci.userNumber;
     }
     contactList.add(cci);
      //Log.i("umeng", "*********"+cci.userNumber);
    }
   }
  }
  cursor.close();
}
 
//从SIM卡中取号
private void GetSimContact(String add){
  //读取SIM卡手机号,有两种可能:content://icc/adn与content://sim/adn
  try {
   Intent intent = new Intent();
   intent.setData(Uri.parse(add));
   Uri uri = intent.getData();
   mCursor = getContentResolver().query(uri, null, null, null, null);
   if (mCursor != null) {
    while (mCursor.moveToNext()) {
     ContactInfo sci = new ContactInfo();
     // 取得联系人名字
     int nameFieldColumnIndex = mCursor.getColumnIndex("name");
     sci.contactName = mCursor.getString(nameFieldColumnIndex);
     // 取得电话号码
     int numberFieldColumnIndex = mCursor
       .getColumnIndex("number");
     sci.userNumber = mCursor.getString(numberFieldColumnIndex);
     sci.userNumber = GetNumber(sci.userNumber);
     sci.isChecked = false;
 
     if (IsUserNumber(sci.userNumber)) {
      if (!IsContain(contactList, sci.userNumber)) {
       if(IsAlreadyCheck(wNumStr, sci.userNumber)){
        sci.isChecked = true;
        numberStr += "," + sci.userNumber;
       }
       contactList.add(sci);
        //Log.i("umeng", "*********"+sci.userNumber);
      }
     }
    }
    mCursor.close();
   }
  } catch (Exception e) {
   Log.i("umeng", e.toString());
  }
}

二. 几种Intent的传值应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//页面传值并获取回传值
Intent intent = new Intent();
intent.setClass(Eoe_Contact.this, ContactListView.class);
Bundle bundle = new Bundle();
String wNumberStr = eMsisdn.getText().toString();
bundle.putString("wNumberStr", wNumberStr);
intent.putExtras(bundle);
startActivityForResult(intent, CONTACT_REQUEST_CODE);
 
//获取前一页面所传值
  Intent intent = this.getIntent();
  Bundle  bundle = intent.getExtras();
  String wNumberStr = bundle.getString("wNumberStr").replace(",", ",");
 
//获取回传值
//重写获取页面回传值
    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     switch (requestCode) {
     case CONTACT_REQUEST_CODE:
   if (resultCode == RESULT_OK) {
    String numberStr = null;
    Bundle bundle = data.getExtras();
    if (bundle != null) {
     numberStr = bundle.getString("numberStr");
    }
    eMsisdn.setText(numberStr);
   }
   break;
  }
    }

三. Adapter的自定义使用
继承BaseAdapter类,重写。这个内容比较多就不粘了,详情看ContactAdapter.JAVA页面
需要注意的一点是,getView方法,adapter是在页面变化的时候,重新获取当前页面的数据

四. AutoCompleteTextView应用 和 TextWatcher应用
大家都看过APIDEMOS的示例,看过AutoCompleteTextView的基本应用,但是实际当中那些是不够的,我们往往希望点击自动提示后对所获取的内容做自己的逻辑处理,因此TextWatcher可以派上用场了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//编辑AUTOCOMPLETE数组
    autoContact = new String[contactList.size()];
    for(int c=0;c<contactList.size();c++){
     autoContact[c]=contactList.get(c).contactName+"("+contactList.get(c).userNumber+")";
    }
    //绑定AUTOCOMPLETE
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(ContactListView.this,
                  android.R.layout.simple_dropdown_item_1line, autoContact);
    textView.setAdapter(adapter);
    textView.addTextChangedListener(mTextWatcher);
 
//监听AUTOTEXT内容变化,当出现符合选中联系人[联系人(手机号)]的情况下,将该勾中,并加入选中手机号中
private TextWatcher mTextWatcher = new TextWatcher() {
  public void beforeTextChanged(CharSequence s, int start, int
                before, int after) { }
        public void onTextChanged(CharSequence s, int start,
                int before, int after) {
                 String autoText = s.toString();
         if(autoText.length()>=13){
          Pattern pt=Pattern.compile("\\(([1][3,5,8]+\\d{9})\\)");
          Matcher mc = pt.matcher(autoText);
          if(mc.find()){
           String sNumber = mc.group(1);
           DealWithAutoComplete(contactList,sNumber);
           //刷新列表
           Toast.makeText(ContactListView.this, "已选中您搜索的结果!",1000).show();
           ca.setItemList(contactList);
           ca.notifyDataSetChanged();
          }
         }
        }
        public void afterTextChanged(Editable s) { }
};

五. AsyncTask应用
考虑到从机子上获取通讯有时间等待,因此使用了进程,提高体验效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//启动进程
  new GetContactTask().execute("");
 
//获取通讯录进程
private class GetContactTask extends AsyncTask<String, String, String> {
  public String doInBackground(String... params) {
 
   return "";
  }
  @Override
  protected void onPreExecute() {
   showDialog(DIALOG_KEY);
  }
  @Override
  public void onPostExecute(String Re) {
 
          removeDialog(DIALOG_KEY);
  }
 
  //下面这段本例未使用,能配合doInBackground进行刷新效果
  @Override
  protected void onProgressUpdate(String... values) {
   // TODO Auto-generated method stub
  }
}
//

六. 防止手机横屏时页面重新加载
AndroidManifest.xml中:


七. 通讯录联系人按拼音重排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//按中文拼音顺序排序
    Comparator comp = new Mycomparator(); 
    Collections.sort(contactList,comp);
 
//通讯社按中文拼音排序
public class Mycomparator implements Comparator{ 
public int compare(Object o1,Object o2) { 
ContactInfo c1=(ContactInfo)o1; 
ContactInfo c2=(ContactInfo)o2; 
Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);
return cmp.compare(c1.contactName, c2.contactName); 
} 
 
}

呃,应该都差不多这些了。。。

后记:
发现ANDROID 2.0以后提供了一个新的类,android.provider.ContactsContract,貌似可以直接取出SIM卡中的联系人。
以前代码都是使用ANDROID 1.5,毕竟需要考虑到一些低版本用户吧~