获取手机通讯录 (含SIM卡中的联系人)

sim卡UIR

content://icc/fdn

content://sim/fdn
MOTO XT800比较异常,通讯录在:
content://contacts/phones 
1.使用android2.0 的 android.provider.ContactsContract获取通讯录内容。即这个版本是2.0
2.对手机号码过滤处理更加彻底,有的手机号码存储格式为135-0538-2341 中间有“-”
3.详细讲解startActivityForResult的用法
4.AsyncTask类的使用
5考虑到一个名字下,对应多个手机号码(非常实用)
6 最最主要的是他的代码居然不在这个板块,所以迁移过来



前天 23:48 上传
下载附件 (29.64 KB)


前天 23:48 上传
下载附件 (60.73 KB)


前天 23:48 上传
下载附件 (63.57 KB)

正题:
本实例包含几下实际应用:
1. 获取手机通讯录(包括SIM卡中的
联系人

2. 几种Intent的传值应用
3. Adapter的自定义使用
4. AutoCompleteTextView应用
5. TextWatcher应用(带正则应用)
6. AsyncTask应用
7. 防止手机横屏时页面重新加载
8. 通讯录
联系人
按拼音重排序

(注:以下代码都是针对标题节选的关键代码,甚至有些不是同一文件中,详情请参考工程)
一.获取手机通讯录:
从Android 2.0 SDK开始有关联系人provider的类变成了ContactsContract,虽然老的android.provider.Contacts能用,但是在SDK中标记为为deprecated将被放弃不推荐的方法,而从Android 2.0及API Level为5开始新增了android.provider.ContactsContract来代替原来的方法。
ContactsContract的子类ContactsContract.Contacts是一张表,代表了所有联系人的统计信息。比如联系人ID(—ID),查询键(LOOKUP_KEY),联系人的姓名(DISPLAY_NAME_PRIMARY),头像的id([url=]PHOTO_ID[/url])以及群组的id等等。

我们可以通过以下的方法取得所有联系人的表的Cursor对象:

1)ContentResolver contentResolver=getContentResolver();

2)Cursor cursor=contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);//根据URI对象ContactsContract.Contacts.CONTENT_URI查询所有联系人;

从Cursor对象里我们关键是要取得联系人的_id。通过它,再通过ContactsContract.CommonDataKinds的各个子类查询该_id联系人的电话(ContactsContract.CommonDataKinds.Phone),email(ContactsContract.CommonDataKinds.Email)等等。

以取得该联系人所有电话为例:

1)int idFieldIndex=cursor.getColumnIndex(ContactsContract.Contacts._ID);
int id=cursor.getInt(idFieldIndex);//根据列名取得该联系人的id;

2)Cursor phonecursor=contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"=?", new String[]{Integer.toString(id)}, null);//再类ContactsContract.CommonDataKinds.Phone中根据查询相应id联系人的所有电话;

类似地可以ContactsContract.CommonDataKinds的不同的子类查询不同的内容。android文档告诉我们推荐使用ContactsContract.Contacts.LOOKUP_KEY代替ContactsContract.Contacts._ID。

二. 几种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应用(第九条有举例说明)
考虑到从机子上获取通讯有时间等待,因此使用了进程,提高体验效果

  • //启动进程
  •   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);
  • }
  • }

八  startActivityForResult的用法(举例说明) 

在切换界面时,原有的界面需要从新界面取得某些数据,这时需要用到startActivityForResult,比如说从activity1跳转到activity2,边看代码边说用法吧:

activity1的代码片段:这是跳转到activity2

Intent intent = new Intent(Activity1.this, Activity2.class);

startActivityForResult(intent, GET_CODE);

Intent intent = new Intent(Activity1.this, Activity2.class);

startActivityForResult(intent, GET_CODE);

这里的GET_CODEint型,值随意定,用途在后面讲

activity2的代码片段,这是当activity2的任务完成后返回时的代码

setResult(RESULT_OK, (new Intent()).setAction("Corky!"));

finish();

setResult(RESULT_OK, (new Intent()).setAction("Corky!"));

finish();

activity2finish之后,activity1会接收到消息,系统会调用activity1中的onActivityResult方法:


protected void onActivityResult(int requestCode, int resultCode,Intent data) {


if (requestCode == GET_CODE) {


//do something


if (resultCode == RESULT_CANCELED) {


//do something


} else {


//do something


}


}

}

protected void onActivityResult(int requestCode, int resultCode,Intent data) {


if (requestCode == GET_CODE) {


//do something


if (resultCode == RESULT_CANCELED) {


//do something


} else {


//do something


}


}

}

注意这里的GET_CODE要与上面代码中的GET_CODE对应起来,用途大概已经明白了,就是说activity1可能会跳转到很多不同的界面来获得信息,那么怎么区分呢,就用这个GET_CODE,我们这里只有一个。参数中的resultCode的值是由activity2中的setResult的第一个参数决定的,data则为可选参数,可以传递更多的信息。


九  AsyncTask的使用

在android程序中一定不能阻塞UI线程,否则很容易就会弹出no respond 的对话框,导致程序退出。为了避免这种情况,一般需要较长时间执行的任务都放在线程中去执行,如从网上下载图片在界面的某个区域显示。但是使用线程回导致cpu开销过大,并且当线程管理不好时也会弹出no respond框。android提供了AsyncTask类用来处理这种情况;例如需要下载图片,然后在songImagButton中显示,下载的逻辑在songImageButton的initImage方法中。

Java代码

  •     private class DrawImageTask extends AsyncTask<Void,Integer,Void>{   
  • //更新图片显示区域,显示图片   
  •         @Override  
  •         protected void onPostExecute(Void params) {   
  •             // TODO Auto-generated method stub   
  •             songImageButton.invalidate();   
  •             this.cancel(false);   
  •         }   
  • //下载图片   
  •         @Override  
  •         protected Void doInBackground(Void... params) {   
  •             // TODO Auto-generated method stub   
  •             songImageButton.initImage();   
  •             return null;   
  •         }   
  •   
  •     }  


一般在doInBackground中执行后台的逻辑,如下载图片或其他需要耗时长的任务,onPostExecute方法用来对界面进行操作。如果后台的逻辑有返回值,则由doInBackground返回然后传入onPostExecute方法,然后更新界面。doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为doInBackground接受的参数,第二个为显示进度的参数,第第三个为doInBackground返回和onPostExecute传入的参数。

当然我个人认为AsyncTask不能完全取代线程,在一些逻辑较为复杂或者需要在后台反复执行的逻辑就可能需要线程来实现了。


 Eoe_Contact.rar (69.32 KB, 下载次数: 12) 

最后再次感谢smallnews 大侠提供初版。

device.png  (63.57 KB, 下载次数: 72)

 

device.png

device2.png  (60.73 KB, 下载次数: 52)

 

device2.png

device3.png  (29.64 KB, 下载次数: 46)

 

device3.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值