mirror of https://github.com/M66B/FairEmail.git
Get contact info in real-time
This commit is contained in:
parent
274deddc88
commit
c3de24c60f
|
@ -73,7 +73,6 @@ import org.xml.sax.XMLReader;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
@ -414,9 +413,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
if (!outgoing && (avatars || identicons)) {
|
if (!outgoing && (avatars || identicons)) {
|
||||||
Bundle aargs = new Bundle();
|
Bundle aargs = new Bundle();
|
||||||
aargs.putLong("id", message.id);
|
aargs.putLong("id", message.id);
|
||||||
aargs.putString("uri", message.avatar);
|
aargs.putSerializable("addresses", message.from);
|
||||||
if (message.from != null && message.from.length > 0)
|
|
||||||
aargs.putString("from", message.from[0].toString());
|
|
||||||
|
|
||||||
new SimpleTask<ContactInfo>() {
|
new SimpleTask<ContactInfo>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -428,39 +425,16 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ContactInfo onExecute(Context context, Bundle args) {
|
protected ContactInfo onExecute(Context context, Bundle args) {
|
||||||
String uri = args.getString("uri");
|
Address[] addresses = (Address[]) args.getSerializable("addresses");
|
||||||
|
|
||||||
ContactInfo info = new ContactInfo();
|
ContactInfo info = ContactInfo.get(context, addresses);
|
||||||
ContentResolver resolver = context.getContentResolver();
|
|
||||||
|
|
||||||
if (contacts && avatars && uri != null)
|
if ((info == null || !info.hasPhoto()) && identicons) {
|
||||||
try {
|
Drawable ident = new BitmapDrawable(
|
||||||
InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(resolver, Uri.parse(uri));
|
|
||||||
if (is != null)
|
|
||||||
info.avatar = Drawable.createFromStream(is, "avatar");
|
|
||||||
} catch (SecurityException ex) {
|
|
||||||
Log.e(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
String from = args.getString("from");
|
|
||||||
if (info.avatar == null && identicons && from != null)
|
|
||||||
info.avatar = new BitmapDrawable(
|
|
||||||
context.getResources(),
|
context.getResources(),
|
||||||
Identicon.generate(from, dp24, 5, "light".equals(theme)));
|
Identicon.generate(addresses[0].toString(),
|
||||||
|
dp24, 5, "light".equals(theme)));
|
||||||
if (contacts && uri != null) {
|
info = new ContactInfo(ident, (info == null ? null : info.getDisplayName()));
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
cursor = resolver.query(
|
|
||||||
Uri.parse(uri),
|
|
||||||
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
|
|
||||||
null, null, null);
|
|
||||||
if (cursor != null && cursor.moveToNext())
|
|
||||||
info.displayName = cursor.getString(0);
|
|
||||||
} finally {
|
|
||||||
if (cursor != null)
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
@ -471,19 +445,16 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
long id = args.getLong("id");
|
long id = args.getLong("id");
|
||||||
|
|
||||||
if ((long) ivAvatar.getTag() == id) {
|
if ((long) ivAvatar.getTag() == id) {
|
||||||
if (info.avatar == null)
|
if (info == null || !info.hasPhoto())
|
||||||
ivAvatar.setImageResource(R.drawable.baseline_person_24);
|
ivAvatar.setImageResource(R.drawable.baseline_person_24);
|
||||||
else
|
else
|
||||||
ivAvatar.setImageDrawable(info.avatar);
|
ivAvatar.setImageDrawable(info.getPhotoDrawable());
|
||||||
ivAvatar.setVisibility(View.VISIBLE);
|
ivAvatar.setVisibility(View.VISIBLE);
|
||||||
} else
|
}
|
||||||
Log.i("Skipping avatar");
|
|
||||||
|
|
||||||
if ((long) tvFrom.getTag() == id) {
|
if ((long) tvFrom.getTag() == id) {
|
||||||
if (info.displayName != null) {
|
if (info != null && info.hasDisplayName())
|
||||||
Log.i("Using contact name=" + info.displayName);
|
tvFrom.setText(info.getDisplayName());
|
||||||
tvFrom.setText(info.displayName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2047,7 +2018,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
this.threading = prefs.getBoolean("threading", true);
|
this.threading = prefs.getBoolean("threading", true);
|
||||||
this.contacts = (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)
|
this.contacts = (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)
|
||||||
== PackageManager.PERMISSION_GRANTED);
|
== PackageManager.PERMISSION_GRANTED);
|
||||||
this.avatars = (prefs.getBoolean("avatars", true) && this.contacts);
|
this.avatars = prefs.getBoolean("avatars", true);
|
||||||
this.identicons = prefs.getBoolean("identicons", false);
|
this.identicons = prefs.getBoolean("identicons", false);
|
||||||
this.preview = prefs.getBoolean("preview", false);
|
this.preview = prefs.getBoolean("preview", false);
|
||||||
this.confirm = prefs.getBoolean("confirm", false);
|
this.confirm = prefs.getBoolean("confirm", false);
|
||||||
|
@ -2203,11 +2174,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ContactInfo {
|
|
||||||
Drawable avatar;
|
|
||||||
String displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IProperties {
|
interface IProperties {
|
||||||
void setValue(String name, long id, boolean enabled);
|
void setValue(String name, long id, boolean enabled);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
package eu.faircode.email;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.mail.Address;
|
||||||
|
import javax.mail.internet.InternetAddress;
|
||||||
|
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
public class ContactInfo {
|
||||||
|
private InputStream is;
|
||||||
|
private Drawable photo;
|
||||||
|
private String displayName;
|
||||||
|
private Uri lookupUri;
|
||||||
|
|
||||||
|
ContactInfo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ContactInfo(String displayName) {
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContactInfo(Drawable photo, String displayName) {
|
||||||
|
this.photo = photo;
|
||||||
|
this.displayName = displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap getPhotoBitmap() {
|
||||||
|
return BitmapFactory.decodeStream(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
Drawable getPhotoDrawable() {
|
||||||
|
if (photo != null)
|
||||||
|
return photo;
|
||||||
|
|
||||||
|
if (is == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return Drawable.createFromStream(is, displayName == null ? "Photo" : displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasPhoto() {
|
||||||
|
return (is != null || photo != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getDisplayName() {
|
||||||
|
return displayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasDisplayName() {
|
||||||
|
return (displayName != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri getLookupUri() {
|
||||||
|
return lookupUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasLookupUri() {
|
||||||
|
return (lookupUri != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ContactInfo get(Context context, Address[] addresses) {
|
||||||
|
if (addresses == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (Address address : addresses) {
|
||||||
|
Cursor cursor = null;
|
||||||
|
try {
|
||||||
|
ContentResolver resolver = context.getContentResolver();
|
||||||
|
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[]{
|
||||||
|
((InternetAddress) 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);
|
||||||
|
|
||||||
|
ContactInfo info = new ContactInfo();
|
||||||
|
info.is = ContactsContract.Contacts.openContactPhotoInputStream(resolver, lookupUri);
|
||||||
|
info.displayName = cursor.getString(colDisplayName);
|
||||||
|
info.lookupUri = lookupUri;
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (cursor != null)
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
Log.e(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,16 +19,11 @@ package eu.faircode.email;
|
||||||
Copyright 2018-2019 by Marcel Bokhorst (M66B)
|
Copyright 2018-2019 by Marcel Bokhorst (M66B)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ContentResolver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.provider.ContactsContract;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
|
@ -43,10 +38,8 @@ import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import javax.mail.Address;
|
import javax.mail.Address;
|
||||||
import javax.mail.internet.InternetAddress;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
import androidx.room.ForeignKey;
|
import androidx.room.ForeignKey;
|
||||||
import androidx.room.Index;
|
import androidx.room.Index;
|
||||||
|
@ -105,7 +98,7 @@ public class EntityMessage implements Serializable {
|
||||||
public String deliveredto;
|
public String deliveredto;
|
||||||
public String inreplyto;
|
public String inreplyto;
|
||||||
public String thread; // compose = null
|
public String thread; // compose = null
|
||||||
public String avatar; // Contact lookup URI
|
public String avatar; // obsolete
|
||||||
public String sender; // sort key
|
public String sender; // sort key
|
||||||
public Address[] from;
|
public Address[] from;
|
||||||
public Address[] to;
|
public Address[] to;
|
||||||
|
@ -210,60 +203,6 @@ public class EntityMessage implements Serializable {
|
||||||
return new File(dir, Long.toString(id));
|
return new File(dir, Long.toString(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getLookupUri(Context context, Address[] froms) {
|
|
||||||
if (froms == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS)
|
|
||||||
!= PackageManager.PERMISSION_GRANTED)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (Address from : froms) {
|
|
||||||
String email = ((InternetAddress) from).getAddress();
|
|
||||||
|
|
||||||
synchronized (emailLookupUri) {
|
|
||||||
Uri lookupUri = emailLookupUri.get(email);
|
|
||||||
if (lookupUri != null)
|
|
||||||
return lookupUri.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
ContentResolver resolver = context.getContentResolver();
|
|
||||||
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[]{email}, 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 lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
|
|
||||||
|
|
||||||
synchronized (emailLookupUri) {
|
|
||||||
emailLookupUri.put(email, lookupUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lookupUri.toString();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
if (cursor != null)
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
Log.e(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void snooze(Context context, long id, Long wakeup) {
|
static void snooze(Context context, long id, Long wakeup) {
|
||||||
Intent snoozed = new Intent(context, ServiceSynchronize.class);
|
Intent snoozed = new Intent(context, ServiceSynchronize.class);
|
||||||
snoozed.setAction("snooze:" + id);
|
snoozed.setAction("snooze:" + id);
|
||||||
|
@ -294,7 +233,6 @@ public class EntityMessage implements Serializable {
|
||||||
//(this.deliveredto == null ? other.deliveredto == null : this.deliveredto.equals(other.deliveredto)) &&
|
//(this.deliveredto == null ? other.deliveredto == null : this.deliveredto.equals(other.deliveredto)) &&
|
||||||
//(this.inreplyto == null ? other.inreplyto == null : this.inreplyto.equals(other.inreplyto)) &&
|
//(this.inreplyto == null ? other.inreplyto == null : this.inreplyto.equals(other.inreplyto)) &&
|
||||||
(this.thread == null ? other.thread == null : this.thread.equals(other.thread)) &&
|
(this.thread == null ? other.thread == null : this.thread.equals(other.thread)) &&
|
||||||
(this.avatar == null ? other.avatar == null : this.avatar.equals(other.avatar)) &&
|
|
||||||
MessageHelper.equal(this.from, other.from) &&
|
MessageHelper.equal(this.from, other.from) &&
|
||||||
MessageHelper.equal(this.to, other.to) &&
|
MessageHelper.equal(this.to, other.to) &&
|
||||||
MessageHelper.equal(this.cc, other.cc) &&
|
MessageHelper.equal(this.cc, other.cc) &&
|
||||||
|
@ -342,7 +280,6 @@ public class EntityMessage implements Serializable {
|
||||||
(this.deliveredto == null ? other.deliveredto == null : this.deliveredto.equals(other.deliveredto)) &&
|
(this.deliveredto == null ? other.deliveredto == null : this.deliveredto.equals(other.deliveredto)) &&
|
||||||
(this.inreplyto == null ? other.inreplyto == null : this.inreplyto.equals(other.inreplyto)) &&
|
(this.inreplyto == null ? other.inreplyto == null : this.inreplyto.equals(other.inreplyto)) &&
|
||||||
(this.thread == null ? other.thread == null : this.thread.equals(other.thread)) &&
|
(this.thread == null ? other.thread == null : this.thread.equals(other.thread)) &&
|
||||||
(this.avatar == null ? other.avatar == null : this.avatar.equals(other.avatar)) &&
|
|
||||||
MessageHelper.equal(this.from, other.from) &&
|
MessageHelper.equal(this.from, other.from) &&
|
||||||
MessageHelper.equal(this.to, other.to) &&
|
MessageHelper.equal(this.to, other.to) &&
|
||||||
MessageHelper.equal(this.cc, other.cc) &&
|
MessageHelper.equal(this.cc, other.cc) &&
|
||||||
|
|
|
@ -214,7 +214,6 @@ public class EntityRule {
|
||||||
reply.subject = context.getString(R.string.title_subject_reply, message.subject == null ? "" : message.subject);
|
reply.subject = context.getString(R.string.title_subject_reply, message.subject == null ? "" : message.subject);
|
||||||
reply.sender = MessageHelper.getSortKey(reply.from);
|
reply.sender = MessageHelper.getSortKey(reply.from);
|
||||||
reply.received = new Date().getTime();
|
reply.received = new Date().getTime();
|
||||||
reply.avatar = EntityMessage.getLookupUri(context, reply.from);
|
|
||||||
reply.id = db.message().insertMessage(reply);
|
reply.id = db.message().insertMessage(reply);
|
||||||
reply.write(context, body);
|
reply.write(context, body);
|
||||||
db.message().setMessageContent(reply.id, true, HtmlHelper.getPreview(body));
|
db.message().setMessageContent(reply.id, true, HtmlHelper.getPreview(body));
|
||||||
|
|
|
@ -1551,7 +1551,6 @@ public class FragmentCompose extends FragmentBase {
|
||||||
result.draft.sender = MessageHelper.getSortKey(result.draft.from);
|
result.draft.sender = MessageHelper.getSortKey(result.draft.from);
|
||||||
|
|
||||||
result.draft.received = new Date().getTime();
|
result.draft.received = new Date().getTime();
|
||||||
result.draft.avatar = EntityMessage.getLookupUri(context, result.draft.from);
|
|
||||||
|
|
||||||
result.draft.id = db.message().insertMessage(result.draft);
|
result.draft.id = db.message().insertMessage(result.draft);
|
||||||
result.draft.write(context, body == null ? "" : body);
|
result.draft.write(context, body == null ? "" : body);
|
||||||
|
|
|
@ -19,7 +19,6 @@ package eu.faircode.email;
|
||||||
Copyright 2018-2019 by Marcel Bokhorst (M66B)
|
Copyright 2018-2019 by Marcel Bokhorst (M66B)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import android.Manifest;
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
@ -31,10 +30,7 @@ import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.Icon;
|
|
||||||
import android.media.RingtoneManager;
|
import android.media.RingtoneManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
|
@ -47,7 +43,6 @@ import android.os.Handler;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.provider.ContactsContract;
|
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.LongSparseArray;
|
import android.util.LongSparseArray;
|
||||||
|
@ -70,7 +65,6 @@ import java.io.BufferedOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
|
@ -483,10 +477,6 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
return notifications;
|
return notifications;
|
||||||
|
|
||||||
boolean pro = Helper.isPro(this);
|
boolean pro = Helper.isPro(this);
|
||||||
boolean contacts =
|
|
||||||
(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
|
|
||||||
== PackageManager.PERMISSION_GRANTED);
|
|
||||||
|
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
|
||||||
// https://developer.android.com/training/notify-user/group
|
// https://developer.android.com/training/notify-user/group
|
||||||
|
@ -495,28 +485,13 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
String summary = getResources().getQuantityString(
|
String summary = getResources().getQuantityString(
|
||||||
R.plurals.title_notification_unseen, messages.size(), messages.size());
|
R.plurals.title_notification_unseen, messages.size(), messages.size());
|
||||||
|
|
||||||
Map<TupleMessageEx, String> messageFrom = new HashMap<>();
|
// Get contact info
|
||||||
|
Map<TupleMessageEx, ContactInfo> messageContact = new HashMap<>();
|
||||||
for (TupleMessageEx message : messages) {
|
for (TupleMessageEx message : messages) {
|
||||||
String from = null;
|
ContactInfo info = ContactInfo.get(this, message.from);
|
||||||
if (!TextUtils.isEmpty(message.avatar) && contacts) {
|
if (info == null)
|
||||||
Cursor cursor = null;
|
info = new ContactInfo(MessageHelper.formatAddressesShort(message.from));
|
||||||
try {
|
messageContact.put(message, info);
|
||||||
cursor = getContentResolver().query(
|
|
||||||
Uri.parse(message.avatar),
|
|
||||||
new String[]{ContactsContract.Contacts.DISPLAY_NAME},
|
|
||||||
null, null, null);
|
|
||||||
if (cursor != null && cursor.moveToNext())
|
|
||||||
from = cursor.getString(0);
|
|
||||||
} finally {
|
|
||||||
if (cursor != null)
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from == null)
|
|
||||||
from = MessageHelper.formatAddressesShort(message.from);
|
|
||||||
|
|
||||||
messageFrom.put(message, from);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build pending intent
|
// Build pending intent
|
||||||
|
@ -596,7 +571,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT);
|
DateFormat df = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT);
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (EntityMessage message : messages) {
|
for (EntityMessage message : messages) {
|
||||||
sb.append("<strong>").append(messageFrom.get(message)).append("</strong>");
|
sb.append("<strong>").append(messageContact.get(message).getDisplayName()).append("</strong>");
|
||||||
if (!TextUtils.isEmpty(message.subject))
|
if (!TextUtils.isEmpty(message.subject))
|
||||||
sb.append(": ").append(message.subject);
|
sb.append(": ").append(message.subject);
|
||||||
sb.append(" ").append(df.format(message.received));
|
sb.append(" ").append(df.format(message.received));
|
||||||
|
@ -611,6 +586,8 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
notifications.add(builder.build());
|
notifications.add(builder.build());
|
||||||
|
|
||||||
for (TupleMessageEx message : messages) {
|
for (TupleMessageEx message : messages) {
|
||||||
|
ContactInfo info = messageContact.get(message);
|
||||||
|
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putLong("id", message.content ? message.id : -message.id);
|
args.putLong("id", message.content ? message.id : -message.id);
|
||||||
|
|
||||||
|
@ -667,7 +644,7 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
mbuilder
|
mbuilder
|
||||||
.addExtras(args)
|
.addExtras(args)
|
||||||
.setSmallIcon(R.drawable.baseline_email_white_24)
|
.setSmallIcon(R.drawable.baseline_email_white_24)
|
||||||
.setContentTitle(messageFrom.get(message))
|
.setContentTitle(info.getDisplayName())
|
||||||
.setSubText(message.accountName + " · " + folderName)
|
.setSubText(message.accountName + " · " + folderName)
|
||||||
.setContentIntent(piContent)
|
.setContentIntent(piContent)
|
||||||
.setWhen(message.received)
|
.setWhen(message.received)
|
||||||
|
@ -702,47 +679,16 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
mbuilder.setStyle(new Notification.BigTextStyle().bigText(ex.toString()));
|
mbuilder.setStyle(new Notification.BigTextStyle().bigText(ex.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(message.avatar)) {
|
if (info.hasPhoto())
|
||||||
if (contacts) {
|
mbuilder.setLargeIcon(info.getPhotoBitmap());
|
||||||
Cursor cursor = null;
|
|
||||||
try {
|
|
||||||
cursor = getContentResolver().query(
|
|
||||||
Uri.parse(message.avatar),
|
|
||||||
new String[]{
|
|
||||||
ContactsContract.Contacts._ID,
|
|
||||||
ContactsContract.Contacts.LOOKUP_KEY
|
|
||||||
},
|
|
||||||
null, null, null);
|
|
||||||
if (cursor != null && cursor.moveToNext()) {
|
|
||||||
if (true || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
||||||
Uri uri = ContactsContract.Contacts.getLookupUri(
|
|
||||||
cursor.getLong(cursor.getColumnIndex(ContactsContract.Contacts._ID)),
|
|
||||||
cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)));
|
|
||||||
InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(
|
|
||||||
getContentResolver(), uri);
|
|
||||||
mbuilder.setLargeIcon(BitmapFactory.decodeStream(is));
|
|
||||||
} else {
|
|
||||||
Uri photo = Uri.withAppendedPath(
|
|
||||||
ContactsContract.Contacts.CONTENT_URI,
|
|
||||||
cursor.getLong(0) + "/photo");
|
|
||||||
mbuilder.setLargeIcon(Icon.createWithContentUri(photo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
Log.e(ex);
|
|
||||||
} finally {
|
|
||||||
if (cursor != null)
|
|
||||||
cursor.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (info.hasLookupUri())
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
|
||||||
mbuilder.addPerson(new Person.Builder()
|
mbuilder.addPerson(new Person.Builder()
|
||||||
.setUri(message.avatar)
|
.setUri(info.getLookupUri().toString())
|
||||||
.build());
|
.build());
|
||||||
else
|
else
|
||||||
mbuilder.addPerson(message.avatar);
|
mbuilder.addPerson(info.getLookupUri().toString());
|
||||||
}
|
|
||||||
|
|
||||||
if (message.accountColor != null) {
|
if (message.accountColor != null) {
|
||||||
mbuilder.setColor(message.accountColor);
|
mbuilder.setColor(message.accountColor);
|
||||||
|
@ -2638,12 +2584,6 @@ public class ServiceSynchronize extends LifecycleService {
|
||||||
if (message == null)
|
if (message == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (message.avatar == null && !folder.isOutgoing()) {
|
|
||||||
message.avatar = EntityMessage.getLookupUri(context, message.from);
|
|
||||||
if (message.avatar != null)
|
|
||||||
db.message().updateMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (download) {
|
if (download) {
|
||||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
long maxSize = prefs.getInt("download", 32768);
|
long maxSize = prefs.getInt("download", 32768);
|
||||||
|
|
Loading…
Reference in New Issue