참고 url
라이브러리: https://github.com/Aevi-UK/android-rxmessenger
예제: https://github.com/susemi99/RxMessenger-sample
클라이언트
- 사용할 명령어를 선언한다.
서버에서도 이걸 사용해야 한다.private static final String IMMEDIATE = "IMMEDIATE"; private static final String DELAY = "DELAY"; private static final String CONTINUOUS = "CONTINUOUS"; private static final String FORCE_INTERRUPT = "FORCE_INTERRUPT";
- 전송에 사용할 클라이언트 클래스를 만든다.
clients 배열에 넣는 건,onDestroy
될 때 연결이 끊기지 않은 것들의 연결을 끊기 위함이다.private ArrayList<ObservableMessengerClient> clients = new ArrayList<>(); private ObservableMessengerClient client() { ObservableMessengerClient client = new ObservableMessengerClient(getApplicationContext(), SERVICE); clients.add(client); return client; }
- 즉시 응답이 오는 요청 보내기
응답을 받으면 연결을 끊어준다.
요청을 받기 전에dispose()
를 먼저 시켜주는 건 아직 오지 않은 응답을 취소시키고 새로운 요청을 보내기 위함이다. 안하면 먼저간 요청이 오지 않은 상태에서 새로운 요청이 또 가기 때문에, 2개의 요청이 오게된다.private void requestImmediate() { immediateResponse.setText(null); try { immediateDisposable.dispose(); } catch (Exception ignore) {} ObservableMessengerClient client = client(); immediateDisposable = client.sendMessage(IMMEDIATE) .subscribe(response -> { Log.i("APP# MainActivity | requestImmediate", "response: " + response); immediateResponse.setText(response); }, throwable -> { throwable.printStackTrace(); immediateResponse.setText(throwable.getMessage()); }, () -> { client.closeConnection(); clients.remove(client); }); }
- 30초 후에 응답이 오는 요청 보내기
기본적으로 즉시 응답 받는 것과 큰 차이 없다.private void requestDelay() { delayResponse.setText("request: " + DateFormatter.format(System.currentTimeMillis())); try { delayDisposable.dispose(); } catch (Exception ignore) {} ObservableMessengerClient client = client(); delayDisposable = client.sendMessage(DELAY) .subscribe(response -> { Log.i("APP# MainActivity | requestDelay", "response: " + response); delayResponse.append("\n" + response); }, throwable -> { throwable.printStackTrace(); delayResponse.setText(throwable.getMessage()); }, () -> { client.closeConnection(); clients.remove(client); }); }
- 3초 마다 계속 응답이 오는 요청 보내기
연결을 끊으면 안된다.private void requestContinuous() { continuousResponse.setText(null); try { continuousDisposable.dispose(); } catch (Exception ignore) {} continuousDisposable = client().sendMessage(CONTINUOUS) .subscribe( response -> continuousResponse.setText(response), throwable -> { throwable.printStackTrace(); continuousResponse.setText(throwable.getMessage()); }); }
- 테스트를 위해 강제로 오류를 내는 신호도 보내본다.
private void requestForceInterrupt() { client().sendMessage(FORCE_INTERRUPT).subscribe(); }
서버
onCreate()
, onDestroy()
에 로그를 찍어보니, 모든 요청에 응답을 하면 서비스가 종료된다. 즉시응답을 보내고 나면 종료되고, 3초 마다 응답을 보내는 중이라면 죽지 않았다. 강제로 오류를 발생시켜도, 그 이후의 요청에도 응답을 잘 해줬다. 혹시나 싶어서 Singleton 클래스도 넣어봤는데, 강제로 종료 시켰어도 값이 유지됐다.
- `AbstractMessengerService`를 상속받은 서비스 클래스를 생성한다.
<service android:name=".MyService" android:enabled="true" android:exported="true"/>
public class MyService extends AbstractMessengerService { . . . }
- 입력받을 명령어를 설정한다.
private static final String IMMEDIATE = "IMMEDIATE"; private static final String DELAY = "DELAY"; private static final String CONTINUOUS = "CONTINUOUS"; private static final String FORCE_INTERRUPT = "FORCE_INTERRUPT";
- 요청을 받는다.
@Override protected void handleRequest(String clientId, String requestData, String packageName) { Log.i("APP# MyService | handleRequest", "clientId: " + clientId + ", request data: " + requestData + ", packageName: " + packageName); if (IMMEDIATE.equals(requestData)) { handleImmediate(clientId); } else if (DELAY.equals(requestData)) { handleDelay(clientId); } else if (CONTINUOUS.equals(requestData)) { handleContinuous(clientId); } else if (FORCE_INTERRUPT.equals(requestData)) { handleForceInterrupt(); } else { sendErrorMessageToClient(clientId, "404", "not found"); sendEndStreamMessageToClient(clientId); } }
- 기본적인 사용법은 아래와 같다.
sendMessageToClient(clientId, "response"); // 응답을 보낸다. sendEndStreamMessageToClient(clientId); // 연결을 닫는다.
- 즉각적인 응답을 보내준다.
private void handleImmediate(String clientId) { try { sendMessageToClient(clientId, DateFormatter.format(System.currentTimeMillis()) + "(" + MySingleton.getInstance().getCount() + ")"); } catch (Exception e) { sendErrorMessageToClient(clientId, "001", e.getMessage()); sendEndStreamMessageToClient(clientId); } sendEndStreamMessageToClient(clientId); }
- 30초 뒤에 응답을 보낸다.
테스트로 30분 뒤에 응답 보내게 해봤는데, 잘 왔다.private void handleDelay(String clientId) { ArrayList<String> response = new ArrayList<>(); response.add("received: " + DateFormatter.format(System.currentTimeMillis())); delayDisposable = Completable.timer(30, TimeUnit.SECONDS) .subscribeOn(Schedulers.computation()) .subscribe(() -> { response.add("response: " + DateFormatter.format(System.currentTimeMillis())); sendMessageToClient(clientId, TextUtils.join("\n", response)); sendEndStreamMessageToClient(clientId); }, throwable -> { throwable.printStackTrace(); sendErrorMessageToClient(clientId, "002", throwable.getMessage()); sendEndStreamMessageToClient(clientId); }); }
- 3초 마다 응답 보내기
private void handleContinuous(String clientId) { continuousDisposable = Observable.interval(3, TimeUnit.SECONDS) .subscribeOn(Schedulers.computation()) .subscribe(__ -> sendMessageToClient(clientId, "time tick: " + DateFormatter.format(System.currentTimeMillis())), throwable -> { sendErrorMessageToClient(clientId, "003", throwable.getMessage()); sendEndStreamMessageToClient(clientId); }); }