reworked account managment. now status display actually works
This commit is contained in:
parent
14a171b088
commit
0d80d88736
|
@ -35,16 +35,16 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Status: "
|
android:text="Status: "
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textSize="14sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/account_status"
|
android:id="@+id/account_status"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="#669900"
|
android:textColor="#669900"
|
||||||
android:text="Online"
|
android:text="unknown"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textSize="14sp"/>
|
android:textSize="16sp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,20 @@ public class Account extends AbstractEntity{
|
||||||
|
|
||||||
public static final int OPTION_USETLS = 0;
|
public static final int OPTION_USETLS = 0;
|
||||||
|
|
||||||
|
public static final int STATUS_OFFLINE = 0;
|
||||||
|
public static final int STATUS_ONLINE = 1;
|
||||||
|
public static final int STATUS_UNAUTHORIZED = 2;
|
||||||
|
public static final int STATUS_NOINTERNET = 3;
|
||||||
|
public static final int STATUS_TLS_ERROR = 4;
|
||||||
|
public static final int STATUS_SERVER_NOT_FOUND = 5;
|
||||||
|
|
||||||
protected String username;
|
protected String username;
|
||||||
protected String server;
|
protected String server;
|
||||||
protected String password;
|
protected String password;
|
||||||
protected int options;
|
protected int options;
|
||||||
protected String rosterVersion;
|
protected String rosterVersion;
|
||||||
|
protected String resource;
|
||||||
|
protected int status = 0;
|
||||||
|
|
||||||
protected boolean online = false;
|
protected boolean online = false;
|
||||||
|
|
||||||
|
@ -70,8 +79,16 @@ public class Account extends AbstractEntity{
|
||||||
this.password = password;
|
this.password = password;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOnline() {
|
public void setStatus(int status) {
|
||||||
return online;
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() {
|
||||||
|
return this.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResource(String resource) {
|
||||||
|
this.resource = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getJid() {
|
public String getJid() {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package de.gultsch.chat.services;
|
package de.gultsch.chat.services;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -10,7 +9,7 @@ import de.gultsch.chat.entities.Contact;
|
||||||
import de.gultsch.chat.entities.Conversation;
|
import de.gultsch.chat.entities.Conversation;
|
||||||
import de.gultsch.chat.entities.Message;
|
import de.gultsch.chat.entities.Message;
|
||||||
import de.gultsch.chat.persistance.DatabaseBackend;
|
import de.gultsch.chat.persistance.DatabaseBackend;
|
||||||
import de.gultsch.chat.ui.ConversationActivity;
|
import de.gultsch.chat.ui.OnAccountListChangedListener;
|
||||||
import de.gultsch.chat.ui.OnConversationListChangedListener;
|
import de.gultsch.chat.ui.OnConversationListChangedListener;
|
||||||
import de.gultsch.chat.ui.OnRosterFetchedListener;
|
import de.gultsch.chat.ui.OnRosterFetchedListener;
|
||||||
import de.gultsch.chat.utils.UIHelper;
|
import de.gultsch.chat.utils.UIHelper;
|
||||||
|
@ -19,20 +18,15 @@ import de.gultsch.chat.xmpp.IqPacket;
|
||||||
import de.gultsch.chat.xmpp.MessagePacket;
|
import de.gultsch.chat.xmpp.MessagePacket;
|
||||||
import de.gultsch.chat.xmpp.OnIqPacketReceived;
|
import de.gultsch.chat.xmpp.OnIqPacketReceived;
|
||||||
import de.gultsch.chat.xmpp.OnMessagePacketReceived;
|
import de.gultsch.chat.xmpp.OnMessagePacketReceived;
|
||||||
|
import de.gultsch.chat.xmpp.OnStatusChanged;
|
||||||
import de.gultsch.chat.xmpp.XmppConnection;
|
import de.gultsch.chat.xmpp.XmppConnection;
|
||||||
import android.R;
|
|
||||||
import android.R.dimen;
|
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class XmppConnectionService extends Service {
|
public class XmppConnectionService extends Service {
|
||||||
|
@ -48,6 +42,7 @@ public class XmppConnectionService extends Service {
|
||||||
private Hashtable<Account, XmppConnection> connections = new Hashtable<Account, XmppConnection>();
|
private Hashtable<Account, XmppConnection> connections = new Hashtable<Account, XmppConnection>();
|
||||||
|
|
||||||
private OnConversationListChangedListener convChangedListener = null;
|
private OnConversationListChangedListener convChangedListener = null;
|
||||||
|
private OnAccountListChangedListener accountChangedListener = null;
|
||||||
|
|
||||||
private final IBinder mBinder = new XmppConnectionBinder();
|
private final IBinder mBinder = new XmppConnectionBinder();
|
||||||
private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() {
|
private OnMessagePacketReceived messageListener = new OnMessagePacketReceived() {
|
||||||
|
@ -79,6 +74,16 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private OnStatusChanged statusListener = new OnStatusChanged() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStatusChanged(Account account) {
|
||||||
|
Log.d(LOGTAG,account.getJid()+" changed status to "+account.getStatus());
|
||||||
|
if (accountChangedListener != null) {
|
||||||
|
accountChangedListener.onAccountListChangedListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
public class XmppConnectionBinder extends Binder {
|
public class XmppConnectionBinder extends Binder {
|
||||||
public XmppConnectionService getService() {
|
public XmppConnectionService getService() {
|
||||||
|
@ -88,15 +93,10 @@ public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
if (!connections.containsKey(account)) {
|
if (!connections.containsKey(account)) {
|
||||||
XmppConnection connection = new XmppConnection(account, pm);
|
|
||||||
connection
|
this.connections.put(account, this.createConnection(account));
|
||||||
.setOnMessagePacketReceivedListener(this.messageListener);
|
|
||||||
Thread thread = new Thread(connection);
|
|
||||||
thread.start();
|
|
||||||
this.connections.put(account, connection);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
|
@ -107,6 +107,17 @@ public class XmppConnectionService extends Service {
|
||||||
databaseBackend = DatabaseBackend.getInstance(getApplicationContext());
|
databaseBackend = DatabaseBackend.getInstance(getApplicationContext());
|
||||||
this.accounts = databaseBackend.getAccounts();
|
this.accounts = databaseBackend.getAccounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XmppConnection createConnection(Account account) {
|
||||||
|
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||||
|
XmppConnection connection = new XmppConnection(account, pm);
|
||||||
|
connection
|
||||||
|
.setOnMessagePacketReceivedListener(this.messageListener);
|
||||||
|
connection.setOnStatusChangedListener(this.statusListener );
|
||||||
|
Thread thread = new Thread(connection);
|
||||||
|
thread.start();
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
|
@ -114,68 +125,49 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(final Account account, final Message message) {
|
public void sendMessage(final Account account, final Message message) {
|
||||||
new Thread() {
|
Log.d(LOGTAG, "sending message for " + account.getJid() + " to: "
|
||||||
@Override
|
+ message.getCounterpart());
|
||||||
public void run() {
|
databaseBackend.createMessage(message);
|
||||||
Log.d(LOGTAG, "sending message for " + account.getJid()
|
MessagePacket packet = new MessagePacket();
|
||||||
+ " to: " + message.getCounterpart());
|
packet.setType(MessagePacket.TYPE_CHAT);
|
||||||
databaseBackend.createMessage(message);
|
packet.setTo(message.getCounterpart());
|
||||||
MessagePacket packet = new MessagePacket();
|
packet.setFrom(account.getJid());
|
||||||
packet.setType(MessagePacket.TYPE_CHAT);
|
packet.setBody(message.getBody());
|
||||||
packet.setTo(message.getCounterpart());
|
connections.get(account).sendMessagePacket(packet);
|
||||||
packet.setFrom(account.getJid());
|
message.setStatus(Message.STATUS_SEND);
|
||||||
packet.setBody(message.getBody());
|
databaseBackend.updateMessage(message);
|
||||||
try {
|
|
||||||
connections.get(account).sendMessagePacket(packet);
|
|
||||||
message.setStatus(Message.STATUS_SEND);
|
|
||||||
databaseBackend.updateMessage(message);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(LOGTAG,
|
|
||||||
"io exception during send. message is in database. will try again later");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void getRoster(final Account account,
|
public void getRoster(final Account account,
|
||||||
final OnRosterFetchedListener listener) {
|
final OnRosterFetchedListener listener) {
|
||||||
new Thread() {
|
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
||||||
@Override
|
Element query = new Element("query");
|
||||||
public void run() {
|
query.setAttribute("xmlns", "jabber:iq:roster");
|
||||||
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
|
query.setAttribute("ver", "");
|
||||||
Element query = new Element("query");
|
iqPacket.addChild(query);
|
||||||
query.setAttribute("xmlns", "jabber:iq:roster");
|
connections.get(account).sendIqPacket(iqPacket,
|
||||||
query.setAttribute("ver", "");
|
new OnIqPacketReceived() {
|
||||||
iqPacket.addChild(query);
|
|
||||||
try {
|
|
||||||
connections.get(account).sendIqPacket(iqPacket,
|
|
||||||
new OnIqPacketReceived() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onIqPacketReceived(Account account,
|
public void onIqPacketReceived(Account account,
|
||||||
IqPacket packet) {
|
IqPacket packet) {
|
||||||
Element roster = packet.findChild("query");
|
Element roster = packet.findChild("query");
|
||||||
List<Contact> contacts = new ArrayList<Contact>();
|
List<Contact> contacts = new ArrayList<Contact>();
|
||||||
for (Element item : roster.getChildren()) {
|
for (Element item : roster.getChildren()) {
|
||||||
String name = item.getAttribute("name");
|
String name = item.getAttribute("name");
|
||||||
String jid = item.getAttribute("jid");
|
String jid = item.getAttribute("jid");
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = jid.split("@")[0];
|
name = jid.split("@")[0];
|
||||||
}
|
}
|
||||||
Contact contact = new Contact(account,
|
Contact contact = new Contact(account, name, jid,
|
||||||
name, jid, null);
|
null);
|
||||||
contacts.add(contact);
|
contacts.add(contact);
|
||||||
}
|
}
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onRosterFetched(contacts);
|
listener.onRosterFetched(contacts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(LOGTAG, "io error during roster fetch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addConversation(Conversation conversation) {
|
public void addConversation(Conversation conversation) {
|
||||||
|
@ -249,14 +241,32 @@ public class XmppConnectionService extends Service {
|
||||||
|
|
||||||
public void createAccount(Account account) {
|
public void createAccount(Account account) {
|
||||||
databaseBackend.createAccount(account);
|
databaseBackend.createAccount(account);
|
||||||
|
this.accounts.add(account);
|
||||||
|
this.connections.put(account, this.createConnection(account));
|
||||||
|
if (accountChangedListener!=null) accountChangedListener.onAccountListChangedListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAccount(Account account) {
|
public void updateAccount(Account account) {
|
||||||
databaseBackend.updateAccount(account);
|
databaseBackend.updateAccount(account);
|
||||||
|
XmppConnection connection = this.connections.get(account);
|
||||||
|
if (connection != null) {
|
||||||
|
connection.disconnect();
|
||||||
|
this.connections.remove(account);
|
||||||
|
}
|
||||||
|
this.connections.put(account, this.createConnection(account));
|
||||||
|
if (accountChangedListener!=null) accountChangedListener.onAccountListChangedListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteAccount(Account account) {
|
public void deleteAccount(Account account) {
|
||||||
|
Log.d(LOGTAG,"called delete account");
|
||||||
|
if (this.connections.containsKey(account)) {
|
||||||
|
Log.d(LOGTAG,"found connection. disconnecting");
|
||||||
|
this.connections.get(account).disconnect();
|
||||||
|
this.connections.remove(account);
|
||||||
|
this.accounts.remove(account);
|
||||||
|
}
|
||||||
databaseBackend.deleteAccount(account);
|
databaseBackend.deleteAccount(account);
|
||||||
|
if (accountChangedListener!=null) accountChangedListener.onAccountListChangedListener();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnConversationListChangedListener(
|
public void setOnConversationListChangedListener(
|
||||||
|
@ -267,4 +277,12 @@ public class XmppConnectionService extends Service {
|
||||||
public void removeOnConversationListChangedListener() {
|
public void removeOnConversationListChangedListener() {
|
||||||
this.convChangedListener = null;
|
this.convChangedListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOnAccountListChangedListener(OnAccountListChangedListener listener) {
|
||||||
|
this.accountChangedListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeOnAccountListChangedListener() {
|
||||||
|
this.accountChangedListener = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import java.util.List;
|
||||||
import de.gultsch.chat.R;
|
import de.gultsch.chat.R;
|
||||||
import de.gultsch.chat.entities.Account;
|
import de.gultsch.chat.entities.Account;
|
||||||
import de.gultsch.chat.ui.EditAccount.EditAccountListener;
|
import de.gultsch.chat.ui.EditAccount.EditAccountListener;
|
||||||
import android.app.ActionBar;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -25,28 +24,72 @@ import android.widget.TextView;
|
||||||
|
|
||||||
public class ManageAccountActivity extends XmppActivity {
|
public class ManageAccountActivity extends XmppActivity {
|
||||||
|
|
||||||
|
|
||||||
protected List<Account> accountList = new ArrayList<Account>();
|
protected List<Account> accountList = new ArrayList<Account>();
|
||||||
protected ListView accountListView;
|
protected ListView accountListView;
|
||||||
protected ArrayAdapter<Account> accountListViewAdapter;
|
protected ArrayAdapter<Account> accountListViewAdapter;
|
||||||
|
protected OnAccountListChangedListener accountChanged = new OnAccountListChangedListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccountListChangedListener() {
|
||||||
|
Log.d("xmppService", "ui on account list changed listener");
|
||||||
|
accountList.clear();
|
||||||
|
accountList.addAll(xmppConnectionService.getAccounts());
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (accountList.size() == 1) {
|
||||||
|
startActivity(new Intent(getApplicationContext(),
|
||||||
|
NewConversationActivity.class));
|
||||||
|
}
|
||||||
|
accountListViewAdapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
setContentView(R.layout.manage_accounts);
|
setContentView(R.layout.manage_accounts);
|
||||||
|
|
||||||
accountListView = (ListView) findViewById(R.id.account_list);
|
accountListView = (ListView) findViewById(R.id.account_list);
|
||||||
accountListViewAdapter = new ArrayAdapter<Account>(getApplicationContext(), R.layout.account_row, this.accountList) {
|
accountListViewAdapter = new ArrayAdapter<Account>(
|
||||||
|
getApplicationContext(), R.layout.account_row, this.accountList) {
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View view, ViewGroup parent) {
|
public View getView(int position, View view, ViewGroup parent) {
|
||||||
|
Account account = getItem(position);
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
view = (View) inflater.inflate(R.layout.account_row, null);
|
view = (View) inflater.inflate(R.layout.account_row, null);
|
||||||
}
|
}
|
||||||
((TextView) view.findViewById(R.id.account_jid)).setText(getItem(position).getJid());
|
((TextView) view.findViewById(R.id.account_jid))
|
||||||
|
.setText(account.getJid());
|
||||||
|
TextView statusView = (TextView) view
|
||||||
|
.findViewById(R.id.account_status);
|
||||||
|
switch (account.getStatus()) {
|
||||||
|
case Account.STATUS_ONLINE:
|
||||||
|
statusView.setText("online");
|
||||||
|
statusView.setTextColor(0xFF83b600);
|
||||||
|
break;
|
||||||
|
case Account.STATUS_OFFLINE:
|
||||||
|
statusView.setText("offline");
|
||||||
|
statusView.setTextColor(0xFFe92727);
|
||||||
|
break;
|
||||||
|
case Account.STATUS_UNAUTHORIZED:
|
||||||
|
statusView.setText("unauthorized");
|
||||||
|
statusView.setTextColor(0xFFe92727);
|
||||||
|
break;
|
||||||
|
case Account.STATUS_SERVER_NOT_FOUND:
|
||||||
|
statusView.setText("server not found");
|
||||||
|
statusView.setTextColor(0xFFe92727);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -54,12 +97,12 @@ public class ManageAccountActivity extends XmppActivity {
|
||||||
accountListView.setOnItemClickListener(new OnItemClickListener() {
|
accountListView.setOnItemClickListener(new OnItemClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> arg0, View view, int position,
|
public void onItemClick(AdapterView<?> arg0, View view,
|
||||||
long arg3) {
|
int position, long arg3) {
|
||||||
EditAccount dialog = new EditAccount();
|
EditAccount dialog = new EditAccount();
|
||||||
dialog.setAccount(accountList.get(position));
|
dialog.setAccount(accountList.get(position));
|
||||||
dialog.setEditAccountListener(new EditAccountListener() {
|
dialog.setEditAccountListener(new EditAccountListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccountEdited(Account account) {
|
public void onAccountEdited(Account account) {
|
||||||
xmppConnectionService.updateAccount(account);
|
xmppConnectionService.updateAccount(account);
|
||||||
|
@ -67,41 +110,27 @@ public class ManageAccountActivity extends XmppActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccountDelete(Account account) {
|
public void onAccountDelete(Account account) {
|
||||||
|
|
||||||
Log.d("gultsch","deleting account:"+account.getJid());
|
|
||||||
|
|
||||||
xmppConnectionService.deleteAccount(account);
|
xmppConnectionService.deleteAccount(account);
|
||||||
|
|
||||||
//dont bother finding the right account in the frontend list. just reload
|
|
||||||
accountList.clear();
|
|
||||||
accountList.addAll(xmppConnectionService.getAccounts());
|
|
||||||
|
|
||||||
accountListViewAdapter.notifyDataSetChanged();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dialog.show(getFragmentManager(),"edit_account");
|
dialog.show(getFragmentManager(), "edit_account");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
protected void onStop() {
|
||||||
super.onStart();
|
super.onStop();
|
||||||
if (xmppConnectionServiceBound) {
|
if (xmppConnectionServiceBound) {
|
||||||
this.accountList.clear();
|
xmppConnectionService.removeOnAccountListChangedListener();
|
||||||
this.accountList.addAll(xmppConnectionService
|
unbindService(mConnection);
|
||||||
.getAccounts());
|
xmppConnectionServiceBound = false;
|
||||||
accountListViewAdapter.notifyDataSetChanged();
|
|
||||||
if (this.accountList.size() == 0) {
|
|
||||||
getActionBar().setDisplayHomeAsUpEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void onBackendConnected() {
|
void onBackendConnected() {
|
||||||
Log.d("gultsch","called on backend connected");
|
xmppConnectionService.setOnAccountListChangedListener(accountChanged);
|
||||||
this.accountList.clear();
|
this.accountList.clear();
|
||||||
this.accountList.addAll(xmppConnectionService.getAccounts());
|
this.accountList.addAll(xmppConnectionService.getAccounts());
|
||||||
accountListViewAdapter.notifyDataSetChanged();
|
accountListViewAdapter.notifyDataSetChanged();
|
||||||
|
@ -110,14 +139,14 @@ public class ManageAccountActivity extends XmppActivity {
|
||||||
addAccount();
|
addAccount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
getMenuInflater().inflate(R.menu.manageaccounts, menu);
|
getMenuInflater().inflate(R.menu.manageaccounts, menu);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
@ -137,23 +166,18 @@ public class ManageAccountActivity extends XmppActivity {
|
||||||
final Activity activity = this;
|
final Activity activity = this;
|
||||||
EditAccount dialog = new EditAccount();
|
EditAccount dialog = new EditAccount();
|
||||||
dialog.setEditAccountListener(new EditAccountListener() {
|
dialog.setEditAccountListener(new EditAccountListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccountEdited(Account account) {
|
public void onAccountEdited(Account account) {
|
||||||
xmppConnectionService.createAccount(account);
|
xmppConnectionService.createAccount(account);
|
||||||
accountList.add(account);
|
|
||||||
accountListViewAdapter.notifyDataSetChanged();
|
|
||||||
activity.getActionBar().setDisplayHomeAsUpEnabled(true);
|
activity.getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
if (accountList.size() == 1) {
|
|
||||||
activity.startActivity(new Intent(activity,NewConversationActivity.class));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccountDelete(Account account) {
|
public void onAccountDelete(Account account) {
|
||||||
//this will never be called
|
// this will never be called
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
dialog.show(getFragmentManager(),"add_account");
|
dialog.show(getFragmentManager(), "add_account");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
5
src/de/gultsch/chat/ui/OnAccountListChangedListener.java
Normal file
5
src/de/gultsch/chat/ui/OnAccountListChangedListener.java
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
package de.gultsch.chat.ui;
|
||||||
|
|
||||||
|
public interface OnAccountListChangedListener {
|
||||||
|
public void onAccountListChangedListener();
|
||||||
|
}
|
|
@ -3,12 +3,37 @@ package de.gultsch.chat.xml;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class TagWriter {
|
public class TagWriter {
|
||||||
|
|
||||||
OutputStreamWriter writer;
|
private OutputStreamWriter outputStream;
|
||||||
|
private LinkedBlockingQueue<String> writeQueue = new LinkedBlockingQueue<String>();
|
||||||
|
private Thread writer = new Thread() {
|
||||||
|
public boolean shouldStop = false;
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while(!shouldStop) {
|
||||||
|
try {
|
||||||
|
String output = writeQueue.take();
|
||||||
|
outputStream.write(output);
|
||||||
|
outputStream.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d("xmppService", "error writing to stream");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
public TagWriter() {
|
public TagWriter() {
|
||||||
|
|
||||||
|
@ -16,31 +41,29 @@ public class TagWriter {
|
||||||
|
|
||||||
public TagWriter(OutputStream out) {
|
public TagWriter(OutputStream out) {
|
||||||
this.setOutputStream(out);
|
this.setOutputStream(out);
|
||||||
|
writer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutputStream(OutputStream out) {
|
public void setOutputStream(OutputStream out) {
|
||||||
this.writer = new OutputStreamWriter(out);
|
this.outputStream = new OutputStreamWriter(out);
|
||||||
|
if (!writer.isAlive()) writer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagWriter beginDocument() throws IOException {
|
public TagWriter beginDocument() {
|
||||||
writer.write("<?xml version='1.0'?>");
|
writeQueue.add("<?xml version='1.0'?>");
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TagWriter writeTag(Tag tag) throws IOException {
|
public TagWriter writeTag(Tag tag) {
|
||||||
writer.write(tag.toString());
|
writeQueue.add(tag.toString());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() throws IOException {
|
public void writeString(String string) {
|
||||||
writer.flush();
|
writeQueue.add(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeString(String string) throws IOException {
|
public void writeElement(Element element) {
|
||||||
writer.write(string);
|
writeQueue.add(element.toString());
|
||||||
}
|
|
||||||
|
|
||||||
public void writeElement(Element element) throws IOException {
|
|
||||||
writer.write(element.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
7
src/de/gultsch/chat/xmpp/OnStatusChanged.java
Normal file
7
src/de/gultsch/chat/xmpp/OnStatusChanged.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package de.gultsch.chat.xmpp;
|
||||||
|
|
||||||
|
import de.gultsch.chat.entities.Account;
|
||||||
|
|
||||||
|
public interface OnStatusChanged {
|
||||||
|
public void onStatusChanged(Account account);
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ public class XmppConnection implements Runnable {
|
||||||
private boolean isTlsEncrypted = false;
|
private boolean isTlsEncrypted = false;
|
||||||
private boolean isAuthenticated = false;
|
private boolean isAuthenticated = false;
|
||||||
//private boolean shouldUseTLS = false;
|
//private boolean shouldUseTLS = false;
|
||||||
private boolean shouldReConnect = true;
|
private boolean shouldConnect = true;
|
||||||
private boolean shouldBind = true;
|
private boolean shouldBind = true;
|
||||||
private boolean shouldAuthenticate = true;
|
private boolean shouldAuthenticate = true;
|
||||||
private Element streamFeatures;
|
private Element streamFeatures;
|
||||||
|
@ -52,8 +52,7 @@ public class XmppConnection implements Runnable {
|
||||||
private OnPresencePacketReceived presenceListener = null;
|
private OnPresencePacketReceived presenceListener = null;
|
||||||
private OnIqPacketReceived unregisteredIqListener = null;
|
private OnIqPacketReceived unregisteredIqListener = null;
|
||||||
private OnMessagePacketReceived messageListener = null;
|
private OnMessagePacketReceived messageListener = null;
|
||||||
|
private OnStatusChanged statusListener = null;
|
||||||
private String resource = null;
|
|
||||||
|
|
||||||
public XmppConnection(Account account, PowerManager pm) {
|
public XmppConnection(Account account, PowerManager pm) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
@ -66,7 +65,6 @@ public class XmppConnection implements Runnable {
|
||||||
protected void connect() {
|
protected void connect() {
|
||||||
try {
|
try {
|
||||||
socket = new Socket(account.getServer(), 5222);
|
socket = new Socket(account.getServer(), 5222);
|
||||||
Log.d(LOGTAG, "starting new socket");
|
|
||||||
OutputStream out = socket.getOutputStream();
|
OutputStream out = socket.getOutputStream();
|
||||||
tagWriter.setOutputStream(out);
|
tagWriter.setOutputStream(out);
|
||||||
InputStream in = socket.getInputStream();
|
InputStream in = socket.getInputStream();
|
||||||
|
@ -77,40 +75,54 @@ public class XmppConnection implements Runnable {
|
||||||
while ((nextTag = tagReader.readTag()) != null) {
|
while ((nextTag = tagReader.readTag()) != null) {
|
||||||
if (nextTag.isStart("stream")) {
|
if (nextTag.isStart("stream")) {
|
||||||
processStream(nextTag);
|
processStream(nextTag);
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName());
|
Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (socket.isConnected()) {
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
Log.d(LOGTAG,account.getJid()+": error during connect. unknown host");
|
account.setStatus(Account.STATUS_SERVER_NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.d(LOGTAG, account.getJid()+": error during connect. io exception. falscher port?");
|
if (shouldConnect) {
|
||||||
return;
|
Log.d(LOGTAG,account.getJid()+": connection lost");
|
||||||
|
account.setStatus(Account.STATUS_OFFLINE);
|
||||||
|
if (statusListener!=null) {
|
||||||
|
statusListener.onStatusChanged(account);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (XmlPullParserException e) {
|
} catch (XmlPullParserException e) {
|
||||||
Log.d(LOGTAG,"xml exception "+e.getMessage());
|
Log.d(LOGTAG,"xml exception "+e.getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while(shouldReConnect) {
|
shouldConnect = true;
|
||||||
|
while(shouldConnect) {
|
||||||
connect();
|
connect();
|
||||||
try {
|
try {
|
||||||
Thread.sleep(30000);
|
if (shouldConnect) {
|
||||||
|
Thread.sleep(30000);
|
||||||
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log.d(LOGTAG,"end run");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processStream(Tag currentTag) throws XmlPullParserException,
|
private void processStream(Tag currentTag) throws XmlPullParserException,
|
||||||
IOException {
|
IOException {
|
||||||
Tag nextTag;
|
Tag nextTag = tagReader.readTag();
|
||||||
while (!(nextTag = tagReader.readTag()).isEnd("stream")) {
|
while ((nextTag != null) && (!nextTag.isEnd("stream"))) {
|
||||||
if (nextTag.isStart("error")) {
|
if (nextTag.isStart("error")) {
|
||||||
processStreamError(nextTag);
|
processStreamError(nextTag);
|
||||||
} else if (nextTag.isStart("features")) {
|
} else if (nextTag.isStart("features")) {
|
||||||
|
@ -124,6 +136,12 @@ public class XmppConnection implements Runnable {
|
||||||
tagReader.reset();
|
tagReader.reset();
|
||||||
sendStartStream();
|
sendStartStream();
|
||||||
processStream(tagReader.readTag());
|
processStream(tagReader.readTag());
|
||||||
|
break;
|
||||||
|
} else if(nextTag.isStart("failure")) {
|
||||||
|
Element failure = tagReader.readElement(nextTag);
|
||||||
|
Log.d(LOGTAG,"read failure element"+failure.toString());
|
||||||
|
account.setStatus(Account.STATUS_UNAUTHORIZED);
|
||||||
|
tagWriter.writeTag(Tag.end("stream"));
|
||||||
} else if (nextTag.isStart("iq")) {
|
} else if (nextTag.isStart("iq")) {
|
||||||
processIq(nextTag);
|
processIq(nextTag);
|
||||||
} else if (nextTag.isStart("message")) {
|
} else if (nextTag.isStart("message")) {
|
||||||
|
@ -134,6 +152,13 @@ public class XmppConnection implements Runnable {
|
||||||
Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName()
|
Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName()
|
||||||
+ " as child of " + currentTag.getName());
|
+ " as child of " + currentTag.getName());
|
||||||
}
|
}
|
||||||
|
nextTag = tagReader.readTag();
|
||||||
|
}
|
||||||
|
if (account.getStatus() == Account.STATUS_ONLINE) {
|
||||||
|
account.setStatus(Account.STATUS_OFFLINE);
|
||||||
|
if (statusListener!=null) {
|
||||||
|
statusListener.onStatusChanged(account);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,11 +215,11 @@ public class XmppConnection implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendStartTLS() throws XmlPullParserException, IOException {
|
private void sendStartTLS() {
|
||||||
Tag startTLS = Tag.empty("starttls");
|
Tag startTLS = Tag.empty("starttls");
|
||||||
startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls");
|
startTLS.setAttribute("xmlns", "urn:ietf:params:xml:ns:xmpp-tls");
|
||||||
Log.d(LOGTAG,account.getJid()+": sending starttls");
|
Log.d(LOGTAG,account.getJid()+": sending starttls");
|
||||||
tagWriter.writeTag(startTLS).flush();
|
tagWriter.writeTag(startTLS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void switchOverToTls(Tag currentTag) throws XmlPullParserException,
|
private void switchOverToTls(Tag currentTag) throws XmlPullParserException,
|
||||||
|
@ -213,6 +238,7 @@ public class XmppConnection implements Runnable {
|
||||||
isTlsEncrypted = true;
|
isTlsEncrypted = true;
|
||||||
sendStartStream();
|
sendStartStream();
|
||||||
processStream(tagReader.readTag());
|
processStream(tagReader.readTag());
|
||||||
|
sslSocket.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.d(LOGTAG, account.getJid()+": error on ssl '" + e.getMessage()+"'");
|
Log.d(LOGTAG, account.getJid()+": error on ssl '" + e.getMessage()+"'");
|
||||||
}
|
}
|
||||||
|
@ -227,7 +253,6 @@ public class XmppConnection implements Runnable {
|
||||||
auth.setContent(saslString);
|
auth.setContent(saslString);
|
||||||
Log.d(LOGTAG,account.getJid()+": sending sasl "+auth.toString());
|
Log.d(LOGTAG,account.getJid()+": sending sasl "+auth.toString());
|
||||||
tagWriter.writeElement(auth);
|
tagWriter.writeElement(auth);
|
||||||
tagWriter.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processStreamFeatures(Tag currentTag)
|
private void processStreamFeatures(Tag currentTag)
|
||||||
|
@ -249,12 +274,10 @@ public class XmppConnection implements Runnable {
|
||||||
startSession.addChild(session);
|
startSession.addChild(session);
|
||||||
sendIqPacket(startSession, null);
|
sendIqPacket(startSession, null);
|
||||||
tagWriter.writeElement(startSession);
|
tagWriter.writeElement(startSession);
|
||||||
tagWriter.flush();
|
|
||||||
}
|
}
|
||||||
Element presence = new Element("presence");
|
Element presence = new Element("presence");
|
||||||
|
|
||||||
tagWriter.writeElement(presence);
|
tagWriter.writeElement(presence);
|
||||||
tagWriter.flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,8 +289,12 @@ public class XmppConnection implements Runnable {
|
||||||
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
this.sendIqPacket(iq, new OnIqPacketReceived() {
|
||||||
@Override
|
@Override
|
||||||
public void onIqPacketReceived(Account account, IqPacket packet) {
|
public void onIqPacketReceived(Account account, IqPacket packet) {
|
||||||
resource = packet.findChild("bind").findChild("jid").getContent().split("/")[1];
|
String resource = packet.findChild("bind").findChild("jid").getContent().split("/")[1];
|
||||||
Log.d(LOGTAG,account.getJid()+": new resource is "+resource);
|
account.setResource(resource);
|
||||||
|
account.setStatus(Account.STATUS_ONLINE);
|
||||||
|
if (statusListener!=null) {
|
||||||
|
statusListener.onStatusChanged(account);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -276,7 +303,7 @@ public class XmppConnection implements Runnable {
|
||||||
Log.d(LOGTAG, "processStreamError");
|
Log.d(LOGTAG, "processStreamError");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendStartStream() throws IOException {
|
private void sendStartStream() {
|
||||||
Tag stream = Tag.start("stream");
|
Tag stream = Tag.start("stream");
|
||||||
stream.setAttribute("from", account.getJid());
|
stream.setAttribute("from", account.getJid());
|
||||||
stream.setAttribute("to", account.getServer());
|
stream.setAttribute("to", account.getServer());
|
||||||
|
@ -284,32 +311,29 @@ public class XmppConnection implements Runnable {
|
||||||
stream.setAttribute("xml:lang", "en");
|
stream.setAttribute("xml:lang", "en");
|
||||||
stream.setAttribute("xmlns", "jabber:client");
|
stream.setAttribute("xmlns", "jabber:client");
|
||||||
stream.setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
|
stream.setAttribute("xmlns:stream", "http://etherx.jabber.org/streams");
|
||||||
tagWriter.writeTag(stream).flush();
|
tagWriter.writeTag(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String nextRandomId() {
|
private String nextRandomId() {
|
||||||
return new BigInteger(50, random).toString(32);
|
return new BigInteger(50, random).toString(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) throws IOException {
|
public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) {
|
||||||
String id = nextRandomId();
|
String id = nextRandomId();
|
||||||
packet.setAttribute("id",id);
|
packet.setAttribute("id",id);
|
||||||
tagWriter.writeElement(packet);
|
tagWriter.writeElement(packet);
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
iqPacketCallbacks.put(id, callback);
|
iqPacketCallbacks.put(id, callback);
|
||||||
}
|
}
|
||||||
tagWriter.flush();
|
|
||||||
Log.d(LOGTAG,account.getJid()+": sending: "+packet.toString());
|
Log.d(LOGTAG,account.getJid()+": sending: "+packet.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessagePacket(MessagePacket packet) throws IOException {
|
public void sendMessagePacket(MessagePacket packet){
|
||||||
tagWriter.writeElement(packet);
|
tagWriter.writeElement(packet);
|
||||||
tagWriter.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPresencePacket(PresencePacket packet) throws IOException {
|
public void sendPresencePacket(PresencePacket packet) {
|
||||||
tagWriter.writeElement(packet);
|
tagWriter.writeElement(packet);
|
||||||
tagWriter.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOnMessagePacketReceivedListener(OnMessagePacketReceived listener) {
|
public void setOnMessagePacketReceivedListener(OnMessagePacketReceived listener) {
|
||||||
|
@ -323,4 +347,13 @@ public class XmppConnection implements Runnable {
|
||||||
public void setOnPresencePacketReceivedListener(OnPresencePacketReceived listener) {
|
public void setOnPresencePacketReceivedListener(OnPresencePacketReceived listener) {
|
||||||
this.presenceListener = listener;
|
this.presenceListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOnStatusChangedListener(OnStatusChanged listener) {
|
||||||
|
this.statusListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect() {
|
||||||
|
shouldConnect = false;
|
||||||
|
tagWriter.writeTag(Tag.end("stream"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue