近日在项目开发过程中发现,华为手机HarmonyOS 3.0系统,设置>隐私 里面可以查看各个应用访问隐私权限的次数,发现应用程序访问手机通讯录的次数异常的高,针对访问通讯录频次高的问题做了研究和优化
问题分析:
分析代码发现只要通过ContentProvider 访问通讯录一次,统计次数就响应增加一次
ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(ContactsContract.Data.CONTENT_URI, null, null, null, null);
代码中获取联系人头像、邮箱、号码、公司信息等都调用了query 方法,因此查询一个联系人的信息访问了多次通讯录,因此对获取联系人的方法做了改进,改进如下:
一、权限声明
AndroidManifest.xml文件中声明权限如下:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 获取联系人权限
<uses-permission android:name="android.permission.READ_CONTACTS" /> 文件读写权限
二、新建联系人信息类
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<ContactsNumber> 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<ContactsNumber> getContactsNumbers() {
if (contactsNumbers == null) {
return new ArrayList<>();
}
return contactsNumbers;
}
public void setContactsNumbers(List<ContactsNumber> contactsNumbers) {
this.contactsNumbers = contactsNumbers;
}
@Override
public 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;
}
@Override
public 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());
// 存储联系人的Map
Map<Long, ContactsInfo> contactsMap = new HashMap<>();
// cursor
ContentResolver resolver = context.getContentResolver();
Cursor cursor = resolver.query(ContactsContract.Data.CONTENT_URI, null, null, null, null);
cursor.moveToFirst();
do {
// 查询联系人id
long contactId = cursor.getLong(cursor.getColumnIndexOrThrow(ContactsContract.Data.CONTACT_ID));
// 查询联系人显示名 displayName
String 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());
// 关闭cursor
cursor.close();
ArrayList<ContactsInfo> contactsList = new ArrayList<>(contactsMap.values());
Log.d(TAG, "contactsList size: " + contactsList.size());
for (ContactsInfo info : contactsList) {
Log.d(TAG, "contacts info: " + info);
}
}
}
以上就是获取联系人信息的详细代码,如果大家还需要获取其他信息的话,可以查看Android SDK 源码,根据源码里面的注释去获取更多的信息。文章来源:https://www.toymoban.com/news/detail-530586.html
以上代码实现仅供大家参考,希望对大家有所帮助文章来源地址https://www.toymoban.com/news/detail-530586.html
到了这里,关于Android 获取手机通讯录联系人信息的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!