Merge branch 'development' of https://github.com/siacs/Conversations into development

This commit is contained in:
kruks23 2014-05-18 19:10:52 +02:00
commit e27bb52575
10 changed files with 92 additions and 83 deletions

View File

@ -9,5 +9,6 @@
android:title="@string/attach_take_picture"/> android:title="@string/attach_take_picture"/>
<item <item
android:id="@+id/attach_record_voice" android:id="@+id/attach_record_voice"
android:title="@string/attach_record_voice" /> android:title="@string/attach_record_voice"
android:visible="false"/>
</menu> </menu>

View File

@ -164,5 +164,9 @@
<string name="mgmt_account_disable">Vorübergehend abschalten</string> <string name="mgmt_account_disable">Vorübergehend abschalten</string>
<string name="mgmt_account_enable">Anschalten</string> <string name="mgmt_account_enable">Anschalten</string>
<string name="attach_record_voice">Sprache aufzeichnen</string> <string name="attach_record_voice">Sprache aufzeichnen</string>
<string name="account_settings">Kontoeinstellungen</string>
<string name="save">Speichern</string>
<string name="passwords_do_not_match">Passwörter stimmen nicht überein</string>
<string name="invalid_jid">Ungültige Jabber ID</string>
</resources> </resources>

View File

@ -164,5 +164,9 @@
<string name="mgmt_account_disable">Temporarily disable</string> <string name="mgmt_account_disable">Temporarily disable</string>
<string name="mgmt_account_enable">Enable</string> <string name="mgmt_account_enable">Enable</string>
<string name="attach_record_voice">Record voice</string> <string name="attach_record_voice">Record voice</string>
<string name="account_settings">Account Settings</string>
<string name="save">Save</string>
<string name="passwords_do_not_match">Passwords do not match</string>
<string name="invalid_jid">This is not a valid Jabber ID</string>
</resources> </resources>

View File

@ -135,7 +135,7 @@ public class Account extends AbstractEntity{
} }
public boolean hasErrorStatus() { public boolean hasErrorStatus() {
return getStatus() > STATUS_NO_INTERNET; return getStatus() > STATUS_NO_INTERNET && (getXmppConnection().getAttempt() >= 2);
} }
public void setResource(String resource) { public void setResource(String resource) {

View File

@ -29,6 +29,7 @@ public class Message extends AbstractEntity {
public static final int TYPE_TEXT = 0; public static final int TYPE_TEXT = 0;
public static final int TYPE_IMAGE = 1; public static final int TYPE_IMAGE = 1;
public static final int TYPE_AUDIO = 2;
public static String CONVERSATION = "conversationUuid"; public static String CONVERSATION = "conversationUuid";
public static String COUNTERPART = "counterpart"; public static String COUNTERPART = "counterpart";

View File

@ -242,10 +242,17 @@ public class XmppConnectionService extends Service {
} else if (account.getStatus() == Account.STATUS_REGISTRATION_SUCCESSFULL) { } else if (account.getStatus() == Account.STATUS_REGISTRATION_SUCCESSFULL) {
databaseBackend.updateAccount(account); databaseBackend.updateAccount(account);
reconnectAccount(account, true); reconnectAccount(account, true);
} else { } else if (account.getStatus() != Account.STATUS_CONNECTING) {
UIHelper.showErrorNotification(getApplicationContext(), int next = account.getXmppConnection().getTimeToNextAttempt();
getAccounts()); Log.d(LOGTAG, account.getJid()
+ ": error connecting account. try again in " + next
+ "s for the "
+ (account.getXmppConnection().getAttempt() + 1)
+ " time");
scheduleWakeupCall(next, false);
} }
UIHelper.showErrorNotification(getApplicationContext(),
getAccounts());
} }
}; };
@ -576,8 +583,6 @@ public class XmppConnectionService extends Service {
statusListener.onStatusChanged(account); statusListener.onStatusChanged(account);
} }
} }
// TODO 3 remaining cases
if (account.getStatus() == Account.STATUS_ONLINE) { if (account.getStatus() == Account.STATUS_ONLINE) {
long lastReceived = account.getXmppConnection().lastPaketReceived; long lastReceived = account.getXmppConnection().lastPaketReceived;
long lastSent = account.getXmppConnection().lastPingSent; long lastSent = account.getXmppConnection().lastPingSent;
@ -605,15 +610,9 @@ public class XmppConnectionService extends Service {
+ ": time out during connect reconnecting"); + ": time out during connect reconnecting");
reconnectAccount(account, true); reconnectAccount(account, true);
} else { } else {
Log.d(LOGTAG, if (account.getXmppConnection().getTimeToNextAttempt() <= 0) {
"seconds since last connect:" reconnectAccount(account, true);
+ ((SystemClock.elapsedRealtime() - account }
.getXmppConnection().lastConnect) / 1000));
Log.d(LOGTAG,
account.getJid() + ": status="
+ account.getStatus());
// TODO notify user of ssl cert problem or auth problem
// or what ever
} }
// in any case. reschedule wakup call // in any case. reschedule wakup call
this.scheduleWakeupCall(PING_MAX_INTERVAL, true); this.scheduleWakeupCall(PING_MAX_INTERVAL, true);
@ -676,7 +675,6 @@ public class XmppConnectionService extends Service {
this.pingIntent, 0); this.pingIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
timeToWake, pendingPingIntent); timeToWake, pendingPingIntent);
// Log.d(LOGTAG,"schedule ping in "+seconds+" seconds");
} else { } else {
long scheduledTime = this.pingIntent.getLongExtra("time", 0); long scheduledTime = this.pingIntent.getLongExtra("time", 0);
if (scheduledTime < SystemClock.elapsedRealtime() if (scheduledTime < SystemClock.elapsedRealtime()
@ -687,7 +685,6 @@ public class XmppConnectionService extends Service {
context, 0, this.pingIntent, 0); context, 0, this.pingIntent, 0);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
timeToWake, pendingPingIntent); timeToWake, pendingPingIntent);
// Log.d(LOGTAG,"reschedule old ping to ping in "+seconds+" seconds");
} }
} }
} else { } else {
@ -729,11 +726,10 @@ public class XmppConnectionService extends Service {
@Override @Override
public void onBind(Account account) { public void onBind(Account account) {
databaseBackend.clearPresences(account); databaseBackend.clearPresences(account); //contact presences
account.clearPresences(); // self presences account.clearPresences(); // self presences
if (account.getXmppConnection().hasFeatureRosterManagment()) { updateRoster(account, null);
updateRoster(account, null); sendPresence(account);
}
connectMultiModeConversations(account); connectMultiModeConversations(account);
if (convChangedListener != null) { if (convChangedListener != null) {
convChangedListener.onConversationListChanged(); convChangedListener.onConversationListChanged();
@ -829,16 +825,16 @@ public class XmppConnectionService extends Service {
} }
} }
} }
private void resendMessage(Message message) { private void resendMessage(Message message) {
Account account = message.getConversation().getAccount(); Account account = message.getConversation().getAccount();
MessagePacket packet = null; MessagePacket packet = null;
if (message.getEncryption() == Message.ENCRYPTION_NONE) { if (message.getEncryption() == Message.ENCRYPTION_NONE) {
packet = prepareMessagePacket(account, message,null); packet = prepareMessagePacket(account, message, null);
} else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) { } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTED) {
packet = prepareMessagePacket(account, message, null); packet = prepareMessagePacket(account, message, null);
packet.setBody("This is an XEP-0027 encryted message"); packet.setBody("This is an XEP-0027 encryted message");
if (message.getEncryptedBody()==null) { if (message.getEncryptedBody() == null) {
markMessage(message, Message.STATUS_SEND_FAILED); markMessage(message, Message.STATUS_SEND_FAILED);
return; return;
} }
@ -850,7 +846,7 @@ public class XmppConnectionService extends Service {
packet.addChild("x", "jabber:x:encrypted").setContent( packet.addChild("x", "jabber:x:encrypted").setContent(
message.getBody()); message.getBody());
} }
if (packet!=null) { if (packet != null) {
account.getXmppConnection().sendMessagePacket(packet); account.getXmppConnection().sendMessagePacket(packet);
markMessage(message, Message.STATUS_SEND); markMessage(message, Message.STATUS_SEND);
} }
@ -1159,8 +1155,7 @@ public class XmppConnectionService extends Service {
if (accountChangedListener != null) { if (accountChangedListener != null) {
accountChangedListener.onAccountListChangedListener(); accountChangedListener.onAccountListChangedListener();
} }
UIHelper.showErrorNotification(getApplicationContext(), UIHelper.showErrorNotification(getApplicationContext(), getAccounts());
getAccounts());
} }
public void deleteAccount(Account account) { public void deleteAccount(Account account) {
@ -1172,8 +1167,7 @@ public class XmppConnectionService extends Service {
if (accountChangedListener != null) { if (accountChangedListener != null) {
accountChangedListener.onAccountListChangedListener(); accountChangedListener.onAccountListChangedListener();
} }
UIHelper.showErrorNotification(getApplicationContext(), UIHelper.showErrorNotification(getApplicationContext(), getAccounts());
getAccounts());
} }
public void setOnConversationListChangedListener( public void setOnConversationListChangedListener(
@ -1394,16 +1388,15 @@ public class XmppConnectionService extends Service {
contact.getAccount().getXmppConnection().sendPresencePacket(packet); contact.getAccount().getXmppConnection().sendPresencePacket(packet);
} }
public void sendPgpPresence(Account account, String signature) { public void sendPresence(Account account) {
PresencePacket packet = new PresencePacket(); PresencePacket packet = new PresencePacket();
packet.setAttribute("from", account.getFullJid()); packet.setAttribute("from", account.getFullJid());
Element status = new Element("status"); String sig = account.getPgpSignature();
status.setContent("online"); if (sig!=null) {
packet.addChild(status); packet.addChild("status").setContent("online");
Element x = new Element("x"); packet.addChild("x","jabber:x:signed").setContent(sig);
x.setAttribute("xmlns", "jabber:x:signed"); }
x.setContent(signature); Log.d(LOGTAG,packet.toString());
packet.addChild(x);
account.getXmppConnection().sendPresencePacket(packet); account.getXmppConnection().sendPresencePacket(packet);
} }
@ -1427,7 +1420,6 @@ public class XmppConnectionService extends Service {
this.tlsException = null; this.tlsException = null;
} }
// TODO dont let thread sleep but schedule wake up
public void reconnectAccount(final Account account, final boolean force) { public void reconnectAccount(final Account account, final boolean force) {
new Thread(new Runnable() { new Thread(new Runnable() {
@ -1492,8 +1484,9 @@ public class XmppConnectionService extends Service {
} }
return false; return false;
} }
public boolean markMessage(Conversation conversation, String uuid, int status) { public boolean markMessage(Conversation conversation, String uuid,
int status) {
for (Message message : conversation.getMessages()) { for (Message message : conversation.getMessages()) {
if (message.getUuid().equals(uuid)) { if (message.getUuid().equals(uuid)) {
markMessage(message, status); markMessage(message, status);

View File

@ -722,12 +722,19 @@ public class ConversationActivity extends XmppActivity {
encryptTextMessage(); encryptTextMessage();
} else if (requestCode == REQUEST_IMAGE_CAPTURE) { } else if (requestCode == REQUEST_IMAGE_CAPTURE) {
attachImageToConversation(getSelectedConversation(), null); attachImageToConversation(getSelectedConversation(), null);
} else if (requestCode == REQUEST_RECORD_AUDIO) {
Log.d("xmppService",data.getData().toString());
attachAudioToConversation(getSelectedConversation(),data.getData());
} else { } else {
Log.d(LOGTAG,"unknown result code:"+requestCode); Log.d(LOGTAG,"unknown result code:"+requestCode);
} }
} }
} }
private void attachAudioToConversation(Conversation conversation, Uri uri) {
}
private void attachImageToConversation(Conversation conversation, Uri uri) { private void attachImageToConversation(Conversation conversation, Uri uri) {
prepareImageToast = Toast.makeText(getApplicationContext(), getText(R.string.preparing_image), Toast.LENGTH_LONG); prepareImageToast = Toast.makeText(getApplicationContext(), getText(R.string.preparing_image), Toast.LENGTH_LONG);
prepareImageToast.show(); prepareImageToast.show();

View File

@ -51,27 +51,19 @@ public class EditAccount extends DialogFragment {
final CheckBox registerAccount = (CheckBox) view final CheckBox registerAccount = (CheckBox) view
.findViewById(R.id.edit_account_register_new); .findViewById(R.id.edit_account_register_new);
final String okButtonDesc;
if (account != null) { if (account != null) {
jidText.setText(account.getJid()); jidText.setText(account.getJid());
password.setText(account.getPassword()); password.setText(account.getPassword());
Log.d("xmppService","mein debugger. account != null");
if (account.isOptionSet(Account.OPTION_REGISTER)) { if (account.isOptionSet(Account.OPTION_REGISTER)) {
registerAccount.setChecked(true); registerAccount.setChecked(true);
builder.setTitle(getString(R.string.register_account));
okButtonDesc = "Register";
passwordConfirm.setVisibility(View.VISIBLE); passwordConfirm.setVisibility(View.VISIBLE);
passwordConfirm.setText(account.getPassword()); passwordConfirm.setText(account.getPassword());
} else { } else {
registerAccount.setVisibility(View.GONE); registerAccount.setVisibility(View.GONE);
builder.setTitle("Edit account");
okButtonDesc = "Edit";
} }
} else {
builder.setTitle("Add account");
okButtonDesc = "Add";
} }
builder.setTitle(R.string.account_settings);
registerAccount registerAccount
.setOnCheckedChangeListener(new OnCheckedChangeListener() { .setOnCheckedChangeListener(new OnCheckedChangeListener() {
@ -79,26 +71,19 @@ public class EditAccount extends DialogFragment {
@Override @Override
public void onCheckedChanged(CompoundButton buttonView, public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) { boolean isChecked) {
AlertDialog d = (AlertDialog) getDialog();
Button positiveButton = (Button) d
.getButton(Dialog.BUTTON_POSITIVE);
if (isChecked) { if (isChecked) {
d.setTitle(getString(R.string.register_account));
positiveButton.setText("Register");
passwordConfirm.setVisibility(View.VISIBLE); passwordConfirm.setVisibility(View.VISIBLE);
confirmPwDesc.setVisibility(View.VISIBLE); confirmPwDesc.setVisibility(View.VISIBLE);
} else { } else {
d.setTitle("Add account");
passwordConfirm.setVisibility(View.GONE); passwordConfirm.setVisibility(View.GONE);
positiveButton.setText("Add");
confirmPwDesc.setVisibility(View.GONE); confirmPwDesc.setVisibility(View.GONE);
} }
} }
}); });
builder.setView(view); builder.setView(view);
builder.setNeutralButton("Cancel", null); builder.setNeutralButton(R.string.cancel, null);
builder.setPositiveButton(okButtonDesc, null); builder.setPositiveButton(R.string.save, null);
return builder.create(); return builder.create();
} }
@ -114,7 +99,9 @@ public class EditAccount extends DialogFragment {
String jid = jidEdit.getText().toString(); String jid = jidEdit.getText().toString();
EditText passwordEdit = (EditText) d EditText passwordEdit = (EditText) d
.findViewById(R.id.account_password); .findViewById(R.id.account_password);
EditText passwordConfirmEdit = (EditText) d.findViewById(R.id.account_password_confirm2);
String password = passwordEdit.getText().toString(); String password = passwordEdit.getText().toString();
String passwordConfirm = passwordConfirmEdit.getText().toString();
CheckBox register = (CheckBox) d.findViewById(R.id.edit_account_register_new); CheckBox register = (CheckBox) d.findViewById(R.id.edit_account_register_new);
String username; String username;
String server; String server;
@ -123,9 +110,15 @@ public class EditAccount extends DialogFragment {
username = parts[0]; username = parts[0];
server = parts[1]; server = parts[1];
} else { } else {
jidEdit.setError("Invalid Jabber ID"); jidEdit.setError(getString(R.string.invalid_jid));
return; return;
} }
if (register.isChecked()) {
if (!passwordConfirm.equals(password)) {
passwordConfirmEdit.setError(getString(R.string.passwords_do_not_match));
return;
}
}
if (account != null) { if (account != null) {
account.setPassword(password); account.setPassword(password);
account.setUsername(username); account.setUsername(username);

View File

@ -175,7 +175,7 @@ public abstract class XmppActivity extends Activity {
@Override @Override
public void success() { public void success() {
xmppConnectionService.databaseBackend.updateAccount(account); xmppConnectionService.databaseBackend.updateAccount(account);
xmppConnectionService.sendPgpPresence(account, account.getPgpSignature()); xmppConnectionService.sendPresence(account);
if (conversation!=null) { if (conversation!=null) {
conversation.setNextEncryption(Message.ENCRYPTION_PGP); conversation.setNextEncryption(Message.ENCRYPTION_PGP);
} }

View File

@ -30,7 +30,6 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager; import javax.net.ssl.X509TrustManager;
import org.json.JSONException;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import android.os.Bundle; import android.os.Bundle;
@ -88,6 +87,8 @@ public class XmppConnection implements Runnable {
public long lastPingSent = 0; public long lastPingSent = 0;
public long lastConnect = 0; public long lastConnect = 0;
public long lastSessionStarted = 0; public long lastSessionStarted = 0;
private int attempt = 0;
private static final int PACKET_IQ = 0; private static final int PACKET_IQ = 0;
private static final int PACKET_MESSAGE = 1; private static final int PACKET_MESSAGE = 1;
@ -113,6 +114,9 @@ public class XmppConnection implements Runnable {
if ((nextStatus == Account.STATUS_OFFLINE)&&(account.getStatus() != Account.STATUS_CONNECTING)&&(account.getStatus() != Account.STATUS_ONLINE)&&(account.getStatus() != Account.STATUS_DISABLED)) { if ((nextStatus == Account.STATUS_OFFLINE)&&(account.getStatus() != Account.STATUS_CONNECTING)&&(account.getStatus() != Account.STATUS_ONLINE)&&(account.getStatus() != Account.STATUS_DISABLED)) {
return; return;
} }
if (nextStatus == Account.STATUS_ONLINE) {
this.attempt = 0;
}
account.setStatus(nextStatus); account.setStatus(nextStatus);
if (statusListener != null) { if (statusListener != null) {
statusListener.onStatusChanged(account); statusListener.onStatusChanged(account);
@ -123,6 +127,7 @@ public class XmppConnection implements Runnable {
protected void connect() { protected void connect() {
Log.d(LOGTAG,account.getJid()+ ": connecting"); Log.d(LOGTAG,account.getJid()+ ": connecting");
lastConnect = SystemClock.elapsedRealtime(); lastConnect = SystemClock.elapsedRealtime();
this.attempt++;
try { try {
shouldAuthenticate = shouldBind = !account.isOptionSet(Account.OPTION_REGISTER); shouldAuthenticate = shouldBind = !account.isOptionSet(Account.OPTION_REGISTER);
tagReader = new XmlReader(wakeLock); tagReader = new XmlReader(wakeLock);
@ -609,25 +614,10 @@ public class XmppConnection implements Runnable {
}); });
} }
private void sendInitialPresence() {
PresencePacket packet = new PresencePacket();
packet.setAttribute("from", account.getFullJid());
if (account.getKeys().has("pgp_signature")) {
try {
String signature = account.getKeys().getString("pgp_signature");
packet.addChild("status").setContent("online");
packet.addChild("x","jabber:x:signed").setContent(signature);
} catch (JSONException e) {
//
}
}
this.sendPresencePacket(packet);
}
private void sendBindRequest() throws IOException { private void sendBindRequest() throws IOException {
IqPacket iq = new IqPacket(IqPacket.TYPE_SET); IqPacket iq = new IqPacket(IqPacket.TYPE_SET);
iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind").addChild("resource").setContent(account.getResource()); iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind").addChild("resource").setContent(account.getResource());
this.sendIqPacket(iq, new OnIqPacketReceived() { this.sendUnboundIqPacket(iq, new OnIqPacketReceived() {
@Override @Override
public void onIqPacketReceived(Account account, IqPacket packet) { public void onIqPacketReceived(Account account, IqPacket packet) {
String resource = packet.findChild("bind").findChild("jid") String resource = packet.findChild("bind").findChild("jid")
@ -642,7 +632,6 @@ public class XmppConnection implements Runnable {
EnablePacket enable = new EnablePacket(smVersion); EnablePacket enable = new EnablePacket(smVersion);
tagWriter.writeStanzaAsync(enable); tagWriter.writeStanzaAsync(enable);
} }
sendInitialPresence();
sendServiceDiscoveryInfo(account.getServer()); sendServiceDiscoveryInfo(account.getServer());
sendServiceDiscoveryItems(account.getServer()); sendServiceDiscoveryItems(account.getServer());
if (bindListener !=null) { if (bindListener !=null) {
@ -655,9 +644,8 @@ public class XmppConnection implements Runnable {
if (this.streamFeatures.hasChild("session")) { if (this.streamFeatures.hasChild("session")) {
Log.d(LOGTAG,account.getJid()+": sending deprecated session"); Log.d(LOGTAG,account.getJid()+": sending deprecated session");
IqPacket startSession = new IqPacket(IqPacket.TYPE_SET); IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session"); //setContent("") startSession.addChild("session","urn:ietf:params:xml:ns:xmpp-session");
startSession.setId(nextRandomId()); this.sendUnboundIqPacket(startSession, null);
this.sendPacket(startSession, null);
} }
} }
@ -757,6 +745,14 @@ public class XmppConnection implements Runnable {
packet.setFrom(account.getFullJid()); packet.setFrom(account.getFullJid());
this.sendPacket(packet, callback); this.sendPacket(packet, callback);
} }
public void sendUnboundIqPacket(IqPacket packet, OnIqPacketReceived callback) {
if (packet.getId()==null) {
String id = nextRandomId();
packet.setAttribute("id", id);
}
this.sendPacket(packet, callback);
}
public void sendMessagePacket(MessagePacket packet) { public void sendMessagePacket(MessagePacket packet) {
this.sendPacket(packet, null); this.sendPacket(packet, null);
@ -916,4 +912,14 @@ public class XmppConnection implements Runnable {
Log.d(LOGTAG,"adding "+jid+" to pending subscriptions"); Log.d(LOGTAG,"adding "+jid+" to pending subscriptions");
this.pendingSubscriptions.add(jid); this.pendingSubscriptions.add(jid);
} }
public int getTimeToNextAttempt() {
int interval = (int) (25 * Math.pow(1.5,attempt));
int secondsSinceLast = (int) ((SystemClock.elapsedRealtime() - this.lastConnect) / 1000);
return interval - secondsSinceLast;
}
public int getAttempt() {
return this.attempt;
}
} }