Android 获取手机通讯录联系人信息

近日在项目开发过程中发现,华为手机HarmonyOS 3.0系统,设置>隐私 里面可以查看各个应用访问隐私权限的次数,发现应用程序访问手机通讯录的次数异常的高,针对访问通讯录频次高的问题做了研究和优化

问题分析:

分析代码发现只要通过ContentProvider 访问通讯录一次,统计次数就响应增加一次

ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(ContactsContract.Data.CONTENT_URI, null, null, null, null);

代码中获取联系人头像、邮箱、号码、公司信息等都调用了query 方法,因此查询一个联系人的信息访问了多次通讯录,因此对获取联系人的方法做了改进,改进如下:

一、权限声明

AndroidManifest.xml文件中声明权限如下:

        获取联系人权限      文件读写权限

二、新建联系人信息类

import java.util.ArrayList;
import java.util.List;/*** Create time 2023/3/8 16:56*/
public class ContactsInfo {long contactId;      String displayName;String photoUri;String photoPath;//String firstName;String lastName;//String company;String department;String job;String jobDescription;//String emailAddress;String emailAddressDisplayName;String note;String nickName;String webUrl;String relationName;String protocol;String customProtocol;String identity;String namespace;String groupId;List contactsNumbers;public long getContactId() {return contactId;}public void setContactId(long contactId) {this.contactId = contactId;}public String getDisplayName() {return displayName == null ? "" : displayName;}public void setDisplayName(String displayName) {this.displayName = displayName;}public String getPhotoUri() {return photoUri == null ? "" : photoUri;}public void setPhotoUri(String photoUri) {this.photoUri = photoUri;}public String getPhotoPath() {return photoPath == null ? "" : photoPath;}public void setPhotoPath(String photoPath) {this.photoPath = photoPath;}public String getFirstName() {return firstName == null ? "" : firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}public String getLastName() {return lastName == null ? "" : lastName;}public void setLastName(String lastName) {this.lastName = lastName;}public String getCompany() {return company == null ? "" : company;}public void setCompany(String company) {this.company = company;}public String getDepartment() {return department == null ? "" : department;}public void setDepartment(String department) {this.department = department;}public String getJob() {return job == null ? "" : job;}public void setJob(String job) {this.job = job;}public String getJobDescription() {return jobDescription == null ? "" : jobDescription;}public void setJobDescription(String jobDescription) {this.jobDescription = jobDescription;}public String getEmailAddress() {return emailAddress == null ? "" : emailAddress;}public void setEmailAddress(String emailAddress) {this.emailAddress = emailAddress;}public String getEmailAddressDisplayName() {return emailAddressDisplayName == null ? "" : emailAddressDisplayName;}public void setEmailAddressDisplayName(String emailAddressDisplayName) {this.emailAddressDisplayName = emailAddressDisplayName;}public String getNote() {return note == null ? "" : note;}public void setNote(String note) {this.note = note;}public String getNickName() {return nickName == null ? "" : nickName;}public void setNickName(String nickName) {this.nickName = nickName;}public String getWebUrl() {return webUrl == null ? "" : webUrl;}public void setWebUrl(String webUrl) {this.webUrl = webUrl;}public String getRelationName() {return relationName == null ? "" : relationName;}public void setRelationName(String relationName) {this.relationName = relationName;}public String getProtocol() {return protocol == null ? "" : protocol;}public void setProtocol(String protocol) {this.protocol = protocol;}public String getCustomProtocol() {return customProtocol == null ? "" : customProtocol;}public void setCustomProtocol(String customProtocol) {this.customProtocol = customProtocol;}public String getIdentity() {return identity == null ? "" : identity;}public void setIdentity(String identity) {this.identity = identity;}public String getNamespace() {return namespace == null ? "" : namespace;}public void setNamespace(String namespace) {this.namespace = namespace;}public String getGroupId() {return groupId == null ? "" : groupId;}public void setGroupId(String groupId) {this.groupId = groupId;}public List getContactsNumbers() {if (contactsNumbers == null) {return new ArrayList<>();}return contactsNumbers;}public void setContactsNumbers(List contactsNumbers) {this.contactsNumbers = contactsNumbers;}@Overridepublic String toString() {return "ContactsInfo{" +"contactId=" + contactId +", displayName='" + displayName + '\'' +", photoUri='" + photoUri + '\'' +", photoPath='" + photoPath + '\'' +", firstName='" + firstName + '\'' +", lastName='" + lastName + '\'' +", company='" + company + '\'' +", department='" + department + '\'' +", job='" + job + '\'' +", jobDescription='" + jobDescription + '\'' +", emailAddress='" + emailAddress + '\'' +", emailAddressDisplayName='" + emailAddressDisplayName + '\'' +", note='" + note + '\'' +", nickName='" + nickName + '\'' +", webUrl='" + webUrl + '\'' +", relationName='" + relationName + '\'' +", protocol='" + protocol + '\'' +", customProtocol='" + customProtocol + '\'' +", identity='" + identity + '\'' +", namespace='" + namespace + '\'' +", groupId='" + groupId + '\'' +", contactsNumbers=" + contactsNumbers +'}';}public static class ContactsNumber {int numberType;String label;String number;public int getNumberType() {return numberType;}public void setNumberType(int numberType) {this.numberType = numberType;}public String getLabel() {return label == null ? "" : label;}public void setLabel(String label) {this.label = label;}public String getNumber() {return number == null ? "" : number;}public void setNumber(String number) {this.number = number;}@Overridepublic String toString() {return "ContactsNumber{" +"numberType=" + numberType +", label='" + label + '\'' +", number='" + number + '\'' +'}';}}
}

三、获取联系人信息

调用方法前先检查读取联系人权限 android.Manifest.permission.READ_CONTACTS,

如果要保存联系人头像到SD卡目录下还需检查文件读写权限 android.Manifest.permission.WRITE_EXTERNAL_STORAGE

import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.util.Log;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;/*** Create time 2023/3/8 16:56*/
public class ContactsLoadUtil {public static final String TAG = "ContactsLoadUtil";/*** 调用之前请检测读取联系人权限{@link android.Manifest.permission#READ_CONTACTS}* 如果要保存头像,请检测SD卡写入权限{@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE}** @param context Context* @throws IOException*/public static void loadContacts(Context context) throws IOException {// 创建保存头像的文件目录File filesDir = context.getFilesDir();File photoDir = new File(filesDir, "photo");if (!photoDir.exists()) {boolean mkdirs = photoDir.mkdirs();Log.d(TAG, "mk photo dir: " + mkdirs);}Log.d(TAG, "photoDir path: " + photoDir.getAbsolutePath());// 存储联系人的MapMap contactsMap = new HashMap<>();// cursorContentResolver resolver = context.getContentResolver();Cursor cursor = resolver.query(ContactsContract.Data.CONTENT_URI, null, null, null, null);cursor.moveToFirst();do {// 查询联系人idlong contactId = cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.Data.CONTACT_ID));// 查询联系人显示名 displayNameString displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Data.DISPLAY_NAME));// 查询联系人头像Uri地址String photoUri = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Data.PHOTO_URI));// mimeType 类型String mimeType = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Data.MIMETYPE));
//            Log.d(TAG, "mimeType: " + mimeType);ContactsInfo contacts = contactsMap.get(contactId);if (contacts == null) {contacts = new ContactsInfo();contactsMap.put(contactId, contacts);}contacts.setContactId(contactId);contacts.setDisplayName(displayName);contacts.setPhotoUri(photoUri);// vnd.android.cursor.item/photo 联系人头像if (ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {byte[] blob = cursor.getBlob(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Photo.PHOTO));// 将头像保存到data/data/packageName/files/photo/ 目录下if (blob != null) {Log.d(TAG, "blob length: " + blob.length);File file = new File(photoDir, contactId + ".jpg");FileOutputStream fos = new FileOutputStream(file);fos.write(blob);fos.flush();fos.close();// 设置头像路径Log.d(TAG, "photo path: " + file.getAbsolutePath());contacts.setPhotoPath(file.getAbsolutePath());}}/*** 查询所有的号码* 手机号码 {@link ContactsContract.CommonDataKinds.Phone#TYPE_MOBILE}* 家庭号码 {@link ContactsContract.CommonDataKinds.Phone#TYPE_HOME}*/if (ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {int numberType = cursor.getInt(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.TYPE));String label = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.LABEL));String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));// 添加号码ContactsInfo.ContactsNumber contactsNumber = new ContactsInfo.ContactsNumber();contactsNumber.setNumberType(numberType);contactsNumber.setNumber(number);contactsNumber.setLabel(label);contacts.getContactsNumbers().add(contactsNumber);}// 查询姓和名if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {String firstName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));String lastName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));contacts.setFirstName(firstName);contacts.setLastName(lastName);}// 公司信息if (ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE.equals(mimeType)) {String company = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Organization.COMPANY));String department = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Organization.DEPARTMENT));String job = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Organization.TITLE));String jobDescription = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Organization.JOB_DESCRIPTION));contacts.setCompany(company);contacts.setDepartment(department);contacts.setJob(job);contacts.setJobDescription(jobDescription);}// 邮箱信息if (ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE.equals(mimeType)) {String emailAddress = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.ADDRESS));String emailAddressDisplayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Email.DISPLAY_NAME));contacts.setEmailAddress(emailAddress);contacts.setEmailAddressDisplayName(emailAddressDisplayName);}// 备注信息if (ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE.equals(mimeType)) {String note = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Note.NOTE));contacts.setNote(note);}// 昵称if (ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) {String nickName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Nickname.NAME));contacts.setNickName(nickName);}// 网址链接if (ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE.equals(mimeType)) {String webUrl = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Website.URL));contacts.setWebUrl(webUrl);}// 亲属姓名if (ContactsContract.CommonDataKinds.Relation.CONTENT_ITEM_TYPE.equals(mimeType)) {String relationName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Relation.NAME));contacts.setRelationName(relationName);}// im 协议if (ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE.equals(mimeType)) {String protocol = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Im.PROTOCOL));String customProtocol = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL));contacts.setProtocol(protocol);contacts.setCustomProtocol(customProtocol);}// 身份信息if (ContactsContract.CommonDataKinds.Identity.CONTENT_ITEM_TYPE.equals(mimeType)) {String identity = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Identity.IDENTITY));String namespace = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Identity.NAMESPACE));contacts.setIdentity(identity);contacts.setNamespace(namespace);}// 群组信息if (ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE.equals(mimeType)) {String groupId = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID));contacts.setGroupId(groupId);}} while (cursor.moveToNext());// 关闭cursorcursor.close();ArrayList contactsList = new ArrayList<>(contactsMap.values());Log.d(TAG, "contactsList size: " + contactsList.size());for (ContactsInfo info : contactsList) {Log.d(TAG, "contacts info: " + info);}}
}

以上就是获取联系人信息的详细代码,如果大家还需要获取其他信息的话,可以查看Android SDK 源码,根据源码里面的注释去获取更多的信息。

以上代码实现仅供大家参考,希望对大家有所帮助


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部