package eu.faircode.email; import android.Manifest; import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.preference.PreferenceManager; import android.provider.ContactsContract; import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.mail.Address; import javax.mail.internet.InternetAddress; public class ContactInfo { private String email; private Bitmap bitmap; private String displayName; private Uri lookupUri; private long time; private static Map emailContactInfo = new HashMap<>(); private static final long CACHE_DURATION = 60 * 1000L; private ContactInfo() { } boolean hasPhoto() { return (bitmap != null); } Bitmap getPhotoBitmap() { return bitmap; } String getDisplayName(boolean name_email) { if (!name_email && displayName != null) return displayName; else if (displayName == null) return (email == null ? "" : email); else return displayName + " <" + email + ">"; } boolean hasLookupUri() { return (lookupUri != null); } Uri getLookupUri() { return lookupUri; } private boolean isExpired() { return (new Date().getTime() - time > CACHE_DURATION); } static void clearCache() { synchronized (emailContactInfo) { emailContactInfo.clear(); } } static ContactInfo get(Context context, Address[] addresses, boolean cacheOnly) { if (addresses == null || addresses.length == 0) return new ContactInfo(); InternetAddress address = (InternetAddress) addresses[0]; String key = MessageHelper.formatAddresses(new Address[]{address}); synchronized (emailContactInfo) { ContactInfo info = emailContactInfo.get(key); if (info != null && !info.isExpired()) return info; } if (cacheOnly) return null; ContactInfo info = new ContactInfo(); info.email = address.getAddress(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); if (Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) try { ContentResolver resolver = context.getContentResolver(); try (Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, new String[]{ ContactsContract.CommonDataKinds.Photo.CONTACT_ID, ContactsContract.Contacts.LOOKUP_KEY, ContactsContract.Contacts.DISPLAY_NAME }, ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", new String[]{ address.getAddress() }, null)) { if (cursor != null && cursor.moveToNext()) { int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); int colLookupKey = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY); int colDisplayName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); long contactId = cursor.getLong(colContactId); String lookupKey = cursor.getString(colLookupKey); Uri lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); boolean avatars = prefs.getBoolean("avatars", true); if (avatars) { InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(resolver, lookupUri); info.bitmap = BitmapFactory.decodeStream(is); } info.displayName = cursor.getString(colDisplayName); info.lookupUri = lookupUri; } } } catch (Throwable ex) { Log.e(ex); } if (info.bitmap == null) { boolean identicons = prefs.getBoolean("identicons", false); if (identicons) { String theme = prefs.getString("theme", "light"); int dp = Helper.dp2pixels(context, 48); info.bitmap = Identicon.generate(key, dp, 5, "light".equals(theme)); } } if (info.displayName == null) info.displayName = address.getPersonal(); synchronized (emailContactInfo) { emailContactInfo.put(key, info); } info.time = new Date().getTime(); return info; } static Uri getLookupUri(Context context, Address[] addresses) { if (addresses == null || addresses.length == 0) return null; InternetAddress address = (InternetAddress) addresses[0]; if (!Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) return null; try { ContentResolver resolver = context.getContentResolver(); try (Cursor cursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, new String[]{ ContactsContract.CommonDataKinds.Photo.CONTACT_ID, ContactsContract.Contacts.LOOKUP_KEY }, ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", new String[]{ address.getAddress() }, null)) { if (cursor != null && cursor.moveToNext()) { int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); int colLookupKey = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY); long contactId = cursor.getLong(colContactId); String lookupKey = cursor.getString(colLookupKey); return ContactsContract.Contacts.getLookupUri(contactId, lookupKey); } else return null; } } catch (Throwable ex) { Log.e(ex); return null; } } }