238 lines
8.4 KiB
Java
238 lines
8.4 KiB
Java
package org.mercury_im.messenger.service;
|
|
|
|
import android.app.Notification;
|
|
import android.app.PendingIntent;
|
|
import android.app.Service;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Handler;
|
|
import android.os.IBinder;
|
|
import android.util.Log;
|
|
import android.util.LongSparseArray;
|
|
|
|
import androidx.annotation.NonNull;
|
|
import androidx.core.app.NotificationCompat;
|
|
|
|
import org.jivesoftware.smack.SmackException;
|
|
import org.jivesoftware.smack.XMPPConnection;
|
|
import org.jivesoftware.smack.XMPPException;
|
|
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
|
import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager;
|
|
import org.jxmpp.stringprep.XmppStringprepException;
|
|
import org.mercury_im.messenger.MercuryImApplication;
|
|
import org.mercury_im.messenger.Notifications;
|
|
import org.mercury_im.messenger.R;
|
|
import org.mercury_im.messenger.handler.RoomPlainMessageHandler;
|
|
import org.mercury_im.messenger.handler.RoomRosterHandler;
|
|
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.repository.EntityRepository;
|
|
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
|
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
|
|
import org.mercury_im.messenger.ui.MainActivity;
|
|
import org.mercury_im.messenger.xmpp_android.AndroidMercuryConnection;
|
|
import org.mercury_im.messenger.xmpp_core.ConnectionHolder;
|
|
import org.mercury_im.messenger.xmpp_core.MercuryConnection;
|
|
|
|
import java.io.IOException;
|
|
import java.util.List;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
/**
|
|
* Started, Bound Service, which is responsible for managing {@link XMPPConnection XMPPConnections}
|
|
* affiliated with registered accounts.
|
|
*/
|
|
public class XmppConnectionService extends Service implements ConnectionHolder {
|
|
|
|
private static final String TAG = MercuryImApplication.TAG;
|
|
|
|
private static final String APP = "org.mercury-im.messenger";
|
|
private static final String SERVICE = APP + ".XmppConnectionService";
|
|
|
|
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";
|
|
|
|
// ACTIONS
|
|
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";
|
|
|
|
// EVENTS
|
|
public static final String EVENT_INCOMING_MESSAGE = EVENT + ".INCOMING_MESSAGE";
|
|
public static final String EVENT_OUTGOING_MESSAGE = EVENT + ".OUTGOING_MESSAGE";
|
|
|
|
// EXTRAS
|
|
public static final String EXTRA_CONFIGURATION = EXTRA + ".CONFIGURATION";
|
|
public static final String EXTRA_ACCOUNT_ID = EXTRA + ".ACCOUNT_ID";
|
|
|
|
// STATUSES
|
|
public static final String STATUS_SUCCESS = STATUS + ".SUCCESS";
|
|
public static final String STATUS_FAILURE = STATUS + ".FAILURE";
|
|
|
|
@Inject
|
|
ContactRepository contactRepository;
|
|
|
|
@Inject
|
|
AccountRepository accountRepository;
|
|
|
|
@Inject
|
|
EntityRepository entityRepository;
|
|
|
|
@Inject
|
|
EntityDao entityDao;
|
|
|
|
@Inject
|
|
ContactDao contactDao;
|
|
|
|
private final LongSparseArray<MercuryConnection> connections = new LongSparseArray<>();
|
|
|
|
private Handler uiHandler;
|
|
|
|
@NonNull
|
|
@Override
|
|
public final IBinder onBind(Intent intent) {
|
|
return new Binder(this);
|
|
}
|
|
|
|
@Override
|
|
public void onCreate() {
|
|
super.onCreate();
|
|
Log.d(TAG, "onCreate()");
|
|
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
|
|
|
new Thread() {
|
|
@Override
|
|
public void run() {
|
|
List<AccountModel> accounts = accountRepository.getAllAccounts();
|
|
|
|
for(AccountModel accountModel : accounts) {
|
|
startConnection(accountModel);
|
|
}
|
|
}
|
|
}.start();
|
|
|
|
|
|
// 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();
|
|
}
|
|
|
|
@Override
|
|
public MercuryConnection getConnection(long accountId) {
|
|
return connections.get(accountId);
|
|
}
|
|
|
|
@Override
|
|
public void putConnection(long accountId, MercuryConnection connection) {
|
|
connections.put(accountId, connection);
|
|
}
|
|
|
|
@Override
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
Log.d(TAG, "onStartCommand(" + intent + ")");
|
|
if (intent == null) {
|
|
startAndDisplayForegroundNotification();
|
|
} else {
|
|
String action = intent.getAction();
|
|
action = action == null ? "" : action;
|
|
|
|
switch (action) {
|
|
case ACTION_START:
|
|
startAndDisplayForegroundNotification();
|
|
break;
|
|
case ACTION_STOP:
|
|
stopForeground(true);
|
|
stopSelf();
|
|
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 startConnection(AccountModel accountModel) {
|
|
MercuryConnection connection = connections.get(accountModel.getId());
|
|
|
|
if (connection != null) {
|
|
return;
|
|
}
|
|
|
|
new Thread() {
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
XMPPTCPConnection connection = new XMPPTCPConnection(accountModel.getJid().getLocalpart().asUnescapedString(),
|
|
accountModel.getPassword(), accountModel.getJid().getDomain().toString());
|
|
MercuryConnection mercuryConnection = new AndroidMercuryConnection(connection, accountModel.getId());
|
|
putConnection(accountModel.getId(), mercuryConnection);
|
|
mercuryConnection.setRosterHandler(new RoomRosterHandler(mercuryConnection));
|
|
mercuryConnection.setPlainMessageHandler(new RoomPlainMessageHandler(accountModel.getId()));
|
|
|
|
connection.connect().login();
|
|
Log.d(MercuryImApplication.TAG, "Logged in for " + accountModel.getJid().toString());
|
|
} catch (XmppStringprepException e) {
|
|
e.printStackTrace();
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
} catch (SmackException e) {
|
|
e.printStackTrace();
|
|
} catch (XMPPException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}.start();
|
|
}
|
|
|
|
public class Binder extends android.os.Binder {
|
|
|
|
private final XmppConnectionService service;
|
|
|
|
public Binder(XmppConnectionService service) {
|
|
this.service = service;
|
|
}
|
|
|
|
public XmppConnectionService getService() {
|
|
return service;
|
|
}
|
|
}
|
|
}
|