Please Enable JavaScript!
Gon[ Enable JavaScript ]

반응형

해당 에러는 허니컴 이후부터 네트워크 관련 작업을 진행할 때 발생할 수 있습니다. 메인 Thread 에서 발생하는 에러로 네트워크를 이용해 데이터를 받기 위해서는 별개의 Thread 가 필요합니다. 그렇지 않으면 Stream 객체를 통해 데이터를 읽어 오는 과정에서 android.os.NetworkOnMainThreadException 에러가 나게 됩니다. 네트워크 처리를 잘 못하게 되면 메인 Thread 가 멈출 수 있으므로 강제로 분리해서 구현하도록 만든 것 같습니다.

 

 

데이터를 읽어 오는 InputStreamReader 에서 Exception 이 발생한 것입니다. 네트워크 특성상 가져오는 데이터 양이 정해져 있지 않기 때문에 Thread 를 별도로 돌려야 합니다. 그렇지 않으면 데이터를 가져오는 동안 프로그램이 멈춰 있겠죠

안드로이드 android.os.NetworkOnMainThreadException 에러, Thread를 사용해야 되는 경우

 

네트워크를 통해서 데이터를 가져오는 소스는 다음과 같습니다. 여기에 에러가 나지 않도록 Thread 를 추가하겠습니다. 데이터를 가져오는 getNaverHtml() 함수가 Thread 안에서 실행을 해야겠죠

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class NetworkActivity extends Activity {

    private TextView edtHtml;
    final int CONN_TIME = 5000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_network);
        String naverHtml = getNaverHtml();

        edtHtml = (TextView)this.findViewById(R.id.edtHtml);
        edtHtml.setText(naverHtml);
    }

    private String getNaverHtml(){
        String naverHtml = "";

        HttpURLConnection con = null;
        InputStreamReader isr = null;
        BufferedReader br = null;

        try{
            URL url = new URL("http://www.naver.com");
            con = (HttpURLConnection) url.openConnection();
            con.setConnectTimeout(CONN_TIME);
            con.setReadTimeout(CONN_TIME);

            isr = new InputStreamReader(con.getInputStream());
            br = new BufferedReader(isr);

            String str = null;
            while ((str = br.readLine()) != null) {
                naverHtml += str + "\n";
            }

        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(con != null){
                try{con.disconnect();}catch(Exception e){}
            }

            if(isr != null){
                try{isr.close();}catch(Exception e){}
            }

            if(br != null){
                try{br.close();}catch(Exception e){}
            }
        }
        return naverHtml;
    }
}

 

 

아래 소스처럼 getNaverHtml() 함수를 Thread run() 함수 안에 넣고 실행합니다. 가져온 데이터는 메인 Thread 인 화면에 데이터를 전달하기 위해서 Handler 을 사용합니다

new Thread() {
    public void run() {
        String naverHtml = getNaverHtml();

        Bundle bun = new Bundle();
        bun.putString("HTML_DATA", naverHtml);
        
        Message msg = handler.obtainMessage();
        msg.setData(bun);
        handler.sendMessage(msg);
    }
}.start();

 

 

데이터를 화면에 표시하는 Handler 소스는 다음과 같습니다. Thread 로부터 전달 받은 html 데이터를 EditText 추가합니다

Handler handler = new Handler() {
    public void handleMessage(Message msg) {
        Bundle bun = msg.getData();
        String naverHtml = bun.getString("HTML_DATA");
        edtHtml.setText(naverHtml);
    }
};

 

 

전체 소스는 다음과 같습니다

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class NetworkActivity extends Activity {

    private TextView edtHtml;
    final int CONN_TIME = 5000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_network);
        String naverHtml = getNaverHtml();

        edtHtml = (TextView)this.findViewById(R.id.edtHtml);
        //edtHtml.setText(naverHtml);

        new Thread() {
            public void run() {
                String naverHtml = getNaverHtml();

                Bundle bun = new Bundle();
                bun.putString("HTML_DATA", naverHtml);
                
                Message msg = handler.obtainMessage();
                msg.setData(bun);
                handler.sendMessage(msg);
            }
        }.start();
    }

    Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            Bundle bun = msg.getData();
            String naverHtml = bun.getString("HTML_DATA");
            edtHtml.setText(naverHtml);
        }
    };

    private String getNaverHtml(){
        String naverHtml = "";

        HttpURLConnection con = null;
        InputStreamReader isr = null;
        BufferedReader br = null;

        try{
            URL url = new URL("http://www.naver.com");
            con = (HttpURLConnection) url.openConnection();
            con.setConnectTimeout(CONN_TIME);
            con.setReadTimeout(CONN_TIME);

            isr = new InputStreamReader(con.getInputStream());
            br = new BufferedReader(isr);

            String str = null;
            while ((str = br.readLine()) != null) {
                naverHtml += str + "\n";
            }

        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(con != null){
                try{con.disconnect();}catch(Exception e){}
            }

            if(isr != null){
                try{isr.close();}catch(Exception e){}
            }

            if(br != null){
                try{br.close();}catch(Exception e){}
            }
        }
        return naverHtml;
    }
}

 

※ 아래는 참고하면 좋을 만한 글들의 링크를 모아둔 것입니다.
스마트폰 드로이드 개발을 위한 개발자 모드 켜고 끄는 방법
이클립스(Eclipse) 안드로이드 개발도구 ADT 설치하기
안드로이드 스튜디오 개발 문서 API 참고하는 방법
안드로이드 Android 배포를 위한 개발자 등록하기
드로이드 개발 Intent 이용한 전화 걸기

 

반응형
Posted by 녹두장군

댓글을 달아 주세요

  1. Favicon of https://lang-thai.tistory.com 개발자 장고 2019.10.26 15:33 신고  댓글주소  수정/삭제  댓글쓰기

    잘 정리해주셔서 감사합니다. 도움 많이 되었습니다.
    다만 오타를 말씀드리고 싶은데, 마지막 전체 소스중 21번의 getNaverHtml(); 는 삭제하는게 맞는것 같습니다.
    thread 함수 내에서 실행되었기 때문이죠.