aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/eu/siacs/conversations/services')
-rw-r--r--src/eu/siacs/conversations/services/AbstractConnectionManager.java23
-rw-r--r--src/eu/siacs/conversations/services/AvatarService.java292
-rw-r--r--src/eu/siacs/conversations/services/ImageProvider.java109
-rw-r--r--src/eu/siacs/conversations/services/NotificationService.java290
-rw-r--r--src/eu/siacs/conversations/services/XmppConnectionService.java280
5 files changed, 723 insertions, 271 deletions
diff --git a/src/eu/siacs/conversations/services/AbstractConnectionManager.java b/src/eu/siacs/conversations/services/AbstractConnectionManager.java
new file mode 100644
index 00000000..676a09c9
--- /dev/null
+++ b/src/eu/siacs/conversations/services/AbstractConnectionManager.java
@@ -0,0 +1,23 @@
+package eu.siacs.conversations.services;
+
+public class AbstractConnectionManager {
+ protected XmppConnectionService mXmppConnectionService;
+
+ public AbstractConnectionManager(XmppConnectionService service) {
+ this.mXmppConnectionService = service;
+ }
+
+ public XmppConnectionService getXmppConnectionService() {
+ return this.mXmppConnectionService;
+ }
+
+ public long getAutoAcceptFileSize() {
+ String config = this.mXmppConnectionService.getPreferences().getString(
+ "auto_accept_file_size", "524288");
+ try {
+ return Long.parseLong(config);
+ } catch (NumberFormatException e) {
+ return 524288;
+ }
+ }
+}
diff --git a/src/eu/siacs/conversations/services/AvatarService.java b/src/eu/siacs/conversations/services/AvatarService.java
new file mode 100644
index 00000000..bd27b555
--- /dev/null
+++ b/src/eu/siacs/conversations/services/AvatarService.java
@@ -0,0 +1,292 @@
+package eu.siacs.conversations.services;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Bookmark;
+import eu.siacs.conversations.entities.Contact;
+import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.ListItem;
+import eu.siacs.conversations.entities.MucOptions;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.Typeface;
+import android.net.Uri;
+
+public class AvatarService {
+
+ private static final int FG_COLOR = 0xFFFAFAFA;
+ private static final int TRANSPARENT = 0x00000000;
+
+ private static final String PREFIX_CONTACT = "contact";
+ private static final String PREFIX_CONVERSATION = "conversation";
+ private static final String PREFIX_ACCOUNT = "account";
+ private static final String PREFIX_GENERIC = "generic";
+
+ private ArrayList<Integer> sizes = new ArrayList<Integer>();
+
+ protected XmppConnectionService mXmppConnectionService = null;
+
+ public AvatarService(XmppConnectionService service) {
+ this.mXmppConnectionService = service;
+ }
+
+ public Bitmap get(Contact contact, int size) {
+ final String KEY = key(contact, size);
+ Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY);
+ if (avatar != null) {
+ return avatar;
+ }
+ avatar = mXmppConnectionService.getFileBackend().getAvatar(
+ contact.getAvatar(), size);
+ if (avatar == null) {
+ if (contact.getProfilePhoto() != null) {
+ avatar = mXmppConnectionService.getFileBackend()
+ .cropCenterSquare(Uri.parse(contact.getProfilePhoto()),
+ size);
+ if (avatar == null) {
+ avatar = get(contact.getDisplayName(), size);
+ }
+ } else {
+ avatar = get(contact.getDisplayName(), size);
+ }
+ }
+ this.mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+ return avatar;
+ }
+
+ public void clear(Contact contact) {
+ for (Integer size : sizes) {
+ this.mXmppConnectionService.getBitmapCache().remove(
+ key(contact, size));
+ }
+ }
+
+ private String key(Contact contact, int size) {
+ synchronized (this.sizes) {
+ if (!this.sizes.contains(size)) {
+ this.sizes.add(size);
+ }
+ }
+ return PREFIX_CONTACT + "_" + contact.getAccount().getJid() + "_"
+ + contact.getJid() + "_" + String.valueOf(size);
+ }
+
+ public Bitmap get(ListItem item, int size) {
+ if (item instanceof Contact) {
+ return get((Contact) item, size);
+ } else if (item instanceof Bookmark) {
+ Bookmark bookmark = (Bookmark) item;
+ if (bookmark.getConversation() != null) {
+ return get(bookmark.getConversation(), size);
+ } else {
+ return get(bookmark.getDisplayName(), size);
+ }
+ } else {
+ return get(item.getDisplayName(), size);
+ }
+ }
+
+ public Bitmap get(Conversation conversation, int size) {
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ return get(conversation.getContact(), size);
+ } else {
+ return get(conversation.getMucOptions(), size);
+ }
+ }
+
+ public void clear(Conversation conversation) {
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ clear(conversation.getContact());
+ } else {
+ clear(conversation.getMucOptions());
+ }
+ }
+
+ public Bitmap get(MucOptions mucOptions, int size) {
+ final String KEY = key(mucOptions, size);
+ Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY);
+ if (bitmap != null) {
+ return bitmap;
+ }
+ List<MucOptions.User> users = mucOptions.getUsers();
+ int count = users.size();
+ bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ bitmap.eraseColor(TRANSPARENT);
+
+ if (count == 0) {
+ String name = mucOptions.getConversation().getName();
+ String letter = name.substring(0, 1);
+ int color = this.getColorForName(name);
+ drawTile(canvas, letter, color, 0, 0, size, size);
+ } else if (count == 1) {
+ drawTile(canvas, users.get(0), 0, 0, size, size);
+ } else if (count == 2) {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
+ drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size);
+ } else if (count == 3) {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size);
+ drawTile(canvas, users.get(1), size / 2 + 1, 0, size, size / 2 - 1);
+ drawTile(canvas, users.get(2), size / 2 + 1, size / 2 + 1, size,
+ size);
+ } else if (count == 4) {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1);
+ drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size);
+ drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1);
+ drawTile(canvas, users.get(3), size / 2 + 1, size / 2 + 1, size,
+ size);
+ } else {
+ drawTile(canvas, users.get(0), 0, 0, size / 2 - 1, size / 2 - 1);
+ drawTile(canvas, users.get(1), 0, size / 2 + 1, size / 2 - 1, size);
+ drawTile(canvas, users.get(2), size / 2 + 1, 0, size, size / 2 - 1);
+ drawTile(canvas, "\u2026", 0xFF202020, size / 2 + 1, size / 2 + 1,
+ size, size);
+ }
+ this.mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+ return bitmap;
+ }
+
+ public void clear(MucOptions options) {
+ for (Integer size : sizes) {
+ this.mXmppConnectionService.getBitmapCache().remove(
+ key(options, size));
+ }
+ }
+
+ private String key(MucOptions options, int size) {
+ synchronized (this.sizes) {
+ if (!this.sizes.contains(size)) {
+ this.sizes.add(size);
+ }
+ }
+ return PREFIX_CONVERSATION + "_" + options.getConversation().getUuid()
+ + "_" + String.valueOf(size);
+ }
+
+ public Bitmap get(Account account, int size) {
+ final String KEY = key(account, size);
+ Bitmap avatar = mXmppConnectionService.getBitmapCache().get(KEY);
+ if (avatar != null) {
+ return avatar;
+ }
+ avatar = mXmppConnectionService.getFileBackend().getAvatar(
+ account.getAvatar(), size);
+ if (avatar == null) {
+ avatar = get(account.getJid(), size);
+ }
+ mXmppConnectionService.getBitmapCache().put(KEY, avatar);
+ return avatar;
+ }
+
+ public void clear(Account account) {
+ for (Integer size : sizes) {
+ this.mXmppConnectionService.getBitmapCache().remove(
+ key(account, size));
+ }
+ }
+
+ private String key(Account account, int size) {
+ synchronized (this.sizes) {
+ if (!this.sizes.contains(size)) {
+ this.sizes.add(size);
+ }
+ }
+ return PREFIX_ACCOUNT + "_" + account.getUuid() + "_"
+ + String.valueOf(size);
+ }
+
+ public Bitmap get(String name, int size) {
+ final String KEY = key(name, size);
+ Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY);
+ if (bitmap != null) {
+ return bitmap;
+ }
+ bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ String letter = name.substring(0, 1);
+ int color = this.getColorForName(name);
+ drawTile(canvas, letter, color, 0, 0, size, size);
+ mXmppConnectionService.getBitmapCache().put(KEY, bitmap);
+ return bitmap;
+ }
+
+ private String key(String name, int size) {
+ synchronized (this.sizes) {
+ if (!this.sizes.contains(size)) {
+ this.sizes.add(size);
+ }
+ }
+ return PREFIX_GENERIC + "_" + name + "_" + String.valueOf(size);
+ }
+
+ private void drawTile(Canvas canvas, String letter, int tileColor,
+ int left, int top, int right, int bottom) {
+ letter = letter.toUpperCase(Locale.getDefault());
+ Paint tilePaint = new Paint(), textPaint = new Paint();
+ tilePaint.setColor(tileColor);
+ textPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
+ textPaint.setColor(FG_COLOR);
+ textPaint.setTypeface(Typeface.create("sans-serif-light",
+ Typeface.NORMAL));
+ textPaint.setTextSize((float) ((right - left) * 0.8));
+ Rect rect = new Rect();
+
+ canvas.drawRect(new Rect(left, top, right, bottom), tilePaint);
+ textPaint.getTextBounds(letter, 0, 1, rect);
+ float width = textPaint.measureText(letter);
+ canvas.drawText(letter, (right + left) / 2 - width / 2, (top + bottom)
+ / 2 + rect.height() / 2, textPaint);
+ }
+
+ private void drawTile(Canvas canvas, MucOptions.User user, int left,
+ int top, int right, int bottom) {
+ Contact contact = user.getContact();
+ if (contact != null) {
+ Uri uri = null;
+ if (contact.getAvatar() != null) {
+ uri = mXmppConnectionService.getFileBackend().getAvatarUri(
+ contact.getAvatar());
+ } else if (contact.getProfilePhoto() != null) {
+ uri = Uri.parse(contact.getProfilePhoto());
+ }
+ if (uri != null) {
+ Bitmap bitmap = mXmppConnectionService.getFileBackend()
+ .cropCenter(uri, bottom - top, right - left);
+ if (bitmap != null) {
+ drawTile(canvas, bitmap, left, top, right, bottom);
+ } else {
+ String letter = user.getName().substring(0, 1);
+ int color = this.getColorForName(user.getName());
+ drawTile(canvas, letter, color, left, top, right, bottom);
+ }
+ } else {
+ String letter = user.getName().substring(0, 1);
+ int color = this.getColorForName(user.getName());
+ drawTile(canvas, letter, color, left, top, right, bottom);
+ }
+ } else {
+ String letter = user.getName().substring(0, 1);
+ int color = this.getColorForName(user.getName());
+ drawTile(canvas, letter, color, left, top, right, bottom);
+ }
+ }
+
+ private void drawTile(Canvas canvas, Bitmap bm, int dstleft, int dsttop,
+ int dstright, int dstbottom) {
+ Rect dst = new Rect(dstleft, dsttop, dstright, dstbottom);
+ canvas.drawBitmap(bm, null, dst, null);
+ }
+
+ private int getColorForName(String name) {
+ int holoColors[] = { 0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5,
+ 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722,
+ 0xFF795548, 0xFF607d8b };
+ return holoColors[(int) ((name.hashCode() & 0xffffffffl) % holoColors.length)];
+ }
+
+}
diff --git a/src/eu/siacs/conversations/services/ImageProvider.java b/src/eu/siacs/conversations/services/ImageProvider.java
deleted file mode 100644
index ac78a454..00000000
--- a/src/eu/siacs/conversations/services/ImageProvider.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package eu.siacs.conversations.services;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-import eu.siacs.conversations.Config;
-import eu.siacs.conversations.entities.Account;
-import eu.siacs.conversations.entities.Conversation;
-import eu.siacs.conversations.entities.Message;
-import eu.siacs.conversations.persistance.DatabaseBackend;
-import eu.siacs.conversations.persistance.FileBackend;
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-public class ImageProvider extends ContentProvider {
-
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode)
- throws FileNotFoundException {
- ParcelFileDescriptor pfd;
- FileBackend fileBackend = new FileBackend(getContext());
- if ("r".equals(mode)) {
- DatabaseBackend databaseBackend = DatabaseBackend
- .getInstance(getContext());
- String uuids = uri.getPath();
- Log.d(Config.LOGTAG, "uuids = " + uuids + " mode=" + mode);
- if (uuids == null) {
- throw new FileNotFoundException();
- }
- String[] uuidsSplited = uuids.split("/", 2);
- if (uuidsSplited.length != 3) {
- throw new FileNotFoundException();
- }
- String conversationUuid = uuidsSplited[1];
- String messageUuid = uuidsSplited[2].split("\\.")[0];
-
- Log.d(Config.LOGTAG, "messageUuid=" + messageUuid);
-
- Conversation conversation = databaseBackend
- .findConversationByUuid(conversationUuid);
- if (conversation == null) {
- throw new FileNotFoundException("conversation "
- + conversationUuid + " could not be found");
- }
- Message message = databaseBackend.findMessageByUuid(messageUuid);
- if (message == null) {
- throw new FileNotFoundException("message " + messageUuid
- + " could not be found");
- }
-
- Account account = databaseBackend.findAccountByUuid(conversation
- .getAccountUuid());
- if (account == null) {
- throw new FileNotFoundException("account "
- + conversation.getAccountUuid() + " cound not be found");
- }
- message.setConversation(conversation);
- conversation.setAccount(account);
-
- File file = fileBackend.getJingleFileLegacy(message);
- pfd = ParcelFileDescriptor.open(file,
- ParcelFileDescriptor.MODE_READ_ONLY);
- return pfd;
- } else {
- throw new FileNotFoundException();
- }
- }
-
- @Override
- public int delete(Uri arg0, String arg1, String[] arg2) {
- return 0;
- }
-
- @Override
- public String getType(Uri arg0) {
- return null;
- }
-
- @Override
- public Uri insert(Uri arg0, ContentValues arg1) {
- return null;
- }
-
- @Override
- public boolean onCreate() {
- return false;
- }
-
- @Override
- public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
- String arg4) {
- return null;
- }
-
- @Override
- public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
- return 0;
- }
-
- public static Uri getProviderUri(Message message) {
- return Uri.parse("content://eu.siacs.conversations.images/"
- + message.getConversationUuid() + "/" + message.getUuid()
- + ".webp");
- }
-} \ No newline at end of file
diff --git a/src/eu/siacs/conversations/services/NotificationService.java b/src/eu/siacs/conversations/services/NotificationService.java
index 41656707..7b2e16df 100644
--- a/src/eu/siacs/conversations/services/NotificationService.java
+++ b/src/eu/siacs/conversations/services/NotificationService.java
@@ -1,5 +1,6 @@
package eu.siacs.conversations.services;
+import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.regex.Matcher;
@@ -11,70 +12,83 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.graphics.Bitmap;
import android.net.Uri;
import android.os.PowerManager;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationCompat.BigPictureStyle;
+import android.support.v4.app.NotificationCompat.Builder;
import android.support.v4.app.TaskStackBuilder;
import android.text.Html;
+import android.util.DisplayMetrics;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
+import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.Downloadable;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.ui.ConversationActivity;
public class NotificationService {
private XmppConnectionService mXmppConnectionService;
- private NotificationManager mNotificationManager;
private LinkedHashMap<String, ArrayList<Message>> notifications = new LinkedHashMap<String, ArrayList<Message>>();
- public int NOTIFICATION_ID = 0x2342;
+ public static int NOTIFICATION_ID = 0x2342;
private Conversation mOpenConversation;
private boolean mIsInForeground;
-
- private long mEndGracePeriod = 0L;
+ private long mLastNotification;
public NotificationService(XmppConnectionService service) {
this.mXmppConnectionService = service;
- this.mNotificationManager = (NotificationManager) service
- .getSystemService(Context.NOTIFICATION_SERVICE);
}
- public synchronized void push(Message message) {
-
+ public void push(Message message) {
PowerManager pm = (PowerManager) mXmppConnectionService
.getSystemService(Context.POWER_SERVICE);
boolean isScreenOn = pm.isScreenOn();
+
if (this.mIsInForeground && isScreenOn
&& this.mOpenConversation == message.getConversation()) {
return;
}
- String conversationUuid = message.getConversationUuid();
- if (notifications.containsKey(conversationUuid)) {
- notifications.get(conversationUuid).add(message);
- } else {
- ArrayList<Message> mList = new ArrayList<Message>();
- mList.add(message);
- notifications.put(conversationUuid, mList);
+ synchronized (notifications) {
+ String conversationUuid = message.getConversationUuid();
+ if (notifications.containsKey(conversationUuid)) {
+ notifications.get(conversationUuid).add(message);
+ } else {
+ ArrayList<Message> mList = new ArrayList<Message>();
+ mList.add(message);
+ notifications.put(conversationUuid, mList);
+ }
+ Account account = message.getConversation().getAccount();
+ updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn)
+ && !account.inGracePeriod()
+ && !this.inMiniGracePeriod(account));
}
- updateNotification((!(this.mIsInForeground && this.mOpenConversation == null) || !isScreenOn)
- && !inGracePeriod());
+
}
public void clear() {
- notifications.clear();
- updateNotification(false);
+ synchronized (notifications) {
+ notifications.clear();
+ updateNotification(false);
+ }
}
public void clear(Conversation conversation) {
- notifications.remove(conversation.getUuid());
- updateNotification(false);
+ synchronized (notifications) {
+ notifications.remove(conversation.getUuid());
+ updateNotification(false);
+ }
}
private void updateNotification(boolean notify) {
+ NotificationManager notificationManager = (NotificationManager) mXmppConnectionService
+ .getSystemService(Context.NOTIFICATION_SERVICE);
SharedPreferences preferences = mXmppConnectionService.getPreferences();
String ringtone = preferences.getString("notification_ringtone", null);
@@ -82,76 +96,16 @@ public class NotificationService {
true);
if (notifications.size() == 0) {
- mNotificationManager.cancel(NOTIFICATION_ID);
+ notificationManager.cancel(NOTIFICATION_ID);
} else {
- NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
- mXmppConnectionService);
- mBuilder.setSmallIcon(R.drawable.ic_notification);
+ if (notify) {
+ this.markLastNotification();
+ }
+ Builder mBuilder;
if (notifications.size() == 1) {
- ArrayList<Message> messages = notifications.values().iterator()
- .next();
- if (messages.size() >= 1) {
- Conversation conversation = messages.get(0)
- .getConversation();
- mBuilder.setLargeIcon(conversation.getImage(
- mXmppConnectionService, 64));
- mBuilder.setContentTitle(conversation.getName());
- StringBuilder text = new StringBuilder();
- for (int i = 0; i < messages.size(); ++i) {
- text.append(messages.get(i).getReadableBody(
- mXmppConnectionService));
- if (i != messages.size() - 1) {
- text.append("\n");
- }
- }
- mBuilder.setStyle(new NotificationCompat.BigTextStyle()
- .bigText(text.toString()));
- mBuilder.setContentText(messages.get(0).getReadableBody(
- mXmppConnectionService));
- if (notify) {
- mBuilder.setTicker(messages.get(messages.size() - 1)
- .getReadableBody(mXmppConnectionService));
- }
- mBuilder.setContentIntent(createContentIntent(conversation
- .getUuid()));
- } else {
- mNotificationManager.cancel(NOTIFICATION_ID);
- return;
- }
+ mBuilder = buildSingleConversations(notify);
} else {
- NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
- style.setBigContentTitle(notifications.size()
- + " "
- + mXmppConnectionService
- .getString(R.string.unread_conversations));
- StringBuilder names = new StringBuilder();
- Conversation conversation = null;
- for (ArrayList<Message> messages : notifications.values()) {
- if (messages.size() > 0) {
- conversation = messages.get(0).getConversation();
- String name = conversation.getName();
- style.addLine(Html.fromHtml("<b>"
- + name
- + "</b> "
- + messages.get(0).getReadableBody(
- mXmppConnectionService)));
- names.append(name);
- names.append(", ");
- }
- }
- if (names.length() >= 2) {
- names.delete(names.length() - 2, names.length());
- }
- mBuilder.setContentTitle(notifications.size()
- + " "
- + mXmppConnectionService
- .getString(R.string.unread_conversations));
- mBuilder.setContentText(names.toString());
- mBuilder.setStyle(style);
- if (conversation != null) {
- mBuilder.setContentIntent(createContentIntent(conversation
- .getUuid()));
- }
+ mBuilder = buildMultipleConversation();
}
if (notify) {
if (vibrate) {
@@ -163,12 +117,147 @@ public class NotificationService {
mBuilder.setSound(Uri.parse(ringtone));
}
}
+ mBuilder.setSmallIcon(R.drawable.ic_notification);
mBuilder.setDeleteIntent(createDeleteIntent());
- if (!inGracePeriod()) {
- mBuilder.setLights(0xffffffff, 2000, 4000);
- }
+ mBuilder.setLights(0xffffffff, 2000, 4000);
Notification notification = mBuilder.build();
- mNotificationManager.notify(NOTIFICATION_ID, notification);
+ notificationManager.notify(NOTIFICATION_ID, notification);
+ }
+ }
+
+ private Builder buildMultipleConversation() {
+ Builder mBuilder = new NotificationCompat.Builder(
+ mXmppConnectionService);
+ NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();
+ style.setBigContentTitle(notifications.size()
+ + " "
+ + mXmppConnectionService
+ .getString(R.string.unread_conversations));
+ StringBuilder names = new StringBuilder();
+ Conversation conversation = null;
+ for (ArrayList<Message> messages : notifications.values()) {
+ if (messages.size() > 0) {
+ conversation = messages.get(0).getConversation();
+ String name = conversation.getName();
+ style.addLine(Html.fromHtml("<b>" + name + "</b> "
+ + getReadableBody(messages.get(0))));
+ names.append(name);
+ names.append(", ");
+ }
+ }
+ if (names.length() >= 2) {
+ names.delete(names.length() - 2, names.length());
+ }
+ mBuilder.setContentTitle(notifications.size()
+ + " "
+ + mXmppConnectionService
+ .getString(R.string.unread_conversations));
+ mBuilder.setContentText(names.toString());
+ mBuilder.setStyle(style);
+ if (conversation != null) {
+ mBuilder.setContentIntent(createContentIntent(conversation
+ .getUuid()));
+ }
+ return mBuilder;
+ }
+
+ private Builder buildSingleConversations(boolean notify) {
+ Builder mBuilder = new NotificationCompat.Builder(
+ mXmppConnectionService);
+ ArrayList<Message> messages = notifications.values().iterator().next();
+ if (messages.size() >= 1) {
+ Conversation conversation = messages.get(0).getConversation();
+ mBuilder.setLargeIcon(mXmppConnectionService.getAvatarService()
+ .get(conversation, getPixel(64)));
+ mBuilder.setContentTitle(conversation.getName());
+ Message message;
+ if ((message = getImage(messages)) != null) {
+ modifyForImage(mBuilder, message, messages, notify);
+ } else {
+ modifyForTextOnly(mBuilder, messages, notify);
+ }
+ mBuilder.setContentIntent(createContentIntent(conversation
+ .getUuid()));
+ }
+ return mBuilder;
+
+ }
+
+ private void modifyForImage(Builder builder, Message message,
+ ArrayList<Message> messages, boolean notify) {
+ try {
+ Bitmap bitmap = mXmppConnectionService.getFileBackend()
+ .getThumbnail(message, getPixel(288), false);
+ ArrayList<Message> tmp = new ArrayList<Message>();
+ for (Message msg : messages) {
+ if (msg.getType() == Message.TYPE_TEXT
+ && msg.getDownloadable() == null) {
+ tmp.add(msg);
+ }
+ }
+ BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();
+ bigPictureStyle.bigPicture(bitmap);
+ if (tmp.size() > 0) {
+ bigPictureStyle.setSummaryText(getMergedBodies(tmp));
+ builder.setContentText(getReadableBody(tmp.get(0)));
+ } else {
+ builder.setContentText(mXmppConnectionService.getString(R.string.image_file));
+ }
+ builder.setStyle(bigPictureStyle);
+ } catch (FileNotFoundException e) {
+ modifyForTextOnly(builder, messages, notify);
+ }
+ }
+
+ private void modifyForTextOnly(Builder builder,
+ ArrayList<Message> messages, boolean notify) {
+ builder.setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(getMergedBodies(messages)));
+ builder.setContentText(getReadableBody(messages.get(0)));
+ if (notify) {
+ builder.setTicker(getReadableBody(messages.get(messages.size() - 1)));
+ }
+ }
+
+ private Message getImage(ArrayList<Message> messages) {
+ for (Message message : messages) {
+ if (message.getType() == Message.TYPE_IMAGE
+ && message.getDownloadable() == null
+ && message.getEncryption() != Message.ENCRYPTION_PGP) {
+ return message;
+ }
+ }
+ return null;
+ }
+
+ private String getMergedBodies(ArrayList<Message> messages) {
+ StringBuilder text = new StringBuilder();
+ for (int i = 0; i < messages.size(); ++i) {
+ text.append(getReadableBody(messages.get(i)));
+ if (i != messages.size() - 1) {
+ text.append("\n");
+ }
+ }
+ return text.toString();
+ }
+
+ private String getReadableBody(Message message) {
+ if (message.getDownloadable() != null
+ && (message.getDownloadable().getStatus() == Downloadable.STATUS_OFFER || message
+ .getDownloadable().getStatus() == Downloadable.STATUS_OFFER_CHECK_FILESIZE)) {
+ return mXmppConnectionService.getText(
+ R.string.image_offered_for_download).toString();
+ } else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
+ return mXmppConnectionService.getText(
+ R.string.encrypted_message_received).toString();
+ } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) {
+ return mXmppConnectionService.getText(R.string.decryption_failed)
+ .toString();
+ } else if (message.getType() == Message.TYPE_IMAGE) {
+ return mXmppConnectionService.getText(R.string.image_file)
+ .toString();
+ } else {
+ return message.getBody().trim();
}
}
@@ -226,16 +315,19 @@ public class NotificationService {
this.mIsInForeground = foreground;
}
- public void activateGracePeriod() {
- this.mEndGracePeriod = SystemClock.elapsedRealtime()
- + (Config.CARBON_GRACE_PERIOD * 1000);
+ private int getPixel(int dp) {
+ DisplayMetrics metrics = mXmppConnectionService.getResources()
+ .getDisplayMetrics();
+ return ((int) (dp * metrics.density));
}
- public void deactivateGracePeriod() {
- this.mEndGracePeriod = 0L;
+ private void markLastNotification() {
+ this.mLastNotification = SystemClock.elapsedRealtime();
}
- private boolean inGracePeriod() {
- return SystemClock.elapsedRealtime() < this.mEndGracePeriod;
+ private boolean inMiniGracePeriod(Account account) {
+ int miniGrace = account.getStatus() == Account.STATUS_ONLINE ? Config.MINI_GRACE_PERIOD
+ : Config.MINI_GRACE_PERIOD * 2;
+ return SystemClock.elapsedRealtime() < (this.mLastNotification + miniGrace);
}
}
diff --git a/src/eu/siacs/conversations/services/XmppConnectionService.java b/src/eu/siacs/conversations/services/XmppConnectionService.java
index e6297f4f..be73e07f 100644
--- a/src/eu/siacs/conversations/services/XmppConnectionService.java
+++ b/src/eu/siacs/conversations/services/XmppConnectionService.java
@@ -27,6 +27,7 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Bookmark;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
+import eu.siacs.conversations.entities.Downloadable;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
import eu.siacs.conversations.entities.MucOptions.OnRenameListener;
@@ -34,6 +35,7 @@ import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.generator.IqGenerator;
import eu.siacs.conversations.generator.MessageGenerator;
import eu.siacs.conversations.generator.PresenceGenerator;
+import eu.siacs.conversations.http.HttpConnectionManager;
import eu.siacs.conversations.parser.IqParser;
import eu.siacs.conversations.parser.MessageParser;
import eu.siacs.conversations.parser.PresenceParser;
@@ -74,6 +76,7 @@ import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.FileObserver;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
@@ -81,11 +84,12 @@ import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.util.Log;
+import android.util.LruCache;
public class XmppConnectionService extends Service {
public DatabaseBackend databaseBackend;
- private FileBackend fileBackend;
+ private FileBackend fileBackend = new FileBackend(this);
public long startDate;
@@ -94,7 +98,8 @@ public class XmppConnectionService extends Service {
private MemorizingTrustManager mMemorizingTrustManager;
- private NotificationService mNotificationService;
+ private NotificationService mNotificationService = new NotificationService(
+ this);
private MessageParser mMessageParser = new MessageParser(this);
private PresenceParser mPresenceParser = new PresenceParser(this);
@@ -106,20 +111,27 @@ public class XmppConnectionService extends Service {
private CopyOnWriteArrayList<Conversation> conversations = null;
private JingleConnectionManager mJingleConnectionManager = new JingleConnectionManager(
this);
+ private HttpConnectionManager mHttpConnectionManager = new HttpConnectionManager(
+ this);
+ private AvatarService mAvatarService = new AvatarService(this);
private OnConversationUpdate mOnConversationUpdate = null;
- private int convChangedListenerCount = 0;
+ private Integer convChangedListenerCount = 0;
private OnAccountUpdate mOnAccountUpdate = null;
- private int accountChangedListenerCount = 0;
+ private Integer accountChangedListenerCount = 0;
private OnRosterUpdate mOnRosterUpdate = null;
- private int rosterChangedListenerCount = 0;
+ private Integer rosterChangedListenerCount = 0;
public OnContactStatusChanged onContactStatusChanged = new OnContactStatusChanged() {
@Override
public void onContactStatusChanged(Contact contact, boolean online) {
Conversation conversation = find(getConversations(), contact);
if (conversation != null) {
- conversation.endOtrIfNeeded();
+ if (online && contact.getPresences().size() > 1) {
+ conversation.endOtrIfNeeded();
+ } else {
+ conversation.resetOtrSession();
+ }
if (online && (contact.getPresences().size() == 1)) {
sendUnsendMessages(conversation);
}
@@ -140,6 +152,17 @@ public class XmppConnectionService extends Service {
}
};
+ private FileObserver fileObserver = new FileObserver(
+ FileBackend.getConversationsDirectory()) {
+
+ @Override
+ public void onEvent(int event, String path) {
+ if (event == FileObserver.DELETE) {
+ markFileDeleted(path.split("\\.")[0]);
+ }
+ }
+ };
+
private final IBinder mBinder = new XmppConnectionBinder();
private OnStatusChanged statusListener = new OnStatusChanged() {
@@ -252,6 +275,7 @@ public class XmppConnectionService extends Service {
}
}
};
+ private LruCache<String, Bitmap> mBitmapCache;
public PgpEngine getPgpEngine() {
if (pgpServiceConnection.isBound()) {
@@ -271,6 +295,10 @@ public class XmppConnectionService extends Service {
return this.fileBackend;
}
+ public AvatarService getAvatarService() {
+ return this.mAvatarService;
+ }
+
public Message attachImageToConversation(final Conversation conversation,
final Uri uri, final UiCallback<Message> callback) {
final Message message;
@@ -331,15 +359,10 @@ public class XmppConnectionService extends Service {
}
}
this.wakeLock.acquire();
- ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
- .getSystemService(Context.CONNECTIVITY_SERVICE);
- NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
- boolean isConnected = activeNetwork != null
- && activeNetwork.isConnected();
for (Account account : accounts) {
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
- if (!isConnected) {
+ if (!hasInternetConnection()) {
account.setStatus(Account.STATUS_NO_INTERNET);
if (statusListener != null) {
statusListener.onStatusChanged(account);
@@ -398,6 +421,13 @@ public class XmppConnectionService extends Service {
return START_STICKY;
}
+ public boolean hasInternetConnection() {
+ ConnectivityManager cm = (ConnectivityManager) getApplicationContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
+ return activeNetwork != null && activeNetwork.isConnected();
+ }
+
@SuppressLint("TrulyRandom")
@Override
public void onCreate() {
@@ -406,10 +436,18 @@ public class XmppConnectionService extends Service {
this.mRandom = new SecureRandom();
this.mMemorizingTrustManager = new MemorizingTrustManager(
getApplicationContext());
- this.mNotificationService = new NotificationService(this);
+
+ int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
+ int cacheSize = maxMemory / 8;
+ this.mBitmapCache = new LruCache<String, Bitmap>(cacheSize) {
+ @Override
+ protected int sizeOf(String key, Bitmap bitmap) {
+ return bitmap.getByteCount() / 1024;
+ }
+ };
+
this.databaseBackend = DatabaseBackend
.getInstance(getApplicationContext());
- this.fileBackend = new FileBackend(getApplicationContext());
this.accounts = databaseBackend.getAccounts();
for (Account account : this.accounts) {
@@ -420,6 +458,7 @@ public class XmppConnectionService extends Service {
getContentResolver().registerContentObserver(
ContactsContract.Contacts.CONTENT_URI, true, contactObserver);
+ this.fileObserver.startWatching();
this.pgpServiceConnection = new OpenPgpServiceConnection(
getApplicationContext(), "org.sufficientlysecure.keychain");
this.pgpServiceConnection.bindToService();
@@ -511,8 +550,9 @@ public class XmppConnectionService extends Service {
return connection;
}
- synchronized public void sendMessage(Message message) {
+ public void sendMessage(Message message) {
Account account = message.getConversation().getAccount();
+ account.deactivateGracePeriod();
Conversation conv = message.getConversation();
MessagePacket packet = null;
boolean saveInDb = true;
@@ -531,13 +571,14 @@ public class XmppConnectionService extends Service {
&& conv.getOtrSession().getSessionStatus() == SessionStatus.ENCRYPTED) {
mJingleConnectionManager
.createNewConnection(message);
- } else if (message.getPresence() == null) {
- message.setStatus(Message.STATUS_WAITING);
}
} else {
mJingleConnectionManager.createNewConnection(message);
}
} else {
+ if (message.getEncryption() == Message.ENCRYPTION_OTR) {
+ conv.startOtrIfNeeded();
+ }
message.setStatus(Message.STATUS_WAITING);
}
} else {
@@ -554,6 +595,7 @@ public class XmppConnectionService extends Service {
send = true;
} else if (message.getPresence() == null) {
+ conv.startOtrIfNeeded();
message.setStatus(Message.STATUS_WAITING);
}
} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
@@ -596,7 +638,7 @@ public class XmppConnectionService extends Service {
}
}
- conv.getMessages().add(message);
+ conv.add(message);
if (saveInDb) {
if (message.getEncryption() == Message.ENCRYPTION_NONE
|| saveEncryptedMessages()) {
@@ -776,6 +818,7 @@ public class XmppConnectionService extends Service {
.getString("photouri"));
contact.setSystemName(phoneContact
.getString("displayname"));
+ getAvatarService().clear(contact);
}
}
}
@@ -794,12 +837,39 @@ public class XmppConnectionService extends Service {
Account account = accountLookupTable.get(conv.getAccountUuid());
conv.setAccount(account);
conv.setMessages(databaseBackend.getMessages(conv, 50));
+ checkDeletedFiles(conv);
}
}
-
return this.conversations;
}
+ private void checkDeletedFiles(Conversation conversation) {
+ for (Message message : conversation.getMessages()) {
+ if (message.getType() == Message.TYPE_IMAGE
+ && message.getEncryption() != Message.ENCRYPTION_PGP) {
+ if (!getFileBackend().isFileAvailable(message)) {
+ message.setDownloadable(new DeletedDownloadable());
+ }
+ }
+ }
+ }
+
+ private void markFileDeleted(String uuid) {
+ for (Conversation conversation : getConversations()) {
+ for (Message message : conversation.getMessages()) {
+ if (message.getType() == Message.TYPE_IMAGE
+ && message.getEncryption() != Message.ENCRYPTION_PGP
+ && message.getUuid().equals(uuid)) {
+ if (!getFileBackend().isFileAvailable(message)) {
+ message.setDownloadable(new DeletedDownloadable());
+ updateConversationUi();
+ }
+ return;
+ }
+ }
+ }
+ }
+
public void populateWithOrderedConversations(List<Conversation> list) {
populateWithOrderedConversations(list, true);
}
@@ -838,7 +908,7 @@ public class XmppConnectionService extends Service {
for (Message message : messages) {
message.setConversation(conversation);
}
- conversation.getMessages().addAll(0, messages);
+ conversation.addAll(0, messages);
return messages.size();
}
@@ -858,9 +928,9 @@ public class XmppConnectionService extends Service {
public Conversation find(List<Conversation> haystack, Account account,
String jid) {
for (Conversation conversation : haystack) {
- if ((account == null || conversation.getAccount().equals(account))
+ if ((account == null || conversation.getAccount() == account)
&& (conversation.getContactJid().split("/", 2)[0]
- .equals(jid))) {
+ .equalsIgnoreCase(jid))) {
return conversation;
}
}
@@ -927,7 +997,6 @@ public class XmppConnectionService extends Service {
public void clearConversationHistory(Conversation conversation) {
this.databaseBackend.deleteMessagesInConversation(conversation);
- this.fileBackend.removeFiles(conversation);
conversation.getMessages().clear();
updateConversationUi();
}
@@ -973,60 +1042,85 @@ public class XmppConnectionService extends Service {
public void setOnConversationListChangedListener(
OnConversationUpdate listener) {
- this.mNotificationService.deactivateGracePeriod();
- if (checkListeners()) {
- switchToForeground();
+ if (!isScreenOn()) {
+ Log.d(Config.LOGTAG,
+ "ignoring setOnConversationListChangedListener");
+ return;
+ }
+ synchronized (this.convChangedListenerCount) {
+ if (checkListeners()) {
+ switchToForeground();
+ }
+ this.mOnConversationUpdate = listener;
+ this.mNotificationService.setIsInForeground(true);
+ this.convChangedListenerCount++;
}
- this.mOnConversationUpdate = listener;
- this.mNotificationService.setIsInForeground(true);
- this.convChangedListenerCount++;
}
public void removeOnConversationListChangedListener() {
- this.convChangedListenerCount--;
- if (this.convChangedListenerCount == 0) {
- this.mOnConversationUpdate = null;
- this.mNotificationService.setIsInForeground(false);
- if (checkListeners()) {
- switchToBackground();
+ synchronized (this.convChangedListenerCount) {
+ this.convChangedListenerCount--;
+ if (this.convChangedListenerCount <= 0) {
+ this.convChangedListenerCount = 0;
+ this.mOnConversationUpdate = null;
+ this.mNotificationService.setIsInForeground(false);
+ if (checkListeners()) {
+ switchToBackground();
+ }
}
}
}
public void setOnAccountListChangedListener(OnAccountUpdate listener) {
- this.mNotificationService.deactivateGracePeriod();
- if (checkListeners()) {
- switchToForeground();
+ if (!isScreenOn()) {
+ Log.d(Config.LOGTAG, "ignoring setOnAccountListChangedListener");
+ return;
+ }
+ synchronized (this.accountChangedListenerCount) {
+ if (checkListeners()) {
+ switchToForeground();
+ }
+ this.mOnAccountUpdate = listener;
+ this.accountChangedListenerCount++;
}
- this.mOnAccountUpdate = listener;
- this.accountChangedListenerCount++;
}
public void removeOnAccountListChangedListener() {
- this.accountChangedListenerCount--;
- if (this.accountChangedListenerCount == 0) {
- this.mOnAccountUpdate = null;
- if (checkListeners()) {
- switchToBackground();
+ synchronized (this.accountChangedListenerCount) {
+ this.accountChangedListenerCount--;
+ if (this.accountChangedListenerCount <= 0) {
+ this.mOnAccountUpdate = null;
+ this.accountChangedListenerCount = 0;
+ if (checkListeners()) {
+ switchToBackground();
+ }
}
}
}
public void setOnRosterUpdateListener(OnRosterUpdate listener) {
- this.mNotificationService.deactivateGracePeriod();
- if (checkListeners()) {
- switchToForeground();
+ if (!isScreenOn()) {
+ Log.d(Config.LOGTAG, "ignoring setOnRosterUpdateListener");
+ return;
+ }
+ synchronized (this.rosterChangedListenerCount) {
+ if (checkListeners()) {
+ switchToForeground();
+ }
+ this.mOnRosterUpdate = listener;
+ this.rosterChangedListenerCount++;
}
- this.mOnRosterUpdate = listener;
- this.rosterChangedListenerCount++;
}
public void removeOnRosterUpdateListener() {
- this.rosterChangedListenerCount--;
- if (this.rosterChangedListenerCount == 0) {
- this.mOnRosterUpdate = null;
- if (checkListeners()) {
- switchToBackground();
+ synchronized (this.rosterChangedListenerCount) {
+ this.rosterChangedListenerCount--;
+ if (this.rosterChangedListenerCount <= 0) {
+ this.rosterChangedListenerCount = 0;
+ this.mOnRosterUpdate = null;
+ if (checkListeners()) {
+ switchToBackground();
+ }
}
}
}
@@ -1042,11 +1136,10 @@ public class XmppConnectionService extends Service {
XmppConnection connection = account.getXmppConnection();
if (connection != null && connection.getFeatures().csi()) {
connection.sendActive();
- Log.d(Config.LOGTAG, account.getJid()
- + " sending csi//active");
}
}
}
+ Log.d(Config.LOGTAG, "app switched into foreground");
}
private void switchToBackground() {
@@ -1055,11 +1148,17 @@ public class XmppConnectionService extends Service {
XmppConnection connection = account.getXmppConnection();
if (connection != null && connection.getFeatures().csi()) {
connection.sendInactive();
- Log.d(Config.LOGTAG, account.getJid()
- + " sending csi//inactive");
}
}
}
+ this.mNotificationService.setIsInForeground(false);
+ Log.d(Config.LOGTAG, "app switched into background");
+ }
+
+ private boolean isScreenOn() {
+ PowerManager pm = (PowerManager) this
+ .getSystemService(Context.POWER_SERVICE);
+ return pm.isScreenOn();
}
public void connectMultiModeConversations(Account account) {
@@ -1197,7 +1296,7 @@ public class XmppConnectionService extends Service {
conversation.getMucOptions().setOffline();
conversation.deregisterWithBookmark();
Log.d(Config.LOGTAG, conversation.getAccount().getJid()
- + " leaving muc " + conversation.getContactJid());
+ + ": leaving muc " + conversation.getContactJid());
} else {
account.pendingConferenceLeaves.add(conversation);
}
@@ -1214,7 +1313,11 @@ public class XmppConnectionService extends Service {
if (conversation.getMode() == Conversation.MODE_MULTI) {
leaveMuc(conversation);
} else {
- conversation.endOtrIfNeeded();
+ if (conversation.endOtrIfNeeded()) {
+ Log.d(Config.LOGTAG, account.getJid()
+ + ": ended otr session with "
+ + conversation.getContactJid());
+ }
}
}
}
@@ -1230,6 +1333,7 @@ public class XmppConnectionService extends Service {
public void updateMessage(Message message) {
databaseBackend.updateMessage(message);
+ updateConversationUi();
}
protected void syncDirtyContacts(Account account) {
@@ -1410,10 +1514,16 @@ public class XmppConnectionService extends Service {
if (account.setAvatar(avatar.getFilename())) {
databaseBackend.updateAccount(account);
}
+ getAvatarService().clear(account);
+ updateConversationUi();
+ updateAccountUi();
} else {
Contact contact = account.getRoster()
.getContact(avatar.owner);
contact.setAvatar(avatar.getFilename());
+ getAvatarService().clear(contact);
+ updateConversationUi();
+ updateRosterUi();
}
if (callback != null) {
callback.success(avatar);
@@ -1463,6 +1573,7 @@ public class XmppConnectionService extends Service {
if (account.setAvatar(avatar.getFilename())) {
databaseBackend.updateAccount(account);
}
+ getAvatarService().clear(account);
callback.success(avatar);
} else {
fetchAvatar(account, avatar, callback);
@@ -1675,6 +1786,10 @@ public class XmppConnectionService extends Service {
return this.pm;
}
+ public LruCache<String, Bitmap> getBitmapCache() {
+ return this.mBitmapCache;
+ }
+
public void replyWithNotAcceptable(Account account, MessagePacket packet) {
if (account.getStatus() == Account.STATUS_ONLINE) {
MessagePacket error = this.mMessageGenerator
@@ -1779,8 +1894,7 @@ public class XmppConnectionService extends Service {
ArrayList<Contact> contacts = new ArrayList<Contact>();
for (Account account : getAccounts()) {
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
- Contact contact = account.getRoster()
- .getContactAsShownInRoster(jid);
+ Contact contact = account.getRoster().getContactFromRoster(jid);
if (contact != null) {
contacts.add(contact);
}
@@ -1792,4 +1906,44 @@ public class XmppConnectionService extends Service {
public NotificationService getNotificationService() {
return this.mNotificationService;
}
+
+ public HttpConnectionManager getHttpConnectionManager() {
+ return this.mHttpConnectionManager;
+ }
+
+ private class DeletedDownloadable implements Downloadable {
+
+ @Override
+ public boolean start() {
+ return false;
+ }
+
+ @Override
+ public int getStatus() {
+ return Downloadable.STATUS_DELETED;
+ }
+
+ @Override
+ public long getFileSize() {
+ return 0;
+ }
+
+ }
+
+ public void resendFailedMessages(Message message) {
+ List<Message> messages = new ArrayList<Message>();
+ Message current = message;
+ while(current.getStatus() == Message.STATUS_SEND_FAILED) {
+ messages.add(current);
+ if (current.mergable(current.next())) {
+ current = current.next();
+ } else {
+ break;
+ }
+ }
+ for(Message msg: messages) {
+ markMessage(msg, Message.STATUS_WAITING);
+ this.resendMessage(msg);
+ }
+ }
}