天冷了,老夫要把伙食搞上去,这不最近在软件园二楼吃,伙食15块,杠杠的。
美包包,不说了,进入正题。今天老夫要讲的是读取联系人,其实我做这个的初衷是想做一个短信拦截,电话拦截的功能。
我们先看一下界面,还是不错的,挺绚丽的。
OK,我们一看就知道,这又是一个ListView。目前的功能是当你在复选框打钩,点击后面的拨号就会将电话打出去。如果不打钩,电话则不会拨出去。OK,我们先看看页面布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical">
<ListView android:id="@+id/contactListView"
android:descendantFocusability="blocksDescendants"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:divider="@color/teal"
android:dividerHeight="1dp">
</ListView>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button android: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>
<Button android: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>
<Button android: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要加载的模版
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:id="@+id/contactTemplate">
<TableLayout android:id="@+id/tabContatMain"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:stretchColumns="2" android:shrinkColumns="2" android:padding="3dip">
<TableRow>
<CheckBox android:id="@+id/chkContactUser"
android:layout_gravity="center_vertical"></CheckBox>
<ImageView android:id="@+id/imgContactPhoto"
android:layout_gravity="center_vertical"
android:scaleType="fitCenter"></ImageView>
<TextView android:id="@+id/txtContactName"
android:layout_marginLeft="10dp"
android:layout_gravity="center_vertical"
android:textColor="@color/teal1"></TextView>
<TextView android:id="@+id/txtContactTelNumber"
android:layout_marginLeft="4dp"
android:gravity="right"
android:layout_gravity="center_vertical"
android:textColor="@color/yellow"></TextView>
<Button android: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,我们看一下后台代码
public void onCreate(Bundle savedInstanceState) {
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 = new ArrayList<Map<String, Object>>();
this.InitData();
}
在OnCreate方法中,我们初始化数据。
private void InitData() {
String phoneUserName = null;
String phoneNumber = null;
Long contactId = null;
Long photoId = null;
Map<String, Object> dataMap = null;
ContentResolver resolver = this.getApplicationContext()
.getContentResolver();
/*
* 获取Sim卡联系人 Uri uri = Uri.parse("content://icc/adn");
*/
Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,
PHONE_PROJECTION, null, null, null);
if (phoneCursor != null) {
while (phoneCursor.moveToNext()) {
dataMap = new HashMap<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;
}
Bitmap contactPhoto = null;
if (photoId > 0) {
Uri uri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, contactId);
InputStream input = 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) {
customAdapter simpleAdapter = new customAdapter(this, dataList,
R.layout.contactdetailtemplate, new String[] {
"UserPhoto", "UserName", "UserPhoneNumber" },
new int[] { 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卡和手机中的联系人信息。
我们主要到下面的这句
Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,
PHONE_PROJECTION, null, null, null);
public abstract interface android.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构造好之后,我们获取图像
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(resolver, uri);
contactPhoto = BitmapFactory.decodeStream(input);
最后加入List<Map<String,Object>>,对ListView运用适配器。
class customAdapter extends BaseAdapter {
private List<Map<String, Object>> dataList;
private LayoutInflater mInflater;
private Context context;
private String[] keyString;
private int[] valueViewID;
Holder holder;
public customAdapter(Context context,
List<Map<String, Object>> dataList, int resource,
String[] from, int[] to) {
this.dataList = dataList;
this.context = context;
mInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
keyString = new String[from.length];
valueViewID = new int[to.length];
System.arraycopy(from, 0, keyString, 0, from.length);
System.arraycopy(to, 0, valueViewID, 0, to.length);
}
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return dataList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public void removeItem(int position) {
dataList.remove(position);
this.notifyDataSetChanged();
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView != null) {
holder = (Holder) convertView.getTag();
} else {
convertView = mInflater.inflate(R.layout.contactdetailtemplate,
null);
holder = new Holder();
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) {
String userName = appInfo.get(keyString[1]).toString();
String userPhoneNumber = appInfo.get(keyString[2]) == null ? ""
: appInfo.get(keyString[2]).toString();
Bitmap userPhoto = (Bitmap) appInfo.get(keyString[0]);
holder.labUserName.setText(userName);
holder.labPhoneNumber.setText(userPhoneNumber);
holder.imgUserPhoto.setImageBitmap(userPhoto);
holder.btnDail.setOnClickListener(new ViewButtonListener(
position, holder.chkContactUser));
}
return convertView;
}
}
class Holder {
public TextView labUserName;
public TextView labPhoneNumber;
public ImageView imgUserPhoto;
public Button btnDail;
public CheckBox chkContactUser;
}
这里,其实很简单,我们就是拿到控件,然后根据Position,拿到List中的某行数据,然后赋值。
最后我们看看按钮的Click事件,我们传入了Position和每行的CheckBox。
class ViewButtonListener implements OnClickListener {
private int position;
Object phoneNumber;
CheckBox chkContactUser;
ViewButtonListener(int position,CheckBox chkContactUser) {
this.position = position;
this.phoneNumber = dataList.get(position).get("UserPhoneNumber");
this.chkContactUser= chkContactUser;
}
@Override
public void onClick(View view) {
int vid = view.getId();
if (vid == R.id.btnDail&&chkContactUser.isChecked()) {
Intent dialIntent = new Intent(Intent.ACTION_CALL, Uri
.parse("tel:" + phoneNumber));
startActivity(dialIntent);
}
}
}
在OnClick中,我们判断如果是拨号按钮并且列头的CheckBox是勾选的,则会拨号,否则不会拨号。OK,最后我们希望在按回退键的时候,弹出是否退出的提示
ok,代码如下
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)) {
dialog();
return true;
}
return true;
}
protected void dialog() {
AlertDialog.Builder builder = new Builder(punchinalarm.this);
builder.setMessage("确定要退出吗?");
builder.setTitle("提示");
builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
android.os.Process.killProcess(android.os.Process.myPid());
}
});
builder.setNegativeButton("取消",
new android.content.DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
最后,哥们的博客是货真价实,小米3测试机。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。