본문 바로가기

Mobile/Android(JAVA)

[Android] Android 통신 방법

앱에서 가장 많이 수행하는 처리 중 하나는 서버에 데이터를 요청하고 받아온 데이터를 클라이언트의 화면에 표시하는 것이다.
이때 클라이언트와 서버가 통신하는 방식은 크게 소켓통신과 HTTP통신 두 가지로 나눌 수 있다.


1. 소켓통신

소켓 : 네트워크 상의 두 프로그램 사이에서 일어나는 양방향 통신 중 한쪽의 엔드 포인트(ip+port)를 의미

: 소켓 통신에서는 클라이언트와 서버가 특정 포트를 통해 연결을 계속 유지하고 있기 때문에 실시간으로 양방향 통신이 가능하다.
: 동영상 스트리밍, 온라인 게임등에서 사용되는 연결방식


2. HTTP 통신

HTTP : 80번 포트를 사용해 웹 상에서 정보를 주고받을 수 있는 프로토콜

: 클라이언트가 서버에 헤더와 바디로 이루어진 메시지를 요청하면 서버는 이 요청을 처리하고 응답코드와 함께 응답을 반환하는 형식

  2-1. Android의 HTTP 통신 라이브러리

  • HttpClient

: Http 통신을 용이하게 수행하기 위해 Apache에서 제작한 라이브러리
: 안드로이드 초기에 주로 사용되었으며 실제로는 이를 래핑한 DefaultHttpClient, AndroidHttpClient가 사용되었다.
: 안드로이드와 독립적으로 개발되는 라이브러리로 변경사항을 안드로이드 SDK에 즉시 반영할 수 없었고 결국 버전이 뒤쳐지면서 버그가 계속 발생하게 되어 결국 Android 5.1에서 Deprecated 되며 6.0에서 아예 삭제되었다.
 

  • HttpUrlConnection

: HttpClient를 삭제하면서 Google에서 제시한 대안으로 기존의 URLConnection에 HTTP를 다루는데 필요한 메서드를 추가한 클래스
 

URL.openConnection()으로 얻어진 URLConnection 객체를 HttpURLConnection으로 캐스팅하여 데이터를 송수신하고 disconnect로 접속을 종료하는 방식 [2][3]
public class MainActivity extends AppCompatActivity {

    private Button btn;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);
        btn = (Button) findViewById(R.id.button);

        btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                String url = "http://www.android.com";

                //AsyncTask를 통해 HttpURLConnection 수행
                ConnTask connTask = new ConnTask(url, null);
                connTask.execute();
            }
        });
    }

    public class ConnTask extends AsyncTask<Void, Void, String> {
        private String url;
        private ContentValues values;

        public ConnTask(String url, ContentValues values){
            this.url = url;
            this.values = values;
        }

        @Override
        protected String doInBackground(Void... voids) {
             HttpURLConnection conn = null;
            try {
                URL url = new URL("http://www.android.com");
                conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            String buffer = null;
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String line = null;
                StringBuffer response = new StringBuffer();
                while(true){
                    line = reader.readLine();
                    if(line == null) break;
                    response.append(line);
                }
                reader.close();
                buffer = response.toString();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                conn.disconnect();
            }
            if (TextUtils.isEmpty(buffer)) return null;
            return buffer;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            textView.setText(s);
        }
    }
}

 

  • OkHttp

: Square에서 발표한 HTTP 클라이언트 라이브러리
: Okio와 코틀린을 활용해서 쓰인다.
: Connection pooling과 Redirection을 도입해 접속을 더 안정적이게 하면서도 속도를 개선시킬 수 있는 여러 기술이 적용되었다.
 

클라이언트 인스턴스를 생성하고 리퀘스트 객체를 만들어 클라이언트에 전해주면 response가 반환되는 구조
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();
  }
}

 

  • Retrofit

: OkHttp를 개발한 Square에서 새로 발표한 라이브러리로 OkHttp를 랩핑한 OkHttp 라이브러리의 상위 구현체
: AsyncTask 없이 Background Thread로 실행하여 Callback을 통해 Main Thread에서 UI 업데이트
: 어노테이션을 사용하여 코드를 생성한다.
 

REST API콜을 인터페이스 형식으로 준비 후 Retrofit 객체를 만들어 인터페이스의 인스턴스를 생성 -> 인터페이스를 동기 혹은 비동기적으로 구동시켜  response를 반환받는 구조
//build.gradle 추가

// retrofit2
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
// Gson 변환기 (api 리턴값이 json일 경우 파싱하기 쉽도록 추가)
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//RetrofitClient.java
//Interface를 사용할 인스턴스, baseUrl, Converter 설정

public class RetrofitClient {
    private static final String BASE_URL = "https://jsonplaceholder.typicode.com/";


    public static RetrofitInterface getApiService(){return getInstance().create(RetrofitInterface.class);}

    private static Retrofit getInstance(){
        Gson gson = new GsonBuilder().setLenient().create();
        return new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }
}
//RetrofitInterface.java
//사용할 HTTP 메서드들(GET, POST, PUT, DELETE)을 정의해놓은 인터페이스

public interface RetrofitInterface {
    @GET("posts/{UserID}")
    Call<RetrofitDataModel> test_api_get(
            @Path("UserID") String userid);
}
//RetrofitDataModel.java
//모델, JSON 타입변환에 사용

package com.example.myapplication;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class RetrofitDataModel {
    @SerializedName("userId")
    @Expose
    private String userId;

    @SerializedName("id")
    @Expose
    private String id;

    @SerializedName("title")
    @Expose
    private String title;

    @SerializedName("body")
    @Expose
    private String body;


    public String getUserId(){
        return userId;
    }

    public String getID(){
        return id;
    }

    public String getTitle(){
        return title;
    }

    public String getBody(){
        return body;
    }
}
//MainActivitiy.java
//버튼 클릭 시 url 반환값을 textView에 넣어주는 예제

public class MainActivity extends AppCompatActivity {

    private Button btn;
    private TextView textView;

    public Call<RetrofitDataModel> call;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);
        btn = (Button) findViewById(R.id.button);

        btn.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {

                //Retrofit 에제
                call = RetrofitClient.getApiService().test_api_get("5");
                call.enqueue(new Callback<RetrofitDataModel>(){
                    //콜백 받는 부분
                    @Override
                    public void onResponse(Call<RetrofitDataModel> call, Response<RetrofitDataModel> response) {
                        RetrofitDataModel result = response.body();
                        String str;
                        str= result.getUserId() +"\n"+
                                result.getID()+"\n"+
                                result.getTitle()+"\n"+
                                result.getBody();
                        textView.setText(str);
                    }

                    @Override
                    public void onFailure(Call<RetrofitDataModel> call, Throwable t) {

                    }
                });
            }
        });
    }

 
 
 

[1] 안드로이드의 HTTP 통신 라이브러리 고찰 : https://cliearl.github.io/posts/android/android-http-library-review/

[2] [안드로이드] Android 통신 라이브러리의 역사 : https://velog.io/@dabin/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-Android-%ED%86%B5%EC%8B%A0-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC%EC%9D%98-%EC%97%AD%EC%82%AC
[3] http post get - 안드로이드 HttpURLConnection으로 웹서버 통신하기 설명잘됨 : http://webs.co.kr/index.php?document_srl=3314894 
[4] 안드로이드 retrofit2 사용법 / 예제, 레트로핏2, Java : https://taewooblog.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-retrofit-2-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%98%88%EC%A0%9C-%EB%A0%88%ED%8A%B8%EB%A1%9C%ED%95%8F-2-Java

안드로이드 retrofit 2 사용법 / 예제  , 레트로핏 2, Java

안드로이드 retrofit2 사용법 먼저 이 포스팅에 오신분들은 레트로핏이 뭔지 대충 알고 오신분들이라 생각하여 간단한 소개만 하고 간단한 예제 코드만 작성해보겠습니다. 아래의 링크에 가시면

taewooblog.tistory.com