Mercury-IM/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionService.java

314 lines
11 KiB
Java
Raw Normal View History

2019-05-27 21:34:11 +02:00
package org.mercury_im.messenger.service;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
2019-06-06 23:32:41 +02:00
import android.os.Binder;
2019-05-27 21:34:11 +02:00
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.util.LongSparseArray;
import android.widget.Toast;
2019-06-10 02:52:08 +02:00
import androidx.annotation.NonNull;
2019-05-27 21:34:11 +02:00
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.chat2.Chat;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.smack.roster.RosterLoadedListener;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
2019-06-10 02:52:08 +02:00
import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager;
2019-05-27 21:34:11 +02:00
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.Notifications;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.persistence.model.AccountModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.persistence.repository.ContactRepository;
import org.mercury_im.messenger.persistence.room.AppDatabase;
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
import org.mercury_im.messenger.persistence.room.model.RoomContactModel;
import org.mercury_im.messenger.ui.MainActivity;
import org.mercury_im.messenger.xmpp_android.ParcelableXMPPTCPConnectionConfiguration;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
/**
2019-06-06 23:32:41 +02:00
* Started, Bound Service, which is responsible for managing {@link XMPPConnection XMPPConnections}
2019-05-27 21:34:11 +02:00
* affiliated with registered accounts.
*/
2019-06-06 23:32:41 +02:00
public class XmppConnectionService extends Service {
2019-05-27 21:34:11 +02:00
private static final String TAG = MercuryImApplication.TAG;
private static final String APP = "org.olomono.mercury";
2019-06-06 23:32:41 +02:00
private static final String SERVICE = APP + ".XmppConnectionService";
2019-05-27 21:34:11 +02:00
private static final String ACTION = SERVICE + ".ACTION";
private static final String EVENT = SERVICE + ".EVENT";
private static final String EXTRA = SERVICE + ".EXTRA";
private static final String STATUS = SERVICE + ".STATUS";
2019-06-06 23:32:41 +02:00
// ACTIONS
2019-05-27 21:34:11 +02:00
public static final String ACTION_START = ACTION + ".START";
public static final String ACTION_STOP = ACTION + ".STOP";
public static final String ACTION_CONNECT = ACTION + ".CONNECT";
public static final String ACTION_DISCONNECT = ACTION + ".DISCONNECT";
public static final String ACTION_PING = ACTION + ".PING";
2019-06-06 23:32:41 +02:00
// EVENTS
2019-05-27 21:34:11 +02:00
public static final String EVENT_INCOMING_MESSAGE = EVENT + ".INCOMING_MESSAGE";
public static final String EVENT_OUTGOING_MESSAGE = EVENT + ".OUTGOING_MESSAGE";
2019-06-06 23:32:41 +02:00
// EXTRAS
2019-05-27 21:34:11 +02:00
public static final String EXTRA_CONFIGURATION = EXTRA + ".CONFIGURATION";
public static final String EXTRA_ACCOUNT_ID = EXTRA + ".ACCOUNT_ID";
2019-06-06 23:32:41 +02:00
// STATUSES
2019-05-27 21:34:11 +02:00
public static final String STATUS_SUCCESS = STATUS + ".SUCCESS";
public static final String STATUS_FAILURE = STATUS + ".FAILURE";
@Inject
ContactRepository rosterRepository;
@Inject
AccountRepository accountRepository;
private final LongSparseArray<XMPPConnection> connections = new LongSparseArray<>();
private Handler uiHandler;
2019-06-10 02:52:08 +02:00
@NonNull
2019-05-27 21:34:11 +02:00
@Override
public final IBinder onBind(Intent intent) {
2019-06-10 02:52:08 +02:00
return new Binder(this);
2019-05-27 21:34:11 +02:00
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate()");
MercuryImApplication.getApplication().getAppComponent().inject(this);
2019-06-10 02:52:08 +02:00
// Begin life cycle of Ping Manager.
// The Manager will automatically detect newly created connections and ping the server
// every half hour if necessary.
ServerPingWithAlarmManager.onCreate(this);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy()");
// End life cycle of Ping Manager.
ServerPingWithAlarmManager.onDestroy();
2019-05-27 21:34:11 +02:00
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (uiHandler == null) {
uiHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
Message m = (Message) msg.obj;
2019-06-06 23:32:41 +02:00
Toast.makeText(XmppConnectionService.this, (m.getFrom() != null ? m.getFrom().toString() : "null") + ": "
2019-05-27 21:34:11 +02:00
+ m.getBody(), Toast.LENGTH_LONG).show();
}
}
};
}
Log.d(TAG, "onStartCommand(" + intent + ")");
if (intent == null) {
startAndDisplayForegroundNotification();
} else {
String action = intent.getAction();
action = action == null ? "" : action;
switch (action) {
case ACTION_START:
startAndDisplayForegroundNotification();
startConnections();
break;
case ACTION_STOP:
stopForeground(true);
break;
case ACTION_CONNECT:
ParcelableXMPPTCPConnectionConfiguration configuration = intent.getParcelableExtra(EXTRA_CONFIGURATION);
if (configuration == null) {
Log.e(TAG, "Configuration is null.");
return START_STICKY_COMPATIBILITY;
}
long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1);
if (accountId == -1) {
Log.d(TAG, "No AccountID provided.");
return START_STICKY_COMPATIBILITY;
}
new Thread() {
public void run() {
XMPPConnection connection = startConnection(configuration, accountId);
connections.put(accountId, connection);
}
}.start();
break;
default:
break;
}
}
return START_STICKY_COMPATIBILITY;
}
public void startAndDisplayForegroundNotification() {
Log.d(TAG, "startAndDisplayForegroundNotification()");
Notification notification = getForegroundNotification(getApplicationContext(), connections.size());
startForeground(Notifications.FOREGROUND_SERVICE_ID, notification);
}
static Notification getForegroundNotification(Context context, int numConnections) {
Intent startMainActivityIntent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
startMainActivityIntent, 0);
return new NotificationCompat.Builder(context, Notifications.NOTIFICATION_CHANNEL__FOREGROUND_SERVICE)
.setContentTitle("Mercury")
.setContentText(numConnections + " connections.")
.setSmallIcon(R.drawable.ic_send_black_24dp)
.setContentIntent(pendingIntent)
.build();
}
public void startConnections() {
new Thread() {
@Override
public void run() {
synchronized (connections) {
List<RoomAccountModel> accounts = accountRepository.getAllAccounts();
if (accounts == null) return;
for (AccountModel a : accounts) {
if (connections.get(a.getId()) != null) {
continue;
}
// XMPPConnection connection = startConnection(a.getJid(), a.getPassword(), a.getId());
// connections.put(a.getId(), connection);
}
}
}
}.start();
}
private XMPPConnection startConnection(ParcelableXMPPTCPConnectionConfiguration connectionConfiguration, long accountId) {
XMPPTCPConnection con = null;
try {
XMPPTCPConnectionConfiguration conf = connectionConfiguration.getConfiguration();
con = new XMPPTCPConnection(conf);
con.connect().login();
} catch (
XMPPException e) {
e.printStackTrace();
} catch (
SmackException e) {
e.printStackTrace();
} catch (
IOException e) {
e.printStackTrace();
} catch (
InterruptedException e) {
e.printStackTrace();
}
NotificationManagerCompat.from(getApplicationContext()).notify(Notifications.FOREGROUND_SERVICE_ID,
getForegroundNotification(getApplicationContext(), connections.size()));
Roster roster = Roster.getInstanceFor(con);
roster.addRosterLoadedListener(new RosterLoadedListener() {
@Override
public void onRosterLoaded(Roster roster) {
Set<RosterEntry> entries = roster.getEntries();
for (RosterEntry e : entries) {
Log.d(TAG, "Inserting Roster entry " + e.getJid().toString());
2019-06-10 02:52:08 +02:00
RoomContactModel contact = new RoomContactModel();
contact.setAccountId(accountId);
// TODO: Fix
2019-05-27 21:34:11 +02:00
}
}
@Override
public void onRosterLoadingFailed(Exception exception) {
Log.d(TAG, "Roster Loading failed", exception);
}
});
try {
roster.reload();
} catch (SmackException.NotLoggedInException e) {
e.printStackTrace();
} catch (SmackException.NotConnectedException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
ChatManager chatManager = ChatManager.getInstanceFor(con);
chatManager.addIncomingListener(new IncomingChatMessageListener() {
@Override
public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
android.os.Message msg = uiHandler.obtainMessage(1, message);
msg.sendToTarget();
}
});
return con;
}
public XMPPConnection getConnection(long accountId) {
return connections.get(accountId);
}
public void putConnection(int accountId, XMPPConnection connection) {
connections.put(accountId, connection);
}
2019-06-10 02:52:08 +02:00
public class Binder extends android.os.Binder {
private final XmppConnectionService service;
public Binder(XmppConnectionService service) {
this.service = service;
}
public XmppConnectionService getService() {
return service;
}
}
2019-05-27 21:34:11 +02:00
}