안드로이드 앱 개발 공부/안드로이드 기본(노션 이동)

[Android] Rest Api

플래시🦥 2023. 3. 7.
반응형

안드로이드에서 HTTP통신을 서버와 통신을 할 때 AsyncTaksk(비동기)로 통신을 해야 한다. 왜냐하면 안드로이드의 메인 스레드는 전부 UI관련 처리를 위해 사용되기 때문이다.

  • Rest 아키텍처의 제약 조건을 준수하는 애플리케이션 프로그래밍 인터페이스
  • 서버와 클라이언트 구조
  • Socket 통신과는 다르게 양방향이 아닌 단방향 통신
  • Request와 Response로 이루어짐
  • Get, Post, Put, Delete등의 메서드를 사용
  • 아래 클래스나 라이브러리를 사용해 통신을 구현
  • OkHttp
  •  Retrofit
  • HttpURLConnection/HttpsURLConnection

HttpURLConnection/HttpsURLConnection

  • Post와 Get 두가지 방식
  • Post : Post에서 URI를 통해 요청하면 리소스를 생성한다.
  • Get : URL을 통해 접속해 리소스 값을 조회하는 행위이다.

참고 : https://android-uni.tistory.com/9

POST

public class onHTTPConnection {
 
    String EXCEPTION_ERROR = "Exception Occured. Check the url";
 
         public String POSTFunction(String mUrl, String params) {
 
            try {
                //받아온 String을 url로 만들어주기
                URL url = new URL(mUrl);
 
                //conn으로 url connection을 open 해주기
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 
                //불러오는데 시간이 오래 걸리는 경우 Time out 설정
                conn.setReadTimeout(10000);
                //연결하는데 시간이 오래 걸리는 경우 Time out 설정
                conn.setConnectTimeout(15000);
                //연결 방법 설정
                conn.setRequestMethod("POST");
                conn.setDoInput(true);
                conn.setDoOutput(true);
 
                //Accept-Charset 설정 UTF-8 or ASCII
                conn.setRequestProperty("Accept-Charset", "UTF-8");
                conn.setRequestProperty("Context_Type", "application/x-www-form-urlencoded;charset=UTF-8");
 
                // POST로 넘겨줄 파라미터 생성.
                byte[] outputInBytes = params.getBytes(StandardCharsets.UTF_8);
                OutputStream os = conn.getOutputStream();
                os.write(outputInBytes);
                os.close();
 
                //결과값을 받아온다.
                InputStream is = conn.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(is));
                String line;
                StringBuffer response = new StringBuffer();
                while ((line = br.readLine()) != null) {
                    response.append(line);
                    response.append('\\r');
                }
                br.close();
 
                String res = response.toString();
                res = res.trim();
 
                return res;
 
            } catch (Exception e) {
                e.printStackTrace();
            }
 
            Log.d("ERROR", EXCEPTION_ERROR);
            return null;
        }
    }
}

GET

public class onHTTPConnection {
 
    String EXCEPTION_ERROR = "Exception Occured. Check the url";
 
        public String GETFunction(String mUrl) {
            try {
                URL url = new URL(mUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(15000);
                conn.setReadTimeout(10000);
                conn.setDoInput(true);
                conn.setDoOutput(true);
 
                InputStream is = conn.getInputStream();
                StringBuilder sb = new StringBuilder();
                BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                String result;
                while ((result = br.readLine()) != null) {
                    sb.append(result + '\\n');
                }
 
                result = sb.toString();
 
                return result;
 
            } catch (Exception e) {
                e.printStackTrace();
            }
 
            Log.d("ERROR", EXCEPTION_ERROR);
            return null;
        }
    }
}

OkHttp

  • RestAPi, HTTP통신을 간편하게 구현할 수 있도록 다양한 기능을 제공해 주는 Square에서 제공하는 Java 오픈소스 라이브러리이다.
  • OkHttp 라이브러리는 Retrofit 이라는 라이브러리의 베이스가 된다.
  • 이 라이브러리를 이용하면 간편하게 몇 줄로 Rest호출을 전송, Http 기반의 요청 및 응답을 처리할 수 있다.

참고 : https://jade314.tistory.com/entry/Android-Library-OKHttp-http

  1. gradle에 dependencies 설정
  2. // define a BOM and its version implementation(platform("com.squareup.okhttp3:okhttp-bom:4.9.1")) // define any required OkHttp artifacts without version implementation("com.squareup.okhttp3:okhttp") implementation("com.squareup.okhttp3:logging-interceptor")
  3. URL을 다운로드하고 그 내용을 문자열로 출력
  4. OkHttpClient client = new OkHttpClient(); String run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } }
  5. json을 서버로 전송
public static final MediaType JSON
    = MediaType.get("application/json; charset=utf-8");

OkHttpClient client = new OkHttpClient();

String post(String url, String json) throws IOException {
  RequestBody body = RequestBody.create(JSON, json);
  Request request = new Request.Builder()
      .url(url)
      .post(body)
      .build();
  try (Response response = client.newCall(request).execute()) {
    return response.body().string();
  }
}

*Get/Head/Delete 예제

public boolean getUserInfo(String key) {
 
	try {
		String url = "<http://127.0.0.1:8080/v1/test/get?key=>" + key;
 
		OkHttpClient client = new OkHttpClient();
 
		// GET 요청을 Request.Builder 를 통해 만듦 (get 요청임을 명시)
		Request.Builder builder = new Request.Builder().url(url).get();
		builder.addHeader("password", "BlahBlah");
        
		Request request = builder.build();
 
		// client 객체의 newCall() 메소드에 만들어진 Request를 전달하고, execute() 메소드를 실행
		Response response = client.newCall(request).execute();
		// execute() 메소드는 요청에 대한 응답이 올때까지 기다렸다가 반환
		if (response.isSuccessful()) {
			ResponseBody body = response.body();
			if (body != null) {
				System.out.println("Response:" + body.string());
			}
		}else{
            System.err.println("Error Occurred");
		}
		return true;
	} catch(Exception e) {
		e.printStackTrace();
        return false;
	}
}

GET요청

GET   http://127.0.0.1:8080/v1/test/get?key=123  HTTP/1.1

Request.Builder builder =new Request.Builder().url(url).get();

HEAD요청

HEAD   http://127.0.0.1:8080/v1/test/get?key=123  HTTP/1.1

Request.Builder builder =new Request.Builder().url(url).head();

DELETE 요청

DELETE   http://127.0.0.1:8080/v1/test/get?key=123  HTTP/1.1

Request.Builder builder =new Request.Builder().url(url).delete();

 

Retrofit

  • 안드로이드 애플리케이션 통신기능에 사용하는 코드를 사용하기 쉽게 만들어 놓은 라이브러리
  • Rest 기반의 웹 서비스를 통해 JSON 구조의 데이터를 쉽게 가져오고 업로드할 수 있다.
  • 앱-서버 통신을 okhttp 라이브러리로 AsyncTask를 사용하여 구현했다고 할 수 있지만, AsyncTask로 서버와 통신을 구현하는 것은 어렵고 시간이 많이 든다.(비동기 처리 코드를 개발자가 하나하나 작성) 그리고 AsyncTask가 안드로이드에서 deprecated되었다. 이것 대신 Retrofit을 사용하는 것이 가독성이 좋고 훨씬 간편하고 쉽고 빠르다.

세 가지의 클래스 필요

  1. JSON 형태의 모델 클래스 (kotlin 에서는 data class 를 사용)
  2. HTTP 작업을 정의하는(onSuccess/onFail) 인터페이스
  3. Retrofit.Builder를 선언한 클래스 (baseUrl과 Converter등을 선언한다. Interceptor를 추가하여 응답을 가공할수도 있다.)
  4. Retrofit 라이브러리를 Gradle에 추가
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
  1. Manifest 파일에 인터넷 permission을 추가
<uses-permission android:name="android.permission.INTERNET"/>
  1. JSON 형테의 모델 클래스를 작성
data class ResponseDTO ( var result: String )
  1. RetrofitService interface 를 작성
interface RetrofitService{

    //post1
    // 매개변수를 미리 정해두는 방식
    @POST("/test")
    fun postRequest(
        @Field("id") id: String,
        @Field("pw") pw: String
    ): Call<ResponseDTO>

    //post2
    // 호출하는 곳에서 매개변수를 HashMap 형태로 보내는 방식
    @POST("/{path}")
    fun testRequest(
    	@Path("path")path: String, 
        @Body parameters: HashMap<String, Any>
    ): Call<ResponseDTO>
}
  1. Retrofit.Builder 로 Retrofit 객체를 초기화
val retrofit = Retrofit.Builder()
        .baseUrl("<https://server-url.com/>")
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        
val server: RetrofitService = retrofit.create(RetrofitService::class.java)
  1. Retrofit 객체에 enqueue() 를 사용하여 서버와 통신했을때 콜백을 작성하여 사용
//post1
// 매개변수를 미리 정해두는 방식
server.postRequest("userid","asd1234").enqueue(object : Callback<ResponseDTO>{
    override fun onFailure(call: Call<ResponseDTO>?, t: Throwable?) {
        Log.e("retrofit", t.toString())
    }

    override fun onResponse(call: Call<ResponseDTO>?, response: Response<ResponseDTO>?) {
        Log.d("retrofit", response?.body().toString())
    }
})
//post2
// 호출하는 곳에서 매개변수를 HashMap 형태로 보내는 방식

var params:HashMap<String, Any> = HashMap<String, Any>()
params.put("id", "hello")
params.put("pw", 123123)

server.testRequest("test", params).enqueue(object : Callback<ResponseDTO>{
    override fun onFailure(call: Call<ResponseDTO>?, t: Throwable?) {
        Log.e("Retrofit", t.toString())
    }

    override fun onResponse(call: Call<ResponseDTO>?, response: Response<ResponseDTO>?) {
        var res: ResponseDTO? = response?.body()
        Log.d("Retrofit", res?.result)
    }
})

참고 : https://salix97.tistory.com/204

728x90
반응형

댓글