From aa806b7ce48d4ef9f985121ca88373b69705902b Mon Sep 17 00:00:00 2001 From: M66B Date: Mon, 6 May 2019 19:19:37 +0200 Subject: [PATCH] Read all contacts at startup --- FAQ.md | 1 - .../java/eu/faircode/email/ApplicationEx.java | 5 + .../java/eu/faircode/email/ContactInfo.java | 101 +++++++++--------- app/src/main/java/eu/faircode/email/Core.java | 8 ++ .../java/eu/faircode/email/WorkerCleanup.java | 29 ----- 5 files changed, 62 insertions(+), 82 deletions(-) diff --git a/FAQ.md b/FAQ.md index acb609df7d..636046a6c8 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1591,7 +1591,6 @@ About each four hours FairEmail runs a cleanup job that: * Removes old image files * Removes old local contacts * Removes old log entries -* Updates contact photos of messages You can see when the last cleanup was performed at the bottom of the advanced options. diff --git a/app/src/main/java/eu/faircode/email/ApplicationEx.java b/app/src/main/java/eu/faircode/email/ApplicationEx.java index 330061c9aa..898450a907 100644 --- a/app/src/main/java/eu/faircode/email/ApplicationEx.java +++ b/app/src/main/java/eu/faircode/email/ApplicationEx.java @@ -33,6 +33,7 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.DeadSystemException; +import android.os.Handler; import android.os.RemoteException; import android.webkit.CookieManager; @@ -91,10 +92,14 @@ public class ApplicationEx extends Application { }); upgrade(this); + createNotificationChannels(); + if (Helper.hasWebView(this)) CookieManager.getInstance().setAcceptCookie(false); + MessageHelper.setSystemProperties(); + ContactInfo.init(this, new Handler()); Core.init(this); } diff --git a/app/src/main/java/eu/faircode/email/ContactInfo.java b/app/src/main/java/eu/faircode/email/ContactInfo.java index f54437c7e8..a3f41ffc36 100644 --- a/app/src/main/java/eu/faircode/email/ContactInfo.java +++ b/app/src/main/java/eu/faircode/email/ContactInfo.java @@ -23,6 +23,7 @@ import android.Manifest; import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; +import android.database.ContentObserver; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -34,6 +35,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.net.Uri; +import android.os.Handler; import android.provider.ContactsContract; import android.util.TypedValue; @@ -43,6 +45,7 @@ import java.io.InputStream; import java.util.Date; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import javax.mail.Address; import javax.mail.internet.InternetAddress; @@ -54,10 +57,10 @@ public class ContactInfo { private Uri lookupUri; private long time; - private static Map emailLookupInfo = new HashMap<>(); + private static Object lock = new Object(); + private static Map emailLookup = new ConcurrentHashMap<>(); private static Map emailContactInfo = new HashMap<>(); - private static final long CACHE_LOOKUP_DURATION = 120 * 60 * 1000L; private static final long CACHE_CONTACT_DURATION = 60 * 1000L; private ContactInfo() { @@ -93,9 +96,6 @@ public class ContactInfo { } static void clearCache() { - synchronized (emailLookupInfo) { - emailLookupInfo.clear(); - } synchronized (emailContactInfo) { emailContactInfo.clear(); } @@ -214,65 +214,62 @@ public class ContactInfo { return info; } - static Uri getLookupUri(Context context, Address[] addresses) { - if (!Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) - return null; + static void init(final Context context, Handler handler) { + if (Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) { + ContentObserver observer = new ContentObserver(handler) { + @Override + public void onChange(boolean selfChange, Uri uri) { + Log.i("Contact changed uri=" + uri); + emailLookup = getEmailLookup(context); + } + }; - if (addresses == null || addresses.length == 0) + emailLookup = getEmailLookup(context); + + Uri uri = ContactsContract.CommonDataKinds.Email.CONTENT_URI; + Log.i("Observing uri=" + uri); + context.getContentResolver().registerContentObserver(uri, true, observer); + } + } + + static Uri getLookupUri(Context context, Address[] addresses) { + if (addresses == null) return null; - InternetAddress address = (InternetAddress) addresses[0]; - synchronized (emailLookupInfo) { - LookupInfo info = emailLookupInfo.get(address.getAddress()); - if (info != null && !info.isExpired()) - return info.uri; + for (Address from : addresses) { + String email = ((InternetAddress) from).getAddress(); + if (emailLookup.containsKey(email)) + return emailLookup.get(email); } - try { + return null; + } + + private static Map getEmailLookup(Context context) { + Map all = new ConcurrentHashMap<>(); + + if (Helper.hasPermission(context, Manifest.permission.READ_CONTACTS)) { 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.LOOKUP_KEY, + ContactsContract.CommonDataKinds.Email.ADDRESS }, - ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", - new String[]{ - address.getAddress() - }, null)) { - - Uri uri = 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); - - uri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); + ContactsContract.CommonDataKinds.Email.ADDRESS + " <> ''", + null, null)) { + while (cursor != null && cursor.moveToNext()) { + long contactId = cursor.getLong(0); + String lookupKey = cursor.getString(1); + String email = cursor.getString(2); + + Uri uri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); + all.put(email, uri); } - - LookupInfo info = new LookupInfo(); - info.uri = uri; - info.time = new Date().getTime(); - - synchronized (emailLookupInfo) { - emailLookupInfo.put(address.getAddress(), info); - } - - return info.uri; } - } catch (Throwable ex) { - Log.e(ex); - return null; } - } - - private static class LookupInfo { - private Uri uri; - private long time; - private boolean isExpired() { - return (new Date().getTime() - time > CACHE_LOOKUP_DURATION); - } + Log.i("Read email/uri=" + all.size()); + return all; } -} +} \ No newline at end of file diff --git a/app/src/main/java/eu/faircode/email/Core.java b/app/src/main/java/eu/faircode/email/Core.java index edc1080d88..c0d1d54417 100644 --- a/app/src/main/java/eu/faircode/email/Core.java +++ b/app/src/main/java/eu/faircode/email/Core.java @@ -1383,6 +1383,14 @@ class Core { Log.i(folder.name + " updated id=" + message.id + " uid=" + message.uid + " unbrowse"); } + Uri uri = ContactInfo.getLookupUri(context, message.from); + String avatar = (uri == null ? null : uri.toString()); + if (!Objects.equals(message.avatar, avatar)) { + update = true; + message.avatar = avatar; + Log.i(folder.name + " updated id=" + message.id + " uid=" + message.uid + " avatar=" + avatar); + } + if (update) try { db.beginTransaction(); diff --git a/app/src/main/java/eu/faircode/email/WorkerCleanup.java b/app/src/main/java/eu/faircode/email/WorkerCleanup.java index 9e0f82d173..6d3e1489e6 100644 --- a/app/src/main/java/eu/faircode/email/WorkerCleanup.java +++ b/app/src/main/java/eu/faircode/email/WorkerCleanup.java @@ -21,7 +21,6 @@ package eu.faircode.email; import android.content.Context; import android.content.SharedPreferences; -import android.net.Uri; import android.os.Build; import androidx.annotation.NonNull; @@ -39,7 +38,6 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; -import java.util.Objects; import java.util.concurrent.TimeUnit; public class WorkerCleanup extends Worker { @@ -146,33 +144,6 @@ public class WorkerCleanup extends Worker { Log.i("Cleanup log"); int logs = db.log().deleteLogs(now - KEEP_LOG_DURATION); Log.i("Deleted logs=" + logs); - - Log.i("Update lookup URIs"); - ContactInfo.clearCache(); - List folders = db.folder().getSynchronizingFolders(); - for (EntityFolder folder : folders) { - Calendar cal = Calendar.getInstance(); - cal.add(Calendar.DAY_OF_MONTH, -folder.sync_days); - cal.set(Calendar.HOUR_OF_DAY, 0); - cal.set(Calendar.MINUTE, 0); - cal.set(Calendar.SECOND, 0); - cal.set(Calendar.MILLISECOND, 0); - long sync_time = cal.getTimeInMillis(); - if (sync_time < 0) - sync_time = 0; - Log.i("Update lookup URIs " + folder.name + " before " + new Date(sync_time)); - - List avatars = db.message().getAvatars(folder.id, sync_time); - for (TupleMessageLookup message : avatars) { - Uri uri = (message.avatar == null ? null : Uri.parse(message.avatar)); - Uri lookup = ContactInfo.getLookupUri(context, message.from); - if (!Objects.equals(uri, lookup)) { - Log.i("Updating email=" + MessageHelper.formatAddresses(message.from) + " uri=" + lookup); - db.message().setMessageAvatar(message.id, lookup == null ? null : lookup.toString()); - } - } - } - Log.i("Updated lookup URIs"); } catch (Throwable ex) { Log.e(ex); } finally {