Android 개발시 apache http client 모듈을 이용할 경우 HttpClient 클래스를 이용하여 다음과 같이 GET/POST 메소드로 전송할 수 있다. 즉, HTTP로 요청할 수 있다.
일단 간단한 소스 코드를 살펴보자.
HttpClient client = new DefaultHttpClient();
HttpGet method = new HttpGet("http://www.daum.net");
method.setHeader("User-Agent", "Android emulator");
HttpResponse res = null;
try {
res = client.execute(method);
StatusLine status = res.getStatusLine();
if (status.getStatusCode() == HttpStatus.SC_OK) {
System.out.println("Method completed");
} else {
System.err.println("Method failed: " + status.getReasonPhrase());
}
} catch ( ClientProtocolException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
일단, 위의 소스는 에러가 발생하지 않는다. 왜냐하면 HttpGet 클래스를 이용한 GET 메소드로 요청하는 것이기 때문이다.
따라서 별도의 Content-Length를 명시하지 않아도 된다.
그런데, 만약 POST 메소드로 요청시에는 Http body 가 첨부됨으로 Content-Length 를 http header 에 명시해 준다. 안드로이드 상에서는 다음과 같이 해 주면 된다.
method.setHeader("Content-Length", "" + httpBody.length);
여기서 이 코딩이 화근이다. 실제로 안드로이드 버전이 아닌 자바 버전의 아파치 HttpComponents를 이용할 경우에는 POST로의 요청일 경우에도 위의 코드를 넣어줄 경우에는 에러가 발생하지 않는다.
하지만, 안드로이드 애플리케이션에서 다음과 같이 http body 를 넣어줄 수 있는데, 여기서 위의 코드와 같이 Content-Length 를 명시할 경우 ClientProtocolException 이 발생한다.
byte[] httpBody = "Android http body".getByte();
HttpEntity entity = new ByteArrayEntity(httpBody);
HttpGet method = new HttpGet("http://test.wiseant.net/debugger");
method.setHeader("Content-Length", "" + httpBody.length);
05-22 06:40:56.533: WARN/System.err(1030): org.apache.http.client.ClientProtocolException
따라서 실제코드 상에서는 Content-Length 를 명시하는 setHeader 메소드를 사용하지 않아야 한다.
자바 버전의 HttpComponents 를 사용하는 것과 안드로이드의 Http client 컴포넌트를 사용하는 것은 상당 부분 차이가 난다.
흠... 이 버그 찾는데 오후 내도록 찾은 것이니 아깝진 하다... 쩝...^^;;