在Android Studio上实现基于Android6.0的通讯录获取功能
1、新建一个Android项目,API选择23: Android6.0(Marshmallow)
2、在MainActivity的layout中添加一个button用于获取通信录功能
3、为了后续开发的方便和规整,新建一个包Contacts用于存放获取通讯录所需的类。并在包中新建一个Activity:GetContacts。
由于Android6.0对APP运行权限做了较大改变,获取通讯录信息不仅需要静态授权还需要动态申请权限,详情见
Android6.0系统权限那些事
http://www.open-open.com/lib/view/open1450578678148.html
Android 6.0 运行时权限处理完全解析
http://www.w2bc.com/article/101798?from=extend
所以在这里需要给APP添加动态申请权限代码,暂时先将其实现,下一篇博客再考虑封装。新建一个String类型的方法getContacts(Context context),第一步检查是否授权,如果没有授权就申请权限
if (ContextCompat.checkSelfPermission(context,android.Manifest.permission.READ_CONTACTS)
!=PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions((Activity) context,
new String[]{android.Manifest.permission.READ_CONTACTS},
1);
}
这里涉及到的API:
注:这里暂时没有考虑权限申请回调onRequestPermissionsResult()方法,只是为了跑通该程序,在下一篇博客再具体分析关于权限的事儿。
4、授权成功后,开始执行获取通讯录功能:
在写具体代码前,先新建一个类:ContactsInfo用于通讯录的数据封装。定义需要获取到的通讯录信息字符串,并写好构造函数。
public class ContactsInfo {
private String name;
private String number;
private String sortKey;
private int id;
public ContactsInfo(String name,String number,String sortKey,int id){
setName(name);
setNumber(number);
setSortKey(sortKey);
setId(id);
}
定义一个ContactsInfo类型的List用于保存数据:public static List
然后再开始写具体功能:
else {
try {
Uri contactUri =ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
Cursor cursor = context.getContentResolver().query(contactUri,
new String[]{"display_name", "sort_key", "contact_id","data1"},
null, null, "sort_key");
String contactName;
String contactNumber;
String contactSortKey;
int contactId;
while (cursor.moveToNext()) {
contactName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
contactNumber = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactId = cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID));
contactSortKey =getSortkey(cursor.getString(1));
ContactsInfo contactsInfo = new ContactsInfo(contactName,contactNumber,contactSortKey,contactId);
if (contactName!=null)
list.add(contactsInfo);
}
cursor.close();//使用完后一定要将cursor关闭,不然会造成内存泄露等问题
}catch (Exception e){
e.printStackTrace();
}finally {
context = null;
}
这里使用了sort_key对获取到的通讯录信息进行了排序,实现一个方法:
private static String getSortkey(String sortKeyString){
String key =sortKeyString.substring(0,1).toUpperCase();
if (key.matches("[A-Z]")){
return key;
}else
return "#"; //获取sort key的首个字符,如果是英文字母就直接返回,否则返回#。
}
5、实现了基本功能后,我们需要将获取到的数据展示在界面上。
在GetContacts的layout中添加一张ListView
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/ContactsLv"
android:layout_weight="1"/>
之后需要自定义一个adapter用于对ListView的数据传递。新建一个类:ContactsAdapter 扩展自BaseAdapter,新建一个contacts布局来展示该adapter的界面,并重构其四个方法:
public class ContactsAdapter extends BaseAdapter{
private List list;
private Context context;
public ContactsAdapter(List list,Context context){
this.list = list;
this.context = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
convertView =LayoutInflater.from(context).inflate(R.layout.contacts,null);
holder = new ViewHolder();
holder.nametv = (TextView) convertView.findViewById(R.id.contactName);
holder.numbertv = (TextView) convertView.findViewById(R.id.contactNumber);
holder.nametv.setText(list.get(position).getName());
holder.numbertv.setText(list.get(position).getNumber());
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
holder.nametv.setText(list.get(position).getName());
holder.numbertv.setText(list.get(position).getNumber());
}
return convertView;
}
private static class ViewHolder{
TextView nametv;
TextView numbertv;
}
}
/**
* ViewHolder就是一个持有者的类,他里面一般没有方法,只有属性,作用就是一个临时的储存器,
* getView方法中每次返回的View存起来,可以下次再用。
* 这样做的好处就是不必每次都到布局文件中去拿到你的View,提高了效率。
*/
这里使用了ViewHolder来对listvier进行优化
6、在GetContacts活动中将ListView与ContactsAdapter进行绑定:
private ListView ContactsLv;
private ContactsAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_get_contacts);
GetContacts.getContacts(this);
ContactsLv = (ListView) findViewById(R.id.ContactsLv);
adapter = new ContactsAdapter(list, this);
ContactsLv.setAdapter(adapter);
}
另外,需要对list清除缓存,不然每一次运行都会重复加载数据:
@Override
public void onBackPressed() { //清除缓存
list.clear();
super.onBackPressed();
}