안드로이드 node js 통신 - andeuloideu node js tongsin

package org.androidtown.socketio;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

import android.widget.Toast;

import org.json.JSONObject;

import java.net.URL;

import io.socket.client.IO;

import io.socket.client.Socket;

import io.socket.emitter.Emitter;

public class MainActivity extends AppCompatActivity {

EditText et_msg, et_host, et_port;

TextView tv_msg;

Button btn_connect, btn_send;

Socket socket;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

init();

}

private void init() {

et_msg = findViewById(R.id.editText_msg);

et_host = findViewById(R.id.editText_host);

et_port = findViewById(R.id.editText_port);

tv_msg = findViewById(R.id.TextView_msgFromServer);

btn_connect = findViewById(R.id.btn_connect);

btn_send = findViewById(R.id.btn_send);

btn_connect.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

if(socket != null)

return;

try {

String host = et_host.getText().toString();

int port = Integer.parseInt(et_port.getText().toString());

URL url = new URL("http", host, port, "/");

socket = IO.socket(url.toURI());

socket.connect();

socket.on("SEND"new Emitter.Listener() {

@Override

public void call(final Object... args) {

runOnUiThread(new Runnable() {

@Override

public void run() {

try {

JSONObject data = (JSONObject) args[0];

tv_msg.setText(data.getString("message"));

catch(Exception e) {

Toast.makeText(getApplicationContext(), e.getMessage(),

Toast.LENGTH_LONG).show();

e.printStackTrace();

}

}

});

}

});

catch(Exception e) {

Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG)

.show();

e.printStackTrace();

}

}

});

btn_send.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

if(socket != null) {

JSONObject data = new JSONObject();

try {

data.put("message", et_msg.getText().toString());

socket.emit("SEND", data);

catch(Exception e) {

Toast.makeText(getApplicationContext(), e.getMessage(), Toast

.LENGTH_LONG).show();

e.printStackTrace();

}

}

}

});

}

@Override

protected void onDestroy() {

super.onDestroy();

socket.emit("disconnect"null);

socket.disconnect();

}

}

- 간단한 버튼들로 Retrofit을 이용해 node.js 서버와 각각 ( post / get / put / delete )의 통신 방법으로 데이터를 주고받는 기능을 구현해보자 

  • 프로젝트 생성

Create New Project

Empty Activity / Next

Name : Example_Retrofit / Finish

  • 버튼 만들기

- activity_main.xml

: Layout은 본인 편한대로! 저는 ConstraintLayout 공부중이라 이걸로... ( 쓰다보면 편할거같음 => 좋음 )

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="//schemas.android.com/apk/res/android" xmlns:app="//schemas.android.com/apk/res-auto" xmlns:tools="//schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/btn_get" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="GET" app:layout_constraintBottom_toTopOf="@+id/btn_post" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed" /> <Button android:id="@+id/btn_post" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="POST" app:layout_constraintBottom_toTopOf="@id/btn_update" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_get" /> <Button android:id="@+id/btn_update" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="UPDATE" app:layout_constraintBottom_toTopOf="@id/btn_delete" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_post" /> <Button android:id="@+id/btn_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="DELETE" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/btn_update" /> </androidx.constraintlayout.widget.ConstraintLayout>
  • gradle에 retrofit 추가

- build.gradle ( Module: Example_Retrofit.app ) 

: dependencies 블럭 안에 추가하고 우측 상단에 Sync Now 클릭!

implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
  • AndroidManifest 에 권한 추가

- AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />

: <manifest ... > 태그 다음에 넣기

android:usesCleartextTraffic="true"

: <application 태그 안에 넣기 

  • 통신하면서 동작할 인터페이스 생성

- ApiService.java

package com.example.example_retrofit; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.http.DELETE; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.PUT; import retrofit2.http.Path; import retrofit2.http.Query; public interface ApiService { @GET("/retrofit/get") Call<ResponseBody> getFunc(@Query("data") String data); @FormUrlEncoded @POST("/retrofit/post") Call<ResponseBody> postFunc(@Field("data") String data); @FormUrlEncoded @PUT("/retrofit/put/{id}") Call<ResponseBody> putFunc(@Path("id") String id, @Field("data") String data); @DELETE("/retrofit/delete/{id}") Call<ResponseBody> deleteFunc(@Path("id") String id); }

: GET - Query 형태로 보냄 

: POST - Field 형태로 보내기 때문에 @FormUrlEncoded 어노테이션 붙여줘야함

: PUT - 마찬가지로 Field 형태가 있어서 어노테이션 추가, 경로를 통해 id를 보냄

: DELETE - 경로를 통해 id를 보냄

=> 통신방법에 따라 보내는 형태가 다름 주의!

  • MainActivity 작성

- MainActivity.java

 : onCreate() 메소드 안에 소스코드가 길면 개인적으로 가독성이 좋지 않은것 같아서 메소드를 따로 만들어서 작성하는 편이다. 그리고 버튼이 비슷한 동작을 할 때에는 아래 코드처럼 클릭리스너를 implements해서 작성한다. 상황에 따라 본인이 알맞게 쓰시길... 코드스타일 굳히기가 너무 어렵다 ㅠ

package com.example.example_retrofit; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import java.io.IOException; import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private final String TAG = "MainActivityLog"; private final String URL = "//192.168.0.174:3000"; private Retrofit retrofit; private ApiService service; private Button btn_get, btn_post, btn_delete, btn_update; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); firstInit(); btn_get.setOnClickListener(this); btn_post.setOnClickListener(this); btn_delete.setOnClickListener(this); btn_update.setOnClickListener(this); } /** * Init */ public void firstInit() { btn_get = (Button) findViewById(R.id.btn_get); btn_post = (Button) findViewById(R.id.btn_post); btn_delete = (Button) findViewById(R.id.btn_delete); btn_update = (Button) findViewById(R.id.btn_update); retrofit = new Retrofit.Builder() .baseUrl(URL) .addConverterFactory(GsonConverterFactory.create()) .build(); service = retrofit.create(ApiService.class); } /** * View.OnLongClickListener override method */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_get: Call<ResponseBody> call_get = service.getFunc("get data"); call_get.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { try { String result = response.body().string(); Log.v(TAG, "result = " + result); Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } else { Log.v(TAG, "error = " + String.valueOf(response.code())); Toast.makeText(getApplicationContext(), "error = " + String.valueOf(response.code()), Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.v(TAG, "Fail"); Toast.makeText(getApplicationContext(), "Response Fail", Toast.LENGTH_SHORT).show(); } }); break; case R.id.btn_post: Call<ResponseBody> call_post = service.postFunc("post data"); call_post.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { try { String result = response.body().string(); Log.v(TAG, "result = " + result); Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } else { Log.v(TAG, "error = " + String.valueOf(response.code())); Toast.makeText(getApplicationContext(), "error = " + String.valueOf(response.code()), Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.v(TAG, "Fail"); Toast.makeText(getApplicationContext(), "Response Fail", Toast.LENGTH_SHORT).show(); } }); break; case R.id.btn_update: Call<ResponseBody> call_put = service.putFunc("board", "put data"); call_put.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { try { String result = response.body().string(); Log.v(TAG, "result = " + result); Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } else { Log.v(TAG, "error = " + String.valueOf(response.code())); Toast.makeText(getApplicationContext(), "error = " + String.valueOf(response.code()), Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.v(TAG, "Fail"); Toast.makeText(getApplicationContext(), "Response Fail", Toast.LENGTH_SHORT).show(); } }); break; case R.id.btn_delete: Call<ResponseBody> call_delete = service.deleteFunc("board"); call_delete.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { if (response.isSuccessful()) { try { String result = response.body().string(); Log.v(TAG, "result = " + result); Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); } } else { Log.v(TAG, "error = " + String.valueOf(response.code())); Toast.makeText(getApplicationContext(), "error = " + String.valueOf(response.code()), Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { Log.v(TAG, "Fail"); Toast.makeText(getApplicationContext(), "Response Fail", Toast.LENGTH_SHORT).show(); } }); break; default: break; } } }

여기까지 앱에서 동작하는 부분은 완료! 다음 포스팅에서 각각의 버튼에 따라 동작하는 node.js 서버를 만들어보자.

Toplist

최신 우편물

태그