开发者社区> 技术小阿哥> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Android切近实战(八)

简介:
+关注继续查看

美包包,不说了,进入正题。今天老夫要讲的是读取联系人,其实我做这个的初衷是想做一个短信拦截,电话拦截的功能。

我们先看一下界面,还是不错的,挺绚丽的。

wKioL1RbeTHAM8hyAAIo4XZJDwQ669.jpg

OK,我们一看就知道,这又是一个ListView。目前的功能是当你在复选框打钩,点击后面的拨号就会将电话打出去。如果不打钩,电话则不会拨出去。OK,我们先看看页面布局

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
<?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要加载的模版

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
<?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,我们看一下后台代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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方法中,我们初始化数据。

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
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, nullnullnull);
 
        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卡和手机中的联系人信息。

我们主要到下面的这句

1
2
Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,
                PHONE_PROJECTION, nullnullnull);

通过接口查询,我们会得到一个Cursor。通过查看Cursor的定义,我们发现它是个抽象类

1
public abstract interface android.database.Cursor

我们发现它提供了一些方法,如下

wKioL1RbgASRasFnAAEq2WtayDw502.jpg

由此可见,它是一个既可以前进又可以后退的无向游标,类似于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。所以我们看到取数据的顺序如下

1
2
3
4
phoneUserName = phoneCursor.getString(0);
                phoneNumber = phoneCursor.getString(1);
                photoId = phoneCursor.getLong(2);
                contactId = phoneCursor.getLong(3);

拿到PhotoID之后,我们判断是否大于0,如果大于0,我们会获取用户图像。

获取用户图像的时候,先通过下面的代码将URI和参数连接起来

1
2
ContentUris.withAppendedId(
                            ContactsContract.Contacts.CONTENT_URI, contactId)

其实这个类似于Get方式的API,比如ContactUser/100,意思是获取编号为100的人的信息。

OK,URI构造好之后,我们获取图像

1
2
3
InputStream input = ContactsContract.Contacts
                            .openContactPhotoInputStream(resolver, uri);
                    contactPhoto = BitmapFactory.decodeStream(input);

最后加入List<Map<String,Object>>,对ListView运用适配器。

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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,最后我们希望在按回退键的时候,弹出是否退出的提示

wKiom1RbjdHDxnOlAAGKTIuOxw4762.jpg

ok,代码如下

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
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测试机。

wKiom1Rbj22DJ0SbAAHqhJl9btY782.jpgwKiom1Rbj6DRdUVHAATC_rI71sI887.jpg



本文转自 BruceAndLee 51CTO博客,原文链接:http://blog.51cto.com/leelei/1573863,如需转载请自行联系原作者


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Android开发之入口Activity
原文:Android开发之入口Activity Android开发之入口Activity Adnroid App是如何确定入口Activity的? 难道就因为class的类名叫MainActivity,布局文件叫activity_main.xml? 如果这样认为,就大错特错了。
941 0
13688
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载