Android切近实战(八)
天冷了,老夫要把伙食搞上去,这不最近在软件园二楼吃,伙食15块,杠杠的。
美包包,不说了,进入正题。今天老夫要讲的是读取联系人,其实我做这个的初衷是想做一个短信拦截,电话拦截的功能。
我们先看一下界面,还是不错的,挺绚丽的。
OK,我们一看就知道,这又是一个ListView。目前的功能是当你在复选框打钩,点击后面的拨号就会将电话打出去。如果不打钩,电话则不会拨出去。OK,我们先看看页面布局
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ListViewandroid:id="@+id/contactListView"android:descendantFocusability="blocksDescendants"android:layout_width="fill_parent"android:layout_height="fill_parent"android:divider="@color/teal"android:dividerHeight="1dp"></ListView><LinearLayoutandroid:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="wrap_content"><Buttonandroid:id="@+id/btnSelAll"android:text="@string/btnSelAll"android:textColor="@color/teal"android:textSize="14dp"android:textStyle="bold"android:layout_weight="1"android:layout_width="fill_parent"android:layout_height="fill_parent"></Button><Buttonandroid:id="@+id/btnInverseSel"android:text="@string/btnSelInverse"android:textColor="@color/teal"android:layout_marginLeft="1dp"android:layout_weight="1"android:textSize="14dp"android:textStyle="bold"android:layout_width="fill_parent"android:layout_height="fill_parent"></Button><Buttonandroid:id="@+id/btnSet"android:text="@string/btnSet"android:layout_weight="1"android:textColor="@color/teal"android:layout_marginLeft="1dp"android:textSize="14dp"android:textStyle="bold"android:layout_width="fill_parent"android:layout_height="fill_parent"></Button></LinearLayout></LinearLayout>
我们再看看ListView要加载的模版
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="wrap_content"android:id="@+id/contactTemplate"><TableLayoutandroid:id="@+id/tabContatMain"android:layout_width="fill_parent"android:layout_height="wrap_content"android:stretchColumns="2"android:shrinkColumns="2"android:padding="3dip"><TableRow><CheckBoxandroid:id="@+id/chkContactUser"android:layout_gravity="center_vertical"></CheckBox><ImageViewandroid:id="@+id/imgContactPhoto"android:layout_gravity="center_vertical"android:scaleType="fitCenter"></ImageView><TextViewandroid:id="@+id/txtContactName"android:layout_marginLeft="10dp"android:layout_gravity="center_vertical"android:textColor="@color/teal1"></TextView><TextViewandroid:id="@+id/txtContactTelNumber"android:layout_marginLeft="4dp"android:gravity="right"android:layout_gravity="center_vertical"android:textColor="@color/yellow"></TextView><Buttonandroid:id="@+id/btnDail"android:text="@string/btnDail"android:textSize="10dp"android:layout_marginLeft="10dp"android:width="60dp"android:drawableRight="@drawable/dail"android:layout_gravity="center_vertical"android:textColor="@color/purplered"></Button></TableRow></TableLayout></LinearLayout>
依然是TableLayout布局,我们设置它的收缩列为第二列,伸展列也是第二列。这样如果第二列不够显示则会收缩。OK,我们看一下后台代码
publicvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.punchinalarm);owner=this;btnSelAll=(Button)this.findViewById(R.id.btnSelAll);btnSelInverse=(Button)this.findViewById(R.id.btnInverseSel);btnSet=(Button)this.findViewById(R.id.btnSet);contactUserListView=(ListView)this.findViewById(R.id.contactListView);dataList=newArrayList<Map<String,Object>>();this.InitData();}
在OnCreate方法中,我们初始化数据。
privatevoidInitData(){StringphoneUserName=null;StringphoneNumber=null;LongcontactId=null;LongphotoId=null;Map<String,Object>dataMap=null;ContentResolverresolver=this.getApplicationContext().getContentResolver();/**获取Sim卡联系人Uriuri=Uri.parse("content://icc/adn");*/CursorphoneCursor=resolver.query(Phone.CONTENT_URI,PHONE_PROJECTION,null,null,null);if(phoneCursor!=null){while(phoneCursor.moveToNext()){dataMap=newHashMap<String,Object>();phoneUserName=phoneCursor.getString(0);phoneNumber=phoneCursor.getString(1);photoId=phoneCursor.getLong(2);contactId=phoneCursor.getLong(3);if(phoneNumber==null||phoneNumber.trim().length()<11){continue;}BitmapcontactPhoto=null;if(photoId>0){Uriuri=ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,contactId);InputStreaminput=ContactsContract.Contacts.openContactPhotoInputStream(resolver,uri);contactPhoto=BitmapFactory.decodeStream(input);}else{contactPhoto=BitmapFactory.decodeResource(getResources(),R.drawable.usersmall);}dataMap.put("UserName",phoneUserName);dataMap.put("UserPhoneNumber",phoneNumber);dataMap.put("UserPhoto",contactPhoto);dataList.add(dataMap);}if(dataList!=null&&dataList.size()>0){customAdaptersimpleAdapter=newcustomAdapter(this,dataList,R.layout.contactdetailtemplate,newString[]{"UserPhoto","UserName","UserPhoneNumber"},newint[]{R.id.chkContactUser,R.id.imgContactPhoto,R.id.txtContactName,R.id.txtContactTelNumber,R.id.btnDail});this.contactUserListView.setAdapter(simpleAdapter);}}}
我们知道外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity当中通过getContentResolver()可以得到当前应用的 ContentResolver实例。因为通讯录和短消息都可以通过接口访问,所以我们就可以通过getContentResolver访问SIM卡和手机中的联系人信息。
我们主要到下面的这句
CursorphoneCursor=resolver.query(Phone.CONTENT_URI,PHONE_PROJECTION,null,null,null);
通过接口查询,我们会得到一个Cursor。通过查看Cursor的定义,我们发现它是个抽象类
publicabstractinterfaceandroid.database.Cursor
我们发现它提供了一些方法,如下
由此可见,它是一个既可以前进又可以后退的无向游标,类似于SqlServer中的游标。这样的话我们不论是读取联系人信息,还是读取短消息,都可以随时定位游标。
在上面我们看到Query的几个参数,Phone.Content_URI,获取联系人的时候需要去这个URI去取数据。其实这里的Phone.Content_URI的值是content://com.android.contacts/contacts。它的定义如下
public static final android.net.Uri CONTENT_URI;
ok,我们拿到联系人之后,我们进行循环,游标下移,拿出所有的有电话号码的联系人的数据。因为我们传入的PHONE_PROJECTION的顺序是姓名,电话号码,照片ID,以及一个ContactID。所以我们看到取数据的顺序如下
phoneUserName=phoneCursor.getString(0);phoneNumber=phoneCursor.getString(1);photoId=phoneCursor.getLong(2);contactId=phoneCursor.getLong(3);
拿到PhotoID之后,我们判断是否大于0,如果大于0,我们会获取用户图像。
获取用户图像的时候,先通过下面的代码将URI和参数连接起来
ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,contactId)
其实这个类似于Get方式的API,比如ContactUser/100,意思是获取编号为100的人的信息。
OK,URI构造好之后,我们获取图像
InputStreaminput=ContactsContract.Contacts.openContactPhotoInputStream(resolver,uri);contactPhoto=BitmapFactory.decodeStream(input);
最后加入List<Map<String,Object>>,对ListView运用适配器。
classcustomAdapterextendsBaseAdapter{privateList<Map<String,Object>>dataList;privateLayoutInflatermInflater;privateContextcontext;privateString[]keyString;privateint[]valueViewID;Holderholder;publiccustomAdapter(Contextcontext,List<Map<String,Object>>dataList,intresource,String[]from,int[]to){this.dataList=dataList;this.context=context;mInflater=(LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);keyString=newString[from.length];valueViewID=newint[to.length];System.arraycopy(from,0,keyString,0,from.length);System.arraycopy(to,0,valueViewID,0,to.length);}@OverridepublicintgetCount(){returndataList.size();}@OverridepublicObjectgetItem(intposition){returndataList.get(position);}@OverridepubliclonggetItemId(intposition){returnposition;}publicvoidremoveItem(intposition){dataList.remove(position);this.notifyDataSetChanged();}publicViewgetView(intposition,ViewconvertView,ViewGroupparent){if(convertView!=null){holder=(Holder)convertView.getTag();}else{convertView=mInflater.inflate(R.layout.contactdetailtemplate,null);holder=newHolder();holder.chkContactUser=(CheckBox)convertView.findViewById(valueViewID[0]);holder.imgUserPhoto=(ImageView)convertView.findViewById(valueViewID[1]);holder.labUserName=(TextView)convertView.findViewById(valueViewID[2]);holder.labPhoneNumber=(TextView)convertView.findViewById(valueViewID[3]);holder.btnDail=(Button)convertView.findViewById(valueViewID[4]);convertView.setTag(holder);}Map<String,Object>appInfo=dataList.get(position);if(appInfo!=null){StringuserName=appInfo.get(keyString[1]).toString();StringuserPhoneNumber=appInfo.get(keyString[2])==null?"":appInfo.get(keyString[2]).toString();BitmapuserPhoto=(Bitmap)appInfo.get(keyString[0]);holder.labUserName.setText(userName);holder.labPhoneNumber.setText(userPhoneNumber);holder.imgUserPhoto.setImageBitmap(userPhoto);holder.btnDail.setOnClickListener(newViewButtonListener(position,holder.chkContactUser));}returnconvertView;}}classHolder{publicTextViewlabUserName;publicTextViewlabPhoneNumber;publicImageViewimgUserPhoto;publicButtonbtnDail;publicCheckBoxchkContactUser;}
这里,其实很简单,我们就是拿到控件,然后根据Position,拿到List中的某行数据,然后赋值。
最后我们看看按钮的Click事件,我们传入了Position和每行的CheckBox。
classViewButtonListenerimplementsOnClickListener{privateintposition;ObjectphoneNumber;CheckBoxchkContactUser;ViewButtonListener(intposition,CheckBoxchkContactUser){this.position=position;this.phoneNumber=dataList.get(position).get("UserPhoneNumber");this.chkContactUser=chkContactUser;}@OverridepublicvoidonClick(Viewview){intvid=view.getId();if(vid==R.id.btnDail&&chkContactUser.isChecked()){IntentdialIntent=newIntent(Intent.ACTION_CALL,Uri.parse("tel:"+phoneNumber));startActivity(dialIntent);}}}
在OnClick中,我们判断如果是拨号按钮并且列头的CheckBox是勾选的,则会拨号,否则不会拨号。OK,最后我们希望在按回退键的时候,弹出是否退出的提示
ok,代码如下
publicbooleanonKeyDown(intkeyCode,KeyEventevent){if((keyCode==KeyEvent.KEYCODE_BACK&&event.getRepeatCount()==0)){dialog();returntrue;}returntrue;}protectedvoiddialog(){AlertDialog.Builderbuilder=newBuilder(punchinalarm.this);builder.setMessage("确定要退出吗?");builder.setTitle("提示");builder.setPositiveButton("确认",newDialogInterface.OnClickListener(){@OverridepublicvoidonClick(DialogInterfacedialog,intwhich){dialog.dismiss();android.os.Process.killProcess(android.os.Process.myPid());}});builder.setNegativeButton("取消",newandroid.content.DialogInterface.OnClickListener(){@OverridepublicvoidonClick(DialogInterfacedialog,intwhich){dialog.dismiss();}});builder.create().show();}
最后,哥们的博客是货真价实,小米3测试机。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。