RocketChatService.java 3.28 KB
Newer Older
1 2 3 4 5
package chat.rocket.android.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
6 7
import android.content.ServiceConnection;
import android.os.Binder;
8 9
import android.os.IBinder;
import android.support.annotation.Nullable;
Yusuke Iwaki's avatar
Yusuke Iwaki committed
10 11

import java.util.HashMap;
12
import java.util.concurrent.TimeUnit;
Yusuke Iwaki's avatar
Yusuke Iwaki committed
13 14
import hugo.weaving.DebugLog;
import rx.Observable;
15
import rx.Single;
16

17 18 19
/**
 * Background service for Rocket.Chat.Application class.
 */
20
public class RocketChatService extends Service implements ConnectivityServiceInterface {
21

22
  private ConnectivityManagerInternal connectivityManager;
Yusuke Iwaki's avatar
Yusuke Iwaki committed
23
  private HashMap<String, RocketChatWebSocketThread> webSocketThreads;
24 25 26 27 28 29 30 31

  public class LocalBinder extends Binder {
    ConnectivityServiceInterface getServiceInterface() {
      return RocketChatService.this;
    }
  }

  private final LocalBinder localBinder = new LocalBinder();
32

33 34 35
  /**
   * ensure RocketChatService alive.
   */
Yusuke Iwaki's avatar
Yusuke Iwaki committed
36
  /*package*/ static void keepAlive(Context context) {
37 38
    context.startService(new Intent(context, RocketChatService.class));
  }
39

40 41 42 43 44 45 46 47 48
  public static void bind(Context context, ServiceConnection serviceConnection) {
    context.bindService(
        new Intent(context, RocketChatService.class), serviceConnection, Context.BIND_AUTO_CREATE);
  }

  public static void unbind(Context context, ServiceConnection serviceConnection) {
    context.unbindService(serviceConnection);
  }

Yusuke Iwaki's avatar
Yusuke Iwaki committed
49 50
  @Override
  public void onCreate() {
51
    super.onCreate();
52

53 54 55
    connectivityManager = ConnectivityManager.getInstanceForInternal(getApplicationContext());
    connectivityManager.resetConnectivityStateList();
    webSocketThreads = new HashMap<>();
56
  }
57

Yusuke Iwaki's avatar
Yusuke Iwaki committed
58 59
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
60
    connectivityManager.ensureConnections();
61
    return START_NOT_STICKY;
62
  }
63

64
  @Override
Yusuke Iwaki's avatar
Yusuke Iwaki committed
65
  public Single<Boolean> ensureConnectionToServer(String hostname) { //called via binder.
66 67 68 69 70
    return getOrCreateWebSocketThread(hostname)
        .doOnError(err -> {
          webSocketThreads.remove(hostname);
          connectivityManager.notifyConnectionLost(hostname, ConnectivityManagerInternal.REASON_NETWORK_ERROR);
        })
Yusuke Iwaki's avatar
Yusuke Iwaki committed
71
        .flatMap(webSocketThreads -> webSocketThreads.keepAlive());
Yusuke Iwaki's avatar
Yusuke Iwaki committed
72
  }
73

74
  @Override
Yusuke Iwaki's avatar
Yusuke Iwaki committed
75
  public Single<Boolean> disconnectFromServer(String hostname) { //called via binder.
76
    return Single.defer(() -> {
Yusuke Iwaki's avatar
Yusuke Iwaki committed
77 78 79
      if (!webSocketThreads.containsKey(hostname)) {
        return Single.just(true);
      }
80

81 82
      RocketChatWebSocketThread thread = webSocketThreads.get(hostname);
      if (thread != null) {
Yusuke Iwaki's avatar
Yusuke Iwaki committed
83
        return thread.terminate();
84
      } else {
Yusuke Iwaki's avatar
Yusuke Iwaki committed
85 86
        return Observable.timer(1, TimeUnit.SECONDS).toSingle()
            .flatMap(_val -> disconnectFromServer(hostname));
87
      }
Yusuke Iwaki's avatar
Yusuke Iwaki committed
88 89 90 91 92
    });
  }

  @DebugLog
  private Single<RocketChatWebSocketThread> getOrCreateWebSocketThread(String hostname) {
93
    return Single.defer(() -> {
Yusuke Iwaki's avatar
Yusuke Iwaki committed
94 95
      if (webSocketThreads.containsKey(hostname)) {
        RocketChatWebSocketThread thread = webSocketThreads.get(hostname);
96
        return Single.just(thread);
Yusuke Iwaki's avatar
Yusuke Iwaki committed
97 98
      }
      return RocketChatWebSocketThread.getStarted(getApplicationContext(), hostname)
Yusuke Iwaki's avatar
Yusuke Iwaki committed
99
          .doOnSuccess(thread -> webSocketThreads.put(hostname, thread));
Yusuke Iwaki's avatar
Yusuke Iwaki committed
100
    });
101 102
  }

Yusuke Iwaki's avatar
Yusuke Iwaki committed
103 104 105
  @Nullable
  @Override
  public IBinder onBind(Intent intent) {
106
    return localBinder;
107
  }
108
}