'안드로이드 메인 쓰레드 익셉션'에 해당되는 글 1건

얼굴도 본적이 없는 본사 신입 안드로이드 개발자로 부터 문의 전화를 받았습니다. 


앱 개발중인데 API 호출 시 android.os.NetworkOnMainThreadException 이 발생했는데 어떻게 해야 하느냐는 문의 였습니다. 


■ NetworkOnMainThreadException 이란?

이는 안드로이드 애플리케이션이 main thread 에서 네트워킹 처리를 시도할 경우 발생하는 오류 입니다. 


안드로이드 Honeycomb (Android 3.0 ☞ API Level 11) 이상 버전에서 부터 Main Thread 에서 네트워킹 프로세스를 금지하고 있습니다. 

다시 이야기 하면 Honeycomb 미만 버전에서는 Main Thread 에서 네트워킹 처리를 허용하고 있다는 말이죠. 

물론 그렇다고 해서 SDK Target 을 하위 버전으로 놓고 개발 하실 분들은 없을 거라 생각합니다. 점유율이 이제 채 5%도 안되는 사용자를 대상으로 앱을 개발 하실 분을 안계시겠죠 :)

하위 버전에서 허용하고 있다고 하더라도 프로세스를 정상적으로 처리 할 수 있을 하드웨어 적인 성능 뒷받침이 안되는 단말들은 어떤 형태로든 오류 발생할 수 있다는 점을 간과 해서는 안될 겁니다 



■ 해결 방법은?

Main Thread 에서 네트워킹 처리를 하는 것이 아니라 AsyncTask 를 생성하여 네트워킹 처리를 하는 것입니다. 


private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}

protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}

protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}


위 예제와 같이 AsyncTask 를 상속받은 class 를 생성합니다. 

그리고 필수 함수로 doInBackgournd(파라미터...) 함수를 override 하여야 합니다. 

여기서 네트워킹 처리를 하면 되구요. 예제는 특정 URL 에 있는 이미지를 다운로드 받는 프로세스(인터넷을 통해 이미지를 다운 받으므로역시 네트워킹입니다) 를 처리하고 있습니다. 



■ AsyncTask 의 4단계 프로세스


1. onPreExecute()

Task 가 시작되기 전 UI Thread (Main Thread) 에서 호출 되는 함수로 일반적으로 프로그래스 바를 보여주는 처리를 할때 많이 사용합니다.


2. doInBackground(Params...)

onPreExecute() 함수가 종료되면 바로 호출 되는 함수로 백그라운드에서 장시간 동안 동작 할 수도 있는 일들을 처리하는 함수 입니다. 일반적으로 네트워킹 처리를 하는 곳이면 인터넷을 통한 이미지 다운로드나 파일 다운로드 등도 해당 됩니다. 


3. onProgressUpdate(Progress..)

호출 시점이 정해 지지 않은 함수로 doInBackground(Params...) 함수가 동작중일때 백그라운드 프로세스 처리율을 전달 합니다. 일반적으로 프로그래스바를 display 할 때 사용합니다. 


4. onPostExecute(Result)

doInBackground(Params...) 함수가 종료 되면 바로 호출 되는 함수 입니다. 백그라운드 프로세스의 처리 결과가 리턴됩니다. 

위 샘플을 참고하자면 이미지를 다운받고 다운 받기가 끝나면 이미지 총 사이즈 (totalSize) 를 반환하게 되어 있습니다. 

이를 onPostExecute() 에서 다운 받은 사이즈를 표기 하는 것으로 처리하고 있습니다. 




간단하게 NetworkOnMainThreadException 에 관해 알아 봤구요. 더불어 해결방안도 같이 정리 해봤습니다. 

많은 도움 되시길 바라겠습니다. 


블로그 이미지

쉬운코딩이최고

Android, Java, jsp, Linux 등의 프로그래밍 언어를 소개 합니다.

,