오늘은 HttpURLConnection 에 대해 포스팅 해보겠다.
포스팅 하게 된 이유는 저번에 잘 사용하던 httpClient(아파치 라이브러리)가 deprecated 되었기 때문이다.
갑자기 사라져서 당황했었다... 아래 내용은 Google Developer 에서 발췌한 android 6.0 변화에서 httpClient에 대한 이야기다.
Apache HTTP Client Removal
Android 6.0 release removes support for the Apache HTTP client. If your app is using this client and targets Android 2.3 (API level 9) or higher, use the HttpURLConnection
class instead. This API is more efficient because it reduces network use through transparent compression and response caching, and minimizes power consumption. To continue using the Apache HTTP APIs, you must first declare the following compile-time dependency in your build.gradle
file:
android {
useLibrary 'org.apache.http.legacy'
}
요약하자면, 위와 같이 gradle에 해당 라이브러리를 추가하면 httpClient 쓸수는 있다. 또 말하기를, httpClient의 기능은 많지만 무겁다,
그리고 안드로이드에서는 조금 오바(?)스러운 httpClient보다는,
안드로이드에 적합한 API인 HttpURLConnection을 사용하라는 이야기다.(해당 이슈는 예전부터 나오던 이슈긴 하다.)
뭐.. httpClient가 편리하지만 저렇게 권장하지 않는 API를 쓰기에는 유지보수와 기능에 문제가 있다고 판단, 바로 HttpURLConnection으로 옮겼었다.
서론은 여기까지 하고, 시작해 보자. HttpURLConnection도 굉장히 쉽다.
먼저 인터넷 환경이 필요한 작업이므로 AndroidManifest.xml 파일에
<uses-permission android:name="android.permission.INTERNET"/> 을 작성해 인터넷 환경을 만들어준다.
이제 MainActivity에 네이버의 웹 정보를 받아오는 코드를 작성해보자.
new AsyncTask<Void,Void,Void>(){
@Override
protected void onPreExecute() {
super.onPreExecute();
strUrl = "http://www.naver.com"; //탐색하고 싶은 URL이다.
}
@Override
protected Void doInBackground(Void... voids) {
try{
Url = new URL(strUrl); // URL화 한다.
HttpURLConnection conn = (HttpURLConnection) Url.openConnection(); // URL을 연결한 객체 생성.
conn.setRequestMethod("GET"); // get방식 통신
conn.setDoOutput(true); // 쓰기모드 지정
conn.setDoInput(true); // 읽기모드 지정
conn.setUseCaches(false); // 캐싱데이터를 받을지 안받을지
conn.setDefaultUseCaches(false); // 캐싱데이터 디폴트 값 설정
strCookie = conn.getHeaderField("Set-Cookie"); //쿠키데이터 보관
InputStream is = conn.getInputStream(); //input스트림 개방
StringBuilder builder = new StringBuilder(); //문자열을 담기 위한 객체
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8")); //문자열 셋 세팅
String line;
while ((line = reader.readLine()) != null) {
builder.append(line+ "\n");
}
result = builder.toString();
}catch(MalformedURLException | ProtocolException exception) {
exception.printStackTrace();
}catch(IOException io){
io.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
System.out.println(result);
}
}.execute();
AsynTask는 통신을 할 때 필요한 클래스이다. 이해하면 사용하기 쉽지만, 모르는 사람은 일단 따라 써보기로 하자.
protected void onPreExecute() 메서드 안에는 통신을 하기전 필요한 정보를 셋팅하는 구간이다.
우리가 탐색할 네이버 주소를 적었다.
protected Void doInBackground(Void... voids) 이 메서드가 실제로 통신 할때 작동하는 부분이다.
왠만한 설명은 주석처리 해놨다. 좀더, 정리를 해주자면..
Url = new URL(strUrl); // URL화 한다.
HttpURLConnection conn = (HttpURLConnection) Url.openConnection(); // URL을 연결한 객체 생성.
이 부분이 해당 URL(예시는 네이버)의 정보를 담고 있는 객체를 생성하는 부분이다.
conn.setRequestMethod("GET"); // get방식 통신
conn.setDoOutput(true); // 쓰기모드 지정
conn.setDoInput(true); // 읽기모드 지정
conn.setUseCaches(false); // 캐싱데이터를 받을지 안받을지
conn.setDefaultUseCaches(false); // 캐싱데이터 디폴트 값 설정
이 부분이 해당 통신을 위한 셋팅 부분이다. HttpURLConnection은 스트림 기반이라 셋팅 할 것이 많다.
strCookie = conn.getHeaderField("Set-Cookie"); //쿠키데이터 보관
이 부분은 세션지정을 위한 쿠키값 저장을 하는 부분이다.
httpClient는 쿠키값을 알아서 저장해줬지만 HttpURLConnection은 따로 저장 관리를 해줘야한다.
InputStream is = conn.getInputStream(); //input스트림 개방
StringBuilder builder = new StringBuilder(); //문자열을 담기 위한 객체
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"UTF-8")); //문자열 셋 세팅
String line;
while ((line = reader.readLine()) != null) {
builder.append(line+ "\n");
}
이 부분은 웹 정보를 파싱하는 부분이다. 중요한 점은 웹 정보 마다 다른 문자열 셋일 수 있으므로 맞는 문자열 셋팅을 해줘야 한다.
protected void onPostExecute(Void aVoid)
이 메서드 부분이 해당 통신이 끝난 후 통신작업이 아닌 마무리 작업(UI작업, 사용자 정의 작업 등)을 하는 부분이다.
예시에서는 콘솔에 출력하는 메서드를 썻다.
실행해보면 네이버의 정보를 콘솔에 출력하는 것을 볼 수 있다.
oRTK : { "t": "2015-11-17T12:25Z", "s": "2015.11.17. (화) 12:25 PM", "d": [ { "k": "오마이비너스", "c": "up", "a": "상승", "n": "72" },
{ "k": "신민아", "c": "up", "a": "상승", "n": "99" }, { "k": "진세연", "c": "up", "a": "상승", "n": "225" },
{ "k": "이정재", "c": "up", "a": "상승", "n": "216" }, { "k": "육룡이 나르샤 결방", "c": "up", "a": "상승", "n": "174" },
{ "k": "다이나믹듀오", "c": "up", "a": "상승", "n": "216" }, { "k": "풍선껌", "c": "up", "a": "상승", "n": "63" },
{ "k": "첼시 리", "c": "up", "a": "상승", "n": "348" }, { "k": "먹는존재", "c": "up", "a": "상승", "n": "150" },
{ "k": "명지전문대", "c": "up", "a": "상승", "n": "93" } ] },
콘솔에 찍힌 정보 중간에 실시간 검색어 정보를 발견했다. (실시간 정보는 네이버에서 제공하는 API가 있다.)
시간대가 틀려 찍히는 정보가 틀리겠지만... 무튼 성공 한걸 알 수 있다.
해당 예시는 get 방식으로 웹 정보를 받아오는 방식이다.
추후에 post방식으로 웹 정보를 이용하는 방법도 포스팅 하겠다.
해당 프로젝트는 https://github.com/Mommoo/ExampleCode/tree/master/HttpURLConnection 에서 받을 수 있다.