diff options
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/services')
5 files changed, 144 insertions, 56 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java b/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java index 6311d739..ed9c259f 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/AvatarService.java @@ -31,14 +31,17 @@ import de.thedevstack.conversationsplus.entities.Message; import de.thedevstack.conversationsplus.entities.MucOptions; import de.thedevstack.conversationsplus.generator.IqGenerator; import de.thedevstack.conversationsplus.persistance.DatabaseBackend; +import de.thedevstack.conversationsplus.persistance.FileBackend; import de.thedevstack.conversationsplus.ui.UiCallback; import de.thedevstack.conversationsplus.utils.UIHelper; import de.thedevstack.conversationsplus.xml.Element; +import de.thedevstack.conversationsplus.xmpp.OnAdvancedStreamFeaturesLoaded; import de.thedevstack.conversationsplus.xmpp.OnIqPacketReceived; +import de.thedevstack.conversationsplus.xmpp.XmppConnection; import de.thedevstack.conversationsplus.xmpp.pep.Avatar; import de.thedevstack.conversationsplus.xmpp.stanzas.IqPacket; -public class AvatarService { +public class AvatarService implements OnAdvancedStreamFeaturesLoaded { private static final int FG_COLOR = 0xFFFAFAFA; private static final int TRANSPARENT = 0x00000000; @@ -408,6 +411,17 @@ public class AvatarService { return true; } + @Override + public void onAdvancedStreamFeaturesAvailable(Account account) { + XmppConnection.Features features = account.getXmppConnection().getFeatures(); + if (features.pep() && !features.pepPersistent()) { + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": has pep but is not persistent"); + if (account.getAvatar() != null) { + republishAvatarIfNeeded(account); + } + } + } + public void publishAvatar(final Account account, final Uri image, final UiCallback<Avatar> callback) { @@ -428,47 +442,79 @@ public class AvatarService { callback.error(R.string.error_saving_avatar, avatar); return; } - final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar); - XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, IqPacket result) { - if (result.getType() == IqPacket.TYPE.RESULT) { - final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarMetadataPacket(avatar); - XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { - - @Override - public void onIqPacketReceived(Account account, - IqPacket result) { - if (result.getType() == IqPacket.TYPE.RESULT) { - if (account.setAvatar(avatar.getFilename())) { - AvatarService.getInstance().clear(account); - DatabaseBackend.getInstance(ConversationsPlusApplication.getAppContext()).updateAccount(account); - } - callback.success(avatar); - } else { - callback.error( - R.string.error_publish_avatar_server_reject, - avatar); - } - } - }); - } else { + sendAndReceiveIqPackages(avatar, account, callback); + } else { + callback.error(R.string.error_publish_avatar_converting, null); + } + } + + public void publishAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + sendAndReceiveIqPackages(avatar, account, callback); + } else { + if (callback != null) { callback.error( R.string.error_publish_avatar_server_reject, avatar); } } - }); - } else { - callback.error(R.string.error_publish_avatar_converting, null); - } + } + }); } private static String generateFetchKey(Account account, final Avatar avatar) { return account.getJid().toBareJid()+"_"+avatar.owner+"_"+avatar.sha1sum; } + public void republishAvatarIfNeeded(Account account) { + if (account.getAxolotlService().isPepBroken()) { + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": skipping republication of avatar because pep is broken"); + return; + } + IqPacket packet = AvatarPacketGenerator.generateRetrieveAvatarMetadataPacket(null); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + private Avatar parseAvatar(IqPacket packet) { + Element pubsub = packet.findChild("pubsub", "http://jabber.org/protocol/pubsub"); + if (pubsub != null) { + Element items = pubsub.findChild("items"); + if (items != null) { + return Avatar.parseMetadata(items); + } + } + return null; + } + + private boolean errorIsItemNotFound(IqPacket packet) { + Element error = packet.findChild("error"); + return packet.getType() == IqPacket.TYPE.ERROR + && error != null + && error.hasChild("item-not-found"); + } + + @Override + public void onIqPacketReceived(Account account, IqPacket packet) { + if (packet.getType() == IqPacket.TYPE.RESULT || errorIsItemNotFound(packet)) { + Avatar serverAvatar = parseAvatar(packet); + if (serverAvatar == null && account.getAvatar() != null) { + Avatar avatar = AvatarUtil.getStoredPepAvatar(account.getAvatar()); + if (avatar != null) { + Logging.d(Config.LOGTAG,account.getJid().toBareJid()+": avatar on server was null. republishing"); + publishAvatar(account, AvatarUtil.getStoredPepAvatar(account.getAvatar()), null); + } else { + Logging.e(Config.LOGTAG, account.getJid().toBareJid()+": error rereading avatar"); + } + } + } + } + }); + } + public void fetchAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { final String KEY = generateFetchKey(account, avatar); synchronized(this.mInProgressAvatarFetches) { @@ -624,4 +670,40 @@ public class AvatarService { } } } + + private void sendAndReceiveIqPackages(final Avatar avatar, final Account account, final UiCallback callback) { + + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + final IqPacket packet = AvatarPacketGenerator.generatePublishAvatarMetadataPacket(avatar); + XmppSendUtil.sendIqPacket(account, packet, new OnIqPacketReceived() { + + @Override + public void onIqPacketReceived(Account account, + IqPacket result) { + if (result.getType() == IqPacket.TYPE.RESULT) { + if (account.setAvatar(avatar.getFilename())) { + AvatarService.getInstance().clear(account); + DatabaseBackend.getInstance(ConversationsPlusApplication.getAppContext()).updateAccount(account); + } + callback.success(avatar); + } else { + callback.error( + R.string.error_publish_avatar_server_reject, + avatar); + } + } + }); + } else { + callback.error( + R.string.error_publish_avatar_server_reject, + avatar); + } + } + }); + } } diff --git a/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java b/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java index 8d48d686..6256609c 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/ContactChooserTargetService.java @@ -48,7 +48,7 @@ public class ContactChooserTargetService extends ChooserTargetService implements final Conversation conversation = conversations.get(i); final String name = conversation.getName(); final Icon icon = Icon.createWithBitmap(AvatarService.getInstance().get(conversation, pixel)); - final float score = (1.0f / MAX_TARGETS) * i; + final float score = 1 - (1.0f / MAX_TARGETS) * i; final Bundle extras = new Bundle(); extras.putString("uuid", conversation.getUuid()); chooserTargets.add(new ChooserTarget(name, icon, score, componentName, extras)); diff --git a/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java b/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java index f2298d8c..cd55b42f 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/MessageArchiveService.java @@ -45,8 +45,10 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } } - long startCatchup = getLastMessageTransmitted(account); + Pair<Long,String> pair = mXmppConnectionService.databaseBackend.getLastMessageReceived(account); + long startCatchup = pair == null ? 0 : pair.first; long endCatchup = account.getXmppConnection().getLastSessionEstablished(); + final Query query; if (startCatchup == 0) { return; } else if (endCatchup - startCatchup >= Config.MAM_MAX_CATCHUP) { @@ -57,8 +59,11 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.query(conversation,startCatchup); } } + query = new Query(account, startCatchup, endCatchup); + } else { + query = new Query(account, startCatchup, endCatchup); + query.reference = pair.second; } - final Query query = new Query(account, startCatchup, endCatchup); this.queries.add(query); this.execute(query); } @@ -75,11 +80,6 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { } } - private long getLastMessageTransmitted(final Account account) { - Pair<Long,String> pair = mXmppConnectionService.databaseBackend.getLastMessageReceived(account); - return pair == null ? 0 : pair.first; - } - public Query query(final Conversation conversation) { if (conversation.getLastMessageTransmitted() < 0 && conversation.countMessages() == 0) { return query(conversation, @@ -292,7 +292,7 @@ public class MessageArchiveService implements OnAdvancedStreamFeaturesLoaded { this.end = end; this.queryId = new BigInteger(50, mXmppConnectionService.getRNG()).toString(32); } - + private Query page(String reference) { Query query = new Query(this.account,this.start,this.end); query.reference = reference; diff --git a/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java b/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java index 488a6075..b06dd95c 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/NotificationService.java @@ -176,6 +176,7 @@ public class NotificationService { final String ringtone = ConversationsPlusPreferences.notificationRingtone(); final boolean vibrate = ConversationsPlusPreferences.vibrateOnNotification(); + final boolean led = ConversationsPlusPreferences.led(); if (notifications.size() == 0) { notificationManager.cancel(NOTIFICATION_ID); @@ -206,7 +207,9 @@ public class NotificationService { mBuilder.setDefaults(0); mBuilder.setSmallIcon(R.drawable.ic_notification); mBuilder.setDeleteIntent(createDeleteIntent()); - mBuilder.setLights(Settings.LED_COLOR, 2000, 4000); + if (led) { + mBuilder.setLights(Settings.LED_COLOR, 2000, 4000); + } final Notification notification = mBuilder.build(); notificationManager.notify(NOTIFICATION_ID, notification); } @@ -519,9 +522,11 @@ public class NotificationService { cancelIcon = R.drawable.ic_action_cancel; } mBuilder.setSmallIcon(R.drawable.ic_link_white_24dp); - mBuilder.addAction(cancelIcon, - mXmppConnectionService.getString(R.string.disable_foreground_service), - createDisableForeground()); + if (Config.SHOW_DISABLE_FOREGROUND) { + mBuilder.addAction(cancelIcon, + mXmppConnectionService.getString(R.string.disable_foreground_service), + createDisableForeground()); + } return mBuilder.build(); } diff --git a/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java b/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java index dda3c7b9..c1426080 100644 --- a/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java +++ b/src/main/java/de/thedevstack/conversationsplus/services/XmppConnectionService.java @@ -455,7 +455,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa } return START_STICKY; case Intent.ACTION_SHUTDOWN: - logoutAndSave(); + logoutAndSave(true); return START_NOT_STICKY; case ACTION_CLEAR_NOTIFICATION: mNotificationService.clear(); @@ -738,12 +738,16 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa public void onTaskRemoved(final Intent rootIntent) { super.onTaskRemoved(rootIntent); if (!ConversationsPlusPreferences.keepForegroundService()) { - this.logoutAndSave(); + this.logoutAndSave(false); } } - private void logoutAndSave() { + private void logoutAndSave(boolean stop) { + int activeAccounts = 0; for (final Account account : accounts) { + if (account.getStatus() != Account.State.DISABLED) { + activeAccounts++; + } databaseBackend.writeRoster(account.getRoster()); if (account.getXmppConnection() != null) { new Thread(new Runnable() { @@ -752,11 +756,12 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa disconnect(account, false); } }).start(); - cancelWakeUpCall(account.getUuid().hashCode()); } } - Logging.d(Config.LOGTAG, "good bye"); - stopSelf(); + if (stop || activeAccounts == 0) { + Logging.d(Config.LOGTAG, "good bye"); + stopSelf(); + } } private void cancelWakeUpCall(int requestCode) { @@ -789,6 +794,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa connection.setOnBindListener(this.mOnBindListener); connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener); connection.addOnAdvancedStreamFeaturesAvailableListener(this.mMessageArchiveService); + connection.addOnAdvancedStreamFeaturesAvailableListener(AvatarService.getInstance()); AxolotlService axolotlService = account.getAxolotlService(); if (axolotlService != null) { connection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService); @@ -2331,12 +2337,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa if (!account.isOptionSet(Account.OPTION_DISABLED)) { if (!force) { disconnect(account, false); - try { - Logging.d(Config.LOGTAG, "wait for disconnect"); - Thread.sleep(500); //sleep wait for disconnect - } catch (InterruptedException e) { - //ignored - } } Thread thread = new Thread(connection); connection.setInteractive(interactive); @@ -2347,6 +2347,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa disconnect(account, force); account.getRoster().clearPresences(); connection.resetEverything(); + account.getAxolotlService().resetBrokenness(); } } } |