Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 463|回复: 0

开发交流:获取手机通讯录的实战应用(含SIM卡中的联系人)

[复制链接]

该用户从未签到

发表于 2011-10-24 09:27:46 | 显示全部楼层 |阅读模式
前言:
以前一直搞了4、5年的.NET(C#),最近跟着一起搞一个ANDROID项目,所以从头开始学ANDROID、学java
之前2、3个星期也是到处找资料、找教程,遇到实际问题就是一片海找,毕竟教程里面的实例都太过简单化,在实际应用中需要很多变化。
像获取SIM卡中的联系人问题,当时困扰了一两天,到处找资料,有的地方能找到只字片语,有的地方能提供一小段代码,但这些对一个初学者来说都是不够。。。我觉得初学者还是更喜欢拿来主义(我也一样 ),嘿嘿,一个运行的通的源码比什么都好~
其实后来这个功能实现后,其实感觉就是一层窗户纸,一捅破其实很简单,往往很多问题都是知者容易,未知者难如上擎天。。。
为后来人少走弯路,特献上处子原创实例讲解贴~
(估计台下手拿板砖作欲扔出状的人已经很多了,速度入题!

效果图:






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

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

//从本机中取号

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("eoe", "*********"+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("eoe", "*********"+sci.userNumber);

      }

     }

    }

    mCursor.close();

   }

  } catch (Exception e) {

   Log.i("eoe", e.toString());

  }

}
复制代码二. 几种Intent的传值应用 //页面传值并获取回传值

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可以派上用场了 //编辑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应用
考虑到从机子上获取通讯有时间等待,因此使用了进程,提高体验效果(有关AsyncTask可以在EOE找专贴,我也是学来的,呵呵) //启动进程

  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中: <activity android:name=".ContactListView"

android:theme="@android:style/Theme.NoTitleBar"

android:noHistory="true"

android:configChanges="orientation|keyboardHidden|navigation">

</activity>
复制代码七. 通讯录联系人按拼音重排序 //按中文拼音顺序排序

    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);

}



}
复制代码呃,应该都差不多这些了。。。不容易啊,也老长一贴啊~
个人认为已经贴的比较详细了,有关要点部分都粘出来了,并且源码中也作了相当的注释。
如果还有问题的话,我就想使用安脚无影腿、鸡风双眼插。。。

好吧。。。还是提供一个邮箱:
yingmuxiaodao@yahoo.com.cn


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

下次如果有时间的话,再写一个有关软件版本更新(XML)、文件下载(带进度条)、文件安装的实例

后续发现一些手机还需要从以下两处取:
content://icc/fdn
content://sim/fdn
MOTO XT800比较异常,通讯录在:
content://contacts/phones
双卡双待手机同时插两张卡无法取出...杯具!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2025-1-10 19:31 , Processed in 0.295004 second(s), 36 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表