Android 에서 WebSocket 을 사용 하여 메시지 통신 을 실현 하 는 방법 에 대한 상세 한 설명
14098 단어 AndroidWebSocket커 뮤 니 케 이 션
메시지 푸 시 기능 은 모 바 일 앱 에 없어 서 는 안 될 기능 중 하나 라 고 할 수 있다.일반적으로 간단 한 푸 시 는 제3자 가 푸 시 하 는 SDK,예 를 들 어 극광 푸 시,전서구 푸 시 등 을 사용 할 수 있 지만 메시지 채 팅 과 같은 신속 성에 대한 요구 가 있 거나 제3자 푸 시 는 업무 수 요 를 만족 시 키 지 못 할 경우 우 리 는 WebSocket 을 사용 하여 메시지 푸 시 기능 을 실현 해 야 한다.
기본 절차
웹 소켓 이 무엇 인지 소개 하지 않 겠 습 니 다.여기 서 사용 하 는 오픈 소스 프레임 워 크 는https://github.com/TakahikoKawasaki/nv-websocket-client입 니 다.
오픈 소스 프로 토 콜 을 바탕 으로 저 희 는 WebSocket 의 연결,등록,심장 박동,메시지 배포,시간 초과 작업 기능 을 밀봉 하고 기본 적 인 절 차 는 다음 과 같 습 니 다.
연결 기능
우선 build.grade 에 설정 을 추가 하 는 항목 을 새로 만 듭 니 다.
compile 'com.neovisionaries:nv-websocket-client:2.2'
새 웹 소켓 관리 클래스 WsManger
public class WsManager {
private volatile static WsManager wsManger;
private WsManager() {
}
public static WsManager getWsManger() {
if (wsManger == null) {
synchronized (WsManager.class) {
if (wsManger == null) {
wsManger = new WsManager();
}
}
}
return wsManger;
}
}
다음 연결 방법 을 추가 합 니 다.웹 소켓 의 상 태 를 세 가지 로 나 누 어 새 Ws Statue 매 거 진 클래스 에 대응 합 니 다.
public enum WsStatus {
/**
*
*/
CONNECT_SUCCESS,
/**
*
*/
CONNECT_FAIL,
/**
*
*/
CONNECTING;
}
연결 방법 은 다음 과 같다.
/**
*
*/
public void connect() {
//WEB_SOCKET_API url ,
// CONNECT_TIMEOUT 5
try {
ws = new WebSocketFactory().createSocket(WEB_SOCKET_API, CONNECT_TIMEOUT)
// 5
.setFrameQueueSize(5)
//
.setMissingCloseFrameAllowed(false)
//
.addListener(new WsListener())
//
.connectAsynchronously();
} catch (IOException e) {
e.printStackTrace();
}
setStatus(WsStatus.CONNECTING);
}
연결 방법 을 호출 한 후에 연결 의 리 셋 을 보 겠 습 니 다.바로 WsListener 입 니 다.
/**
* websocket
*/
private class WsListener extends WebSocketAdapter {
@Override
public void onConnected(WebSocket websocket, Map<String, List<String>> headers) throws Exception {
Log.d(TAG, "onConnected: ");
}
@Override
public void onConnectError(WebSocket websocket, WebSocketException exception) throws Exception {
Log.d(TAG, "onConnectError: ");
}
@Override
public void onDisconnected(WebSocket websocket, WebSocketFrame serverCloseFrame,
WebSocketFrame clientCloseFrame,
boolean closedByServer) throws Exception {
Log.d(TAG, "onDisconnected: ");
}
@Override
public void onTextMessage(WebSocket websocket, String text) throws Exception {
Log.d(TAG, "onTextMessage: :" + text);
}
}
다음은 연결 방법 을 호출 하 겠 습 니 다.
WsManager.getWsManger().connect();
프로젝트 를 실행 하면 다음 과 같은 인쇄 를 볼 수 있 습 니 다.여기 서 우리 가 해 야 할 일 은 연결 이 실패 하거나 연결 이 끊 긴 리 셋 을 받 으 면 다시 연결 해 야 한 다 는 것 입 니 다.우 리 는 연결 방법 을 다시 호출 하면 됩 니 다.또한 세 번 의 리 셋 이 실패 하면 우 리 는 업무 중 에 인 터 페 이 스 를 호출 하여 데 이 터 를 얻 을 수 있 고 데이터 가 손실 되 지 않도록 할 수 있 습 니 다.이 디 테 일 은 생략 합 니 다.
프로 토 콜 패키지
이 프로 토 콜 은 다음 과 같 습 니 다.
{
"action":"",
"requestChild":{
"clientType":"",
"id":""
}
}
심장 박동,전송 요청 은 모두 클 라 이언 트 가 주동 적 으로 요청 을 보 내 는 것 에 속 합 니 다.요청 결과 에 대해 우 리 는 성공 과 실패,시간 초과 로 나 눌 수 있 습 니 다.전송 시간 초과 에 대해 우 리 는 서버 의 어떠한 답장 도 받 을 수 없 기 때문에 보 낸 후에 시간 초과 작업 대기 열 에 보 내야 합 니 다.요청 이 성공 하면 작업 을 시간 초과 대기 열 에서 제거 해 야 합 니 다.시간 초과 대기 열 에서 작업 을 가 져 와 다시 요청 합 니 다.시간 초과 작업 대기 열 에 성공,실패,시간 초과 가 있 습 니 다.
우 리 는 상기 협의 에 따라 대응 하 는 실체 류 를 추가 하고 Builder 디자인 모델 을 사용한다.
public class Request {
/**
*
*/
private String action;
/**
*
*/
private RequestChild req;
/**
*
*/
private transient int reqCount;
/**
*
*/
private transient int timeOut;
public Request() {
}
public Request(String action, int reqCount, int timeOut, RequestChild req) {
this.action = action;
this.req = req;
this.reqCount = reqCount;
this.timeOut = timeOut;
}
public static class Builder {
//action
private String action;
//
private RequestChild req;
//
private int reqCount;
//
private int timeOut;
public Builder action(String action) {
this.action = action;
return this;
}
public Builder req(RequestChild req) {
this.req = req;
return this;
}
public Builder reqCount(int reqCount) {
this.reqCount = reqCount;
return this;
}
public Builder timeOut(int timeOut) {
this.timeOut = timeOut;
return this;
}
public Request build() {
return new Request(action, reqCount, timeOut, req);
}
}
}
public class RequestChild {
/**
*
*/
private String clientType;
/**
* id
*/
private String id;
public RequestChild(String clientType, String id) {
this.clientType = clientType;
this.id = id;
}
public RequestChild() {
}
public static class Builder {
private String clientType;
private String id;
public RequestChild.Builder setClientType(String clientType) {
this.clientType = clientType;
return this;
}
public RequestChild.Builder setId(String id) {
this.id = id;
return this;
}
public RequestChild build() {
return new RequestChild(clientType, id);
}
}
}
요청 을 보 내 는 방법 은 다음 과 같 습 니 다.
/**
*
*
* @param request
* @param reqCount
* @param requestListern
*/
private void senRequest(Request request, final int reqCount, final RequestListern requestListern) {
if (!isNetConnect()) {
requestListern.requestFailed(" ");
return;
}
}
다음 과 같이 반전 을 요청 합 니 다.
public interface RequestListern {
/**
*
*/
void requestSuccess();
/**
*
*
* @param message
*/
void requestFailed(String message);
}
이어서 우 리 는 요청 을 시간 초과 대기 열 에 놓 아야 한다.새 시간 초과 작업 클래스 는 요청 파라미터,요청 리 셋,작업 스케줄 링 에 대응한다.
public class TimeOutTask {
/**
*
*/
private Request request;
/**
*
*/
private RequestCallBack requestCallBack;
/**
* r
*/
private ScheduledFuture scheduledFuture;
public TimeOutTask(Request request,
RequestCallBack requestCallBack,
ScheduledFuture scheduledFuture) {
this.request = request;
this.requestCallBack = requestCallBack;
this.scheduledFuture = scheduledFuture;
}
public ScheduledFuture getScheduledFuture() {
return scheduledFuture;
}
public void setScheduledFuture(ScheduledFuture scheduledFuture) {
this.scheduledFuture = scheduledFuture;
}
public Request getRequest() {
return request;
}
public void setRequest(Request request) {
this.request = request;
}
public RequestCallBack getRequestCallBack() {
return requestCallBack;
}
public void setRequestCallBack(RequestCallBack requestCallBack) {
this.requestCallBack = requestCallBack;
}
}
RequestCallBack 은 시간 초과 작업 의 리 셋 입 니 다.리 셋 을 요청 하 는 것 보다 시간 초과 가 많 을 뿐 입 니 다.시간 초과 처리 메커니즘 이 같 기 때문에 시간 초과 리 셋 을 요청 할 필요 가 없습니다.
public interface RequestCallBack {
/**
*
*/
void requestSuccess();
/**
*
*
* @param request
* @param message
*/
void requestFailed(String message, Request request);
/**
*
*
* @param request
*/
void timeOut(Request request);
}
/**
*
*/
private ScheduledFuture enqueueTimeout(final Request request, final long timeout) {
Log.d(TAG, " " + "enqueueTimeout: :" + request.getAction());
return executor.schedule(new Runnable() {
@Override
public void run() {
TimeOutTask timeoutTask = callbacks.remove(request.getAction());
if (timeoutTask != null) {
timeoutTask.getRequestCallBack().timeOut(timeoutTask.getRequest());
}
}
}, timeout, TimeUnit.MILLISECONDS);
}
시간 초과 작업 의 방법 은 작업 스케줄 을 통 해 정시 에 호출 하 는 것 입 니 다.요청 이 성공 한 후에 우 리 는 시간 초과 작업 을 제거 할 것 입 니 다.시간 초과 시간 이 되면 작업 이 존재 한 다 는 것 은 작업 시간 초과 임 무 를 설명 합 니 다.매번 작업 은 action 을 키 로 hashMap 에 존재 합 니 다.
private Map<String, CallbackWrapper> callbacks = new HashMap<>();
시간 초과 작업 코드 에 작업 을 넣 으 면 다음 과 같 습 니 다.
final ScheduledFuture timeoutTask = enqueueTimeout(request, request.getTimeOut());
final RequestCallBack requestCallBack = new RequestCallBack() {
@Override
public void requestSuccess() {
requestListern.requestSuccess();
}
@Override
public void requestFailed(String message, Request request) {
requestListern.requestFailed(message);
}
@Override
public void timeOut(Request request) {
timeOutHanlder(request);
}
};
callbacks.put(request.getAction(),
new CallbackWrapper(request, requestCallBack, timeoutTask));
일반적으로 작업 시간 초과 가 연결 원인 으로 인해 발생 하기 때문에 다시 시도 해 볼 수 있 습 니 다.시간 초과 일 경우 timeOutHanlder(request)를 통 해 다시 시도 할 수 있 습 니 다.방법 은 다시 연결 하고 코드 를 다시 연결 하 는 것 은 연결 코드 와 마찬가지 로 여 기 는 생략 합 니 다.이 작업 을 잘 하면 우 리 는 메 시 지 를 보 낼 수 있 습 니 다.
/**
*
*/
private void timeOutHanlder(Request requset) {
setStatus(WsStatus.CONNECT_FAIL);
//
Log.d(TAG, "timeOutHanlder: ");
}
여기까지 우리 의 절 차 는 기본적으로 통할 수 있다.가슴 이 두근거리다
우선 우 리 는 심장 박동 의 작용 이 무엇 인지 알 아야 한다.심장 박동 은 연결 에 성공 한 후에 고정된 간격 을 통 해 서버 에 문의 하 는 것 이다.현재 아직 온라인 상태 인지,많은 사람들 이 심장 박동 이 실패 하면 우 리 는 다시 연결 되 고 성공 하면 심장 박동 을 계속 하 는 것 이 라 고 말한다.그러나 여기 서 주의해 야 할 것 은 우 리 는 일반적으로 심장 박동 실패 의 반전 을 받 지 못 하고 심장 박동 도 서버 에 데 이 터 를 보 내 는 것 이다.그래서 우 리 는 모든 주동 적 인 요청 을 시간 초과 작업 대기 열 에 두 어야 합 니 다.
따라서 웹 소켓 에 대한 요청 결 과 는 세 가지 가 있 습 니 다.성공,실패,시간 초과,사용자 에 게 성공,실패 만 있 으 면 됩 니 다.
심장 박동,등록 등 요청 한 데이터 가 무엇 인지 에 대해 서 는 서버 와 의 협의 가 어떻게 되 는 지 에 달 려 있 습 니 다.일반적으로 action 과 requestBody 로 나 뉘 는데 협의 형식 은 두 번 째 단계 로 봉 인 했 습 니 다.여기 서 우 리 는 심장 박동 임 무 를 예 로 들 어 위의 포장 을 검증 합 니 다.
/**
*
*/
void keepAlive() {
Request request = new Request.Builder()
.reqCount(0)
.timeOut(REQUEST_TIMEOUT)
.action(ACTION_KEEPALIVE).build();
WsManager.getWsManger().senRequest(request, request.getReqCount() + 1, new RequestListern() {
@Override
public void requestSuccess() {
Log.d(TAG, "requestSuccess: ");
}
@Override
public void requestFailed(String message) {
}
});
}
저 희 는 10s 간격 으로 심장 박동 미 션 을 한 번 씩 시작 합 니 다.
/**
*
*/
public void startKeepAlive() {
mHandler.postDelayed(mKeepAliveTask, HEART_BEAT_RATE);
}
/**
*
*/
private Runnable mKeepAliveTask = new Runnable() {
@Override
public void run() {
keepAlive();
mHandler.removeCallbacks(mKeepAliveTask);
mHandler.postDelayed(mKeepAliveTask, HEART_BEAT_RATE);
}
};
프 리 젠 테 이 션 을 편리 하 게 하기 위해 홈 페이지 에 단 추 를 추가 하고 단 추 를 누 르 면 startKeepAlive 방법 을 호출 합 니 다.다음 과 같이 실행 합 니 다. 심장 박동 이 돌아 오 는 statue 는 300 이 성공 하지 못 한 것 을 볼 수 있 습 니 다.5 초 후에 요청 시간 초과 방법 에 도 착 했 습 니 다.따라서 상태 가 성공 하면 호출 자 에 게 되 돌려 주어 야 합 니 다.
/**
*
*
* @param action
*/
void disPatchCallbackWarp(String action, boolean isSuccess) {
CallbackWrapper callBackWarp = callbacks.remove(action);
if (callBackWarp == null) {
Logger.d(TAG+" "+ "disPatchCallbackWarp: ");
} else {
callBackWarp.getScheduledFuture().cancel(true);
if (isSuccess) {
callBackWarp.getRequestCallBack().requestSuccess();
} else {
callBackWarp.getRequestCallBack().requestFailed("", new Request());
}
}
}
이렇게 호출 해 야 성공 이나 실 패 를 알 수 있다.다른 메 시 지 를 보 내 는 것 은 심장 박동 과 마찬가지 로 요청 인자 만 다 를 뿐 Request 인 자 를 수정 하면 됩 니 다.이렇게 해서 우 리 는 협의 와 업무 에 따라 비교적 규범 화 된 웹 소켓 메시지 전송 절 차 를 실현 했다.
안 드 로 이 드 에서 웹 소켓 을 사용 하여 메시지 통신 을 실현 하 는 방법 에 대한 상세 한 설명 은 여기까지 입 니 다.더 많은 안 드 로 이 드 가 웹 소켓 을 사용 하여 메시지 통신 을 실현 하 는 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많이 응원 해 주세요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.