Android 未经明确许可访问联系人信息

Android 未经明确许可访问联系人信息,android,android-permissions,android-contacts,Android,Android Permissions,Android Contacts,我对应用程序开发非常陌生。我正在尝试阅读联系人信息,而无需请求对联系人的许可(因此我正在使用意图) 我在我的主要活动中获得一个URI,其中包含以下代码: Intent selectContactIntent = new Intent(Intent.ACTION_PICK); selectContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE); if (selectContactIntent.resolveActivity(get

我对应用程序开发非常陌生。我正在尝试阅读联系人信息,而无需请求对联系人的许可(因此我正在使用意图)

我在我的主要活动中获得一个URI,其中包含以下代码:

Intent selectContactIntent = new Intent(Intent.ACTION_PICK);
selectContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);
if (selectContactIntent.resolveActivity(getPackageManager()) != null) {
    startActivityForResult(selectContactIntent, REQUEST_CODE_SELECT_CONTACT);
}
else {
    showContactRequiredMessage(view);
}
在另一个(子)活动中,我执行以下操作:

contactUri = intent.getParcelableExtra(MainActivity.CONTACT_URI);

String[] projection = new String[] {
        ContactsContract.Contacts.Data._ID,
        ContactsContract.Contacts.Data.MIMETYPE,
        ContactsContract.Contacts.Data.DATA1,
        ContactsContract.Contacts.Data.DATA2,
        ContactsContract.Contacts.Data.DATA3,
        ContactsContract.Contacts.Data.DATA4,
        ContactsContract.Contacts.Data.DATA5,
        ContactsContract.Contacts.Data.DATA6,
        ContactsContract.Contacts.Data.DATA7,
        ContactsContract.Contacts.Data.DATA8,
        ContactsContract.Contacts.Data.DATA9,
        ContactsContract.Contacts.Data.DATA10,
        ContactsContract.Contacts.Data.DATA11,
        ContactsContract.Contacts.Data.DATA12,
        ContactsContract.Contacts.Data.DATA13,
        ContactsContract.Contacts.Data.DATA14,
        ContactsContract.Contacts.Data.DATA15
};
Cursor contactResults = getContentResolver().query(contactUri, projection, null, null, null);
最后一行抛出异常
java.lang.IllegalArgumentException:Invalid column


我的应用程序并不需要所有的数据,实际上我只是想看看有什么可用的,我很可能需要名字、姓氏、电话和电子邮件。

我的问题是我在请求联系信息时设置的MIME类型。应使用状态
Contacts contract.Contacts.CONTENT\u TYPE
。但是,如果我使用类似于
contacts contract.commondatatypes.Phone.CONTENT\u TYPE的
,我可以获得显示名称和电话号码。我不确定这是否意味着我需要进行多次查询才能获得所有信息(更改请求的类型时,联系人选择器中显示的信息会发生变化)


TL;DR:在创建选择联系人的意图时使用了“错误”的内容类型。

我的问题是我在请求联系人信息时在意图上设置的MIME类型。应使用状态
Contacts contract.Contacts.CONTENT\u TYPE
。但是,如果我使用类似于
contacts contract.commondatatypes.Phone.CONTENT\u TYPE的
,我可以获得显示名称和电话号码。我不确定这是否意味着我需要进行多次查询才能获得所有信息(更改请求的类型时,联系人选择器中显示的信息会发生变化)


TL;DR:在创建联系人选择意向时使用了“错误”的内容类型。

如我在对您的答案的评论中所述,您应该能够获得预期的信息,而无需使用特定的
内容类型
CommonDataTypes.Phone.content\u类型

我在代码中看到的问题是,您试图从
联系人
表uri访问
数据
表信息

ContactsContract
api将信息存储在三个主表上:Contacts、RawContacts和Data。 如果给您一个contactUri,它指向Contacts表中的一个条目,请使用以下代码读取与该联系人相关的数据条目:

long contactId = ContentUris.parseId(contactUri);
String projection = String[] { Data.MIMETYPE, Data.DISPLAY_NAME, Data.DATA1 };
String selection = Data.CONTACT_ID + " = " + contactId;
Cursor cursor = getContentResolver().query(Data.CONTENT_URI, projection, selection, null, null);

while (cursor != null && cursor.moveToNext()) {
  String mime = cursor.getString(0);
  String name = cursor.getString(1);
  String info = cursor.getString(2);
  if (mime.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
     Log.d(TAG, name + ": email = " + info;
  }
  if (mime.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
     Log.d(TAG, name + ": phone = " + info;
  }
  // Add more mimetypes here if needed...
}
if (cursor != null) {
  cursor.close();
}

正如我在对您的回答的评论中所提到的,您应该能够在不使用特定的
CONTENT\u类型
的情况下获得所需的信息,如
commondatatypes.Phone.CONTENT\u类型

我在代码中看到的问题是,您试图从
联系人
表uri访问
数据
表信息

ContactsContract
api将信息存储在三个主表上:Contacts、RawContacts和Data。 如果给您一个contactUri,它指向Contacts表中的一个条目,请使用以下代码读取与该联系人相关的数据条目:

long contactId = ContentUris.parseId(contactUri);
String projection = String[] { Data.MIMETYPE, Data.DISPLAY_NAME, Data.DATA1 };
String selection = Data.CONTACT_ID + " = " + contactId;
Cursor cursor = getContentResolver().query(Data.CONTENT_URI, projection, selection, null, null);

while (cursor != null && cursor.moveToNext()) {
  String mime = cursor.getString(0);
  String name = cursor.getString(1);
  String info = cursor.getString(2);
  if (mime.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
     Log.d(TAG, name + ": email = " + info;
  }
  if (mime.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
     Log.d(TAG, name + ": phone = " + info;
  }
  // Add more mimetypes here if needed...
}
if (cursor != null) {
  cursor.close();
}

这个问题中被接受的答案的可能重复事实上正是让我走到了现在的地步。如果我尝试使用在那里找到的代码片段,结果是相同的,则会引发异常。该问题中被接受答案的可能重复事实上正是使我达到现在这个地步的原因。如果我尝试使用在那里找到的代码片段,结果是相同的,会引发异常。我不认为你一开始是错的,文档清楚地说明了两个选项:(1)使用
Contacts.CONTENT\u TYPE
获取临时信息。访问联系人的所有字段或(2)使用一种
CommonDataTypes
CONTENT\u TYPE
s访问特定字段。您可以(2)工作,但(1)也应该工作,但可能使用不同的API我不认为您一开始是错的,文档清楚地说明了两个选项:(1)使用
联系人。内容键入
获取临时信息。访问联系人的所有字段或(2)使用一种
CommonDataTypes
CONTENT\u TYPE
s访问特定字段。您可以使(2)工作,但(1)也应该工作,但可能使用不同的api