天冷了,老夫要把伙食搞上去,这不最近在软件园二楼吃,伙食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);

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

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);}@Overridepublic int getCount() {return dataList.size();}@Overridepublic Object getItem(int position) {return dataList.get(position);}@Overridepublic 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;}@Overridepublic 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() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();android.os.Process.killProcess(android.os.Process.myPid());}});builder.setNegativeButton("取消",new android.content.DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}});builder.create().show();}

最后,哥们的博客是货真价实,小米3测试机。

Android切近实战(八)相关推荐

  1. Android切近实战(五)

    最近天气真他娘的热,炸鸡啤酒,我觉得如果不演那么什么我从来都不看的韩剧,绝对没有人喜欢这种吃法.好了,废话不多说,天这么热,我只能晚上腾出时间来写这个东东,顺便引用吉日嘎拉的博客上面的一句话" ...

  2. Node.js 切近实战(八) 之Excel在线(文件权限)

    2019独角兽企业重金招聘Python工程师标准>>> 最近美国又他妈的皮痒了,在南海找事,还说什么中国必须接受南海仲裁结果,我去你大爷的,你以为你是谁啊.说实话只要我们要决一死战的 ...

  3. (转载)Android项目实战(二十八):使用Zxing实现二维码及优化实例

    Android项目实战(二十八):使用Zxing实现二维码及优化实例 作者:听着music睡 字体:[增加 减小] 类型:转载 时间:2016-11-21 我要评论 这篇文章主要介绍了Android项 ...

  4. Android项目实战(三十八):2017最新 将AndroidLibrary提交到JCenter仓库(图文教程)...

    Android项目实战(三十八):2017最新 将AndroidLibrary提交到JCenter仓库(图文教程) 原文:Android项目实战(三十八):2017最新 将AndroidLibrary ...

  5. 基于eclipse的android项目实战—博学谷(十八)播放不同视频(网络视频)

    相信经过了这么长时间,小伙伴们应该都发现了博学谷这个项目存在问题,播放视频的时候,无论播放任何一个章节,他播放的视频都只是一个,也就是VideoPlayActivity.java里面写死的那个(myv ...

  6. (转载)Android项目实战(二十七):数据交互(信息编辑)填写总结

    Android项目实战(二十七):数据交互(信息编辑)填写总结 前言: 项目中必定用到的数据填写需求.比如修改用户名的文字编辑对话框,修改生日的日期选择对话框等等.现总结一下,方便以后使用. 注: 先 ...

  7. 【Android项目实战 | 从零开始写app(十二)】实现app首页智慧服务热门推荐热门主题、新闻

    说在前面,由于各种adapter,xml布局,bean实体类,Activity,也为了让看懂,代码基本都是"简单粗暴直接不好看",没啥okhttp和util工具类之类的封装,本篇幅 ...

  8. 【Android项目实战 | 从零开始写app (六) 】用TabLayout+ViewPager搭建App 框架主页面底部导航栏

    本篇实现效果: 搭建app框架的方式有很多,本节主要用TabLayout+ViewPager搭建App框架,这种方式简单易实现,在主页中加载Fragment碎片,实现不同功能页面的切换效果图如下: 文 ...

  9. 【Android项目实战 | 从零开始写app(十三)】实现用户中心模块清除token退出登录信息修改等功能

    五一后,被ji金伤了,哇呜呜,还是得苦逼老老实实打工写代码,看下面吧 本篇实现效果: 实现登录用户名展示到用户中心页面上,并且页面有个人信息,订单列表,修改密码,意见反馈发送到服务端,前面登录后,通过 ...

最新文章

  1. harmonyos con,鸿蒙HarmonyOS系统中的JS开发框架
  2. javadoc - Java API 文档生成器(Windows版本)
  3. txt文件可存储最大值_Verilog边码边学:十六进制文件读取$readmemh
  4. android elf 加固_Android常见App加固厂商脱壳方法的整理
  5. 小米再被质疑Mimoji抄袭苹果 回应:上传出错 将严肃处理
  6. Asp调用函数是否会影响性能?
  7. 腾讯IM可以实现聊天信息保存到本地服务器吗
  8. java feature类_Java FeatureCollection类代码示例
  9. leetcode 之Rotate List(18)
  10. mysql的条件求和函数_使用SQL语句统计数据时sum和count函数中使用if判断条件的讲解...
  11. 孙鑫-MFC笔记十一--动态链接库
  12. velocity 将数字转为以万为单位,保留2位小数
  13. 一阅阅读-ios上的免费换源小说阅读器
  14. 解决Windows聚焦不更新图片问题
  15. 如何搭建用户生命周期模型?
  16. 学习笔记13--基于蜂窝移动通信的车联网技术
  17. 秦九韶算法与霍纳规则
  18. 高考加油别学计算机图片,高考加油励志说说带图片,2020高考加油说说配图
  19. 《NVM-Express-1_4-2019.06.10-Ratified》学习笔记(8)
  20. VIVADO+ZYNQ7000入门三,PS与PL的联合开发

热门文章

  1. java实现指数分布_Nim 语言编程实现指数分布的随机数
  2. sql sum条件求和_SQL进阶7外连接(outer join)
  3. mysql数据库什么是事件_MySQL数据库之mysql 事件(Event) 总结
  4. // synopsys_translate_off,parallel_case 和 full_case
  5. 【 FPGA 】总线实现形式之选择器
  6. 【 C 】动态内存分配案例分析
  7. 实验long raw 和 blob两种数据类型遇到dblink的表现
  8. Android之LinearLayout布局下怎么让按钮固定在底部
  9. Kubernetes集群监控方案
  10. 背水一战 Windows 10 (47) - 控件(ScrollViewer 特性): Chaining, Rail, Inertia, Snap, Zoom