我正在尝试将手机中的联系人加载到android应用程序的列表视图中,但没有加载我的联系人。我有一个允许或拒绝权限的对话框,当我按“允许”时,它向我显示空白屏幕
我使用contact fetcher类来检索联系人。当我拒绝权限时,其按预期显示吐司,但不以列表视图显示联系人
public class ContactFetcher {
private final Context context;
public ContactFetcher(Context c) {
this.context = c;
}
public ArrayList<Contact> fetchAll() {
String[] projectionFields = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
};
ArrayList<Contact> listContacts = new ArrayList<>();
CursorLoader cursorLoader = new CursorLoader(context,
ContactsContract.Contacts.CONTENT_URI,
projectionFields, // the columns to retrieve
null, // the selection criteria (none)
null, // the selection args (none)
null // the sort order (default)
);
Cursor c = cursorLoader.loadInBackground();
final Map<String, Contact> contactsMap = new HashMap<>(c.getCount());
if (c.moveToFirst()) {
int idIndex = c.getColumnIndex(ContactsContract.Contacts._ID);
int nameIndex =
c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
do {
String contactId = c.getString(idIndex);
String contactDisplayName = c.getString(nameIndex);
Contact contact = new Contact(contactId, contactDisplayName);
contactsMap.put(contactId, contact);
listContacts.add(contact);
} while (c.moveToNext());
}
c.close();
matchContactNumbers(contactsMap);
return listContacts;
}
public void matchContactNumbers(Map<String, Contact> contactsMap) {
// Get numbers
final String[] numberProjection = new String[]{
Phone.NUMBER,
Phone.TYPE,
Phone.CONTACT_ID,
};
Cursor phone = new CursorLoader(context,
Phone.CONTENT_URI,
numberProjection,
null,
null,
null).loadInBackground();
if (phone.moveToFirst()) {
final int contactNumberColumnIndex =
phone.getColumnIndex(Phone.NUMBER);
final int contactTypeColumnIndex =
phone.getColumnIndex(Phone.TYPE);
final int contactIdColumnIndex = phone.getColumnIndex(Phone.CONTACT_ID);
while (!phone.isAfterLast()) {
final String number = phone.getString(contactNumberColumnIndex);
final String contactId = phone.getString(contactIdColumnIndex);
Contact contact = contactsMap.get(contactId);
if (contact == null) {
continue;
}
final int type = phone.getInt(contactTypeColumnIndex);
String customLabel = "Custom";
CharSequence phoneType = ContactsContract.CommonDataKinds.Phone.getTypeLabel(context.getResources(), type, customLabel);
contact.addNumber(number, phoneType.toString());
phone.moveToNext();
}
}
phone.close();
}
这是我的mainActivity ...
private static final int PERMISSIONS_REQUEST_READ_CONTACTS=100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lvContacts = (ListView) findViewById(R.id.lvContacts);
showContacts();
}
private void showContacts(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS);
//After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method
} else {
listContacts = new ContactFetcher(this).fetchAll();
ContactsAdapter adapterContacts = new ContactsAdapter(this, listContacts);
lvContacts.setAdapter(adapterContacts);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults) {
if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Permission is granted
listContacts = new ContactFetcher(this).fetchAll();
ContactsAdapter adapterContacts = new ContactsAdapter(this, listContacts);
lvContacts.setAdapter(adapterContacts);
} else {
Toast.makeText(this, "Until you grant the permission, we canot display the names", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
答案 0 :(得分:0)
您遇到的特定问题是假设loadInBackground
立即返回一个包含所有数据的游标,而不是它的工作原理。
但是通常不建议使用CursorLoader
模式将内容加载到UI。
您应该以不同的方式进行操作,例如,在AsyncTask
中查询数据,然后将结果传递到onPostExecute
中。
对于现有代码中最简单的更改,我将fetchAll
更改为阻塞方法,如下所示:
public ArrayList<Contact> fetchAll() {
String[] projectionFields = new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
};
ArrayList<Contact> listContacts = new ArrayList<>();
Cursor c = context.getContentResolver().query(Contacts.CONTENT_URI,projectionFields,null,null,null);
final Map<String, Contact> contactsMap = new HashMap<>(c.getCount());
if (c.moveToFirst()) {
... // same code
}
c.close();
matchContactNumbers(contactsMap);
return listContacts;
}
并从AsyncTask调用,以免它在UI线程上运行任何繁琐的代码,例如:
new AsyncTask<Void, Void, ArrayList<Contact>>() {
@Override
protected ArrayList<Contact> doInBackground(Void... params) {
return new ContactFetcher(this).fetchAll();
}
@Override
protected void onPostExecute(ArrayList<Contact> listContacts) {
ContactsAdapter adapterContacts = new ContactsAdapter(this, listContacts);
lvContacts.setAdapter(adapterContacts);
}
}.execute();