Как получить контакты в порядке их предстоящих дней рождения?
-
21-09-2019 - |
Вопрос
У меня есть код для чтения контактных данных и для чтения дней рождения.Но как мне получить список контактов в порядке их предстоящего дня рождения?
Для единственного контакта, идентифицированного id
, Я получаю подробности и дату рождения вот так:
Cursor c = null;
try {
Uri uri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI, id);
c = ctx.getContentResolver().query(uri, null, null, null, null);
if (c != null) {
if (c.moveToFirst()) {
DatabaseUtils.cursorRowToContentValues(c, data);
}
}
c.close();
// read birthday
c = ctx.getContentResolver()
.query(
Data.CONTENT_URI,
new String[] { Event.DATA },
Data.CONTACT_ID + "=" + id + " AND "
+ Data.MIMETYPE + "= '"
+ Event.CONTENT_ITEM_TYPE + "' AND "
+ Event.TYPE + "=" + Event.TYPE_BIRTHDAY,
null, Data.DISPLAY_NAME);
if (c != null) {
try {
if (c.moveToFirst()) {
this.setBirthday(c.getString(0));
}
} finally {
c.close();
}
}
return super.load(id);
} catch (Exception e) {
Log.v(TAG(), e.getMessage(), e);
e.printStackTrace();
return false;
} finally {
if (c != null)
c.close();
}
и код для чтения всех контактов такой:
public Cursor getList() {
// Get the base URI for the People table in the Contacts content
// provider.
Uri contacts = ContactsContract.Contacts.CONTENT_URI;
// Make the query.
ContentResolver cr = ctx.getContentResolver();
// Form an array specifying which columns to return.
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME };
Cursor managedCursor = cr.query(contacts, projection, null, null,
ContactsContract.Contacts.DISPLAY_NAME
+ " COLLATE LOCALIZED ASC");
return managedCursor;
}
Решение
Я сделал это наоборот - выделил непосредственно таблицу данных, в которой хранится день рождения.
private static final int UPCOMING_COUNT = 10;
public static List<BContact> upcomingBirthday(Context ctx) {
String today = new SimpleDateFormat("MM-dd").format(new Date());
List<BContact> firstPart = upcomingBirthday(ctx, today, "12-31", UPCOMING_COUNT);
if (firstPart.size() < UPCOMING_COUNT) {
firstPart.addAll(upcomingBirthday(ctx, "01-01", today, UPCOMING_COUNT - firstPart.size()));
}
return firstPart;
}
public static List<BContact> upcomingBirthday(Context ctx, String fromDate, String toDate, int rows) {
Uri dataUri = ContactsContract.Data.CONTENT_URI;
String[] projection = new String[] { ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.CommonDataKinds.Event.CONTACT_ID,
ContactsContract.CommonDataKinds.Event.START_DATE
};
Cursor c = ctx.getContentResolver().query(
dataUri,
projection,
ContactsContract.Data.MIMETYPE + "= ? AND " +
ContactsContract.CommonDataKinds.Event.TYPE + "=" + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY +
" AND substr(" + ContactsContract.CommonDataKinds.Event.START_DATE + ",6) >= ?" +
" AND substr(" + ContactsContract.CommonDataKinds.Event.START_DATE + ",6) <= ?" ,
new String[] {ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE, fromDate, toDate},
"substr("+ ContactsContract.CommonDataKinds.Event.START_DATE +",6)");
List<BContact> result = new ArrayList<BContact>();
int i=0;
while (c.moveToNext() && i<rows) {
result.add(new BContact(c.getString(0), c.getString(1), c.getString(2)));
i++;
}
c.close();
return result;
}
Выбранный вызывается дважды - один звонок с сегодняшнего дня по 12/31 и второй звонок с 01/01 по сегодняшний день.Я ограничиваю возвращаемые строки 10, но это не обязательно.
Редактировать: Я обнаружил, что это не будет работать на всех телефонах Android, поскольку даты рождения хранятся в разных форматах.Таким образом, вы должны загрузить все дни рождения (неупорядоченные), проанализировать их и отсортировать в памяти.#Потерпеть неудачу
Другие советы
Я думаю, я бы отсортировал список по дням рождения, затем скопировал этот список во второй список, используя сегодняшнюю дату в качестве "нулевой даты". Похоже, было бы чище сделать это таким образом, чем пытаться выполнить соответствующий запрос, хотя это может быть немного медленнее.
В итоге я пришел к такому решению
- создал таблицу владельцев данных в моей базе данных SQLite для хранения идентификатора контакта, имени, даты рождения
- читать контакты, у которых установлен день рождения
- вставьте контакты с днем рождения в таблицу
- возвращает курсор, который выполняет rawQuery при вычислении текущего дня рождения в SQL
итак, в финале у меня получился курсор с идентификатором контактов, отображаемым именем и днем рождения из базы данных в нужном мне порядке
Возможно, вы хотите использовать CursorJoiner, как в следующем ответе:http://www.mail-archive.com/android-developers@googlegroups.com/msg44317.html
У меня есть похожая проблема, которую я еще не решил, поэтому я хотел бы знать, можете ли вы заставить это работать.
Измените параметр сортировки при вызове query() в getList().В настоящее время для него установлено значение DISPLAY_NAME.Попробуйте TYPE_BIRTHDAY.