티스토리 뷰

안드로이드에서 네트워크 연결하기 위해 자바에서처럼 코딩하면 십중팔구는 다음과 같은 오류 메시지를 만난다. 

android.os.NetworkOnMainThreadException


메시지를 살펴보면 Main Thread에서 네트워크를 호출하면서 발생한 오류라고 나온다. 

즉, 안드로이드에서 Main Thread에서는 네트워크 연결을 하지 못하도록 한 것이다. 

아마도 안드로이드 앱에서 네트워크 호출하면서 에러가 발생한 것을 사용자들이 안드로이드의 오류로 인식하기 때문에 그런 듯 하다. 


AsyncTask 쓰레드 클래스 이해

그럼 안드로이드에서는 어떻게 네트워크에 연결할 수 있을까? 

AsyncTask라는 쓰레드 클래스를 상속받아 네트워크 연결하는 부분을 만들면 된다. 


AsyncTask는 상속시 3개의 Generic Type의 매개변수가 필요한데, 

첫번째는 쓰레드를 실행하는 메소드(doInBackground)에서 사용할 매개변수이며,

두번째는 쓰레드가 업데이트될때마다 호출되는 메소드(onProgressUpdate)에서 사용할 Progress 이고, 

세번째는 쓰레드가 완료되면 실행되는 메소드(onPostExecute)에서 사용할 Result의 타입을 나타낸다.


AsyncTask에서 오버라이드할 수 있는 메소드를 호출 순서대로 나열하면 다음과 같다. 

onPreExecute() -> doInBackground(Params... params) -> 

onProgressUpdate(Progress... values) -> onPostExecute(Result result)


아래 살펴볼 예제에서는 간단하게 donInBackground에서 네트워크 연결을 하고, 

onPostExecute에서 화면에 출력하도록 구성했다. 


안드로이드 네트워크 연결 예제


인터넷 접근 권한 설정

먼저 앱에서 네트워크에 접속하기 위한 시스템 권한을 설정한다. 

AndroidManifest.xml 파일에 다음과 같이 설정하면 된다. 

가끔 아래 태그의 위치를 잘못 놓는 경우가 있는데, 부모 엘리먼트는 <manifest>라는 것을 꼭 기억해 두기 바란다. 


android.permission.INTERNET은 인터넷 접속을 위한 권한 설정이고, 

android.permission.ACCESS_NETWORK_STATE는 인터넷 접속이 가능한지 체크하기 위해 네트워크 상태를 볼 수 있는 권한이다. 


레이아웃 설정

예제를 위한 레이아웃을 다음과 같이 설정한다.  (activity_json.xml)


레이아웃은 단순하다. "SEND" 버튼을 클릭하면 웹으로 연결해서 결과값을 가져와서 맨 아래의 텍스트뷰에 뿌려주는 것이다.

SEND 버튼의 클릭 이벤트 처리를 위해서  18번째 줄에 android:onClick="sendData" 를 추가했다. 


액티비티 코딩

"SEND" 버튼을 클릭했을 때 처리를 다음과 같이 구성한다. (JsonActivity.java)


12번째 줄을 보면 네트워크에 연결이 가능한지 살펴보고 난 후, 

13번째 줄에서 DownloadJson이라는 AsyncTask를 상속받은 쓰레드 클래스를 실행하고 있다. 

만약 인터넷 연결이 안되어 있을 경우, Toast로 메시지를 출력하도록 구성했다. 


참고로 데이터로 가져올 URL은 이전 강좌인 PHP를 활용하여 DB 내용을 JSON으로 출력하기 를 참고하기 바란다.


AsyncTask를 상속 받은 웹 연결 쓰레드 코딩

앞서 설명한 doInBackground와 onPostExecute를 오버라이딩해서 구현한 소스는 다음과 같다. 


doInBackground에서는 getData라는 메소드를 호출해서 인터넷 연결해서 데이터를 가져오도록 했다. 

onPostExecute에서는 가져온 데이터를 텍스트뷰에 출력하는 역할을 한다. 


참고로 getData 메소드를 살펴보면 연결을 위해 HTTPURLConnection을 사용하고 있다. 

예전에는 아파치의 HttpClient나 DefaultHttpClient를 사용했으나 허니컴 이후 deprecated 되었다. 


JsonActivity.java의 전체 소스는 다음과 같다. 

댓글
  • 프로필사진 미니~ 위 글과 관련한 질문이 올라와서 댓글로 남깁니다.

    1. onPostExecute() 함수 호출
    onPostExecute() 함수는 명시적으로 호출하는 것이 아니라
    맨 앞에 설명한 것처럼 AsyncTask를 상속 받은 클래스를 실행할 경우, 순서대로 호출하게 되는 함수 중의 하나입니다.

    즉, onPreExecute() -> doInBackground -> onProgressUpdate-> onPostExecute

    그러므로 47번째 줄에서 new DownloadJson().execute(url); 를 실행하면 onPostExecute()까지 호출되는 것이죠.

    2. getData()의 리턴값
    getData()에서 리턴하는 return sb.toString(); 값이 어디로 가는지에 대한 문의도 있었는데요.

    61번째 줄을 보면 doInBackground에서 getData()를 호출하고
    그 결과값을 리턴하는 것을 확인할 수 있습니다.

    이렇게 되면 AsyncTask에서는 리턴된 결과값을 onPostExecute()함수에 파라미터로 전달하게 됩니다.

    3. 예제 실행시 결과값이 안보이는 경우
    예제를 그대로 따라했는데 결과값이 안 보인다면,

    1) 네트워크 접속이 가능한지 확인하고
    2) 네트워크 접속 권한 설정을 했는지 확인하고
    3) 위 예제에서 layout 파일(activity_json.xml)과 JsonActivity.java 파일을 제대로 작성했는지 확인한번 해보세요~



    2015.07.27 00:04 신고
댓글쓰기 폼