본문 바로가기
안드로이드

[Android] android.os.NetworkOnMainThreadException 해결

by 코딩히어로 2022. 10. 6.
728x90

title


안드로이드에서 Network를 이용한 TCP/IP 통신을 구현함에 있어 다음과 같은 에러가 발생했습니다

android.os.NetworkOnMainThreadException

해당 에러의 발생 원인은 Network API를 MainActivity에서 직접 호출했을 경우인데

MainActivity에서 Network관련 작업을 직접 실행할 경우 MainThread가 멈추는 현상이

발생할 수 있기 때문에 Android OS에서는 해당 에러 문구를 출력하게 됩니다.

 

즉 해당 에러는 MainThread에서 Network를 호출했다는게 문제가 된다는 것인데

간단하게 해결할 수 있는 방법은 MainThread가 아닌 Sub Thread에서 해당 작업을 하거나

Background 작업에서 Network 관련 기능을 실행하면 됩니다

 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        socket.connect(new InetSocketAddress("1.1.1.1",1234));
        is = socket.getInputStream();
        os = socket.getOutputStream();
    }

먼저 해당 에러는 위 코드처럼 MainActivity의 onCreate에서 직접 Socket을 connect 했을 때

발생하는 것을 확인할 수 있는데 MainActivity의 onCreate는 MainThread이기 때문입니다

즉 이 문제를 해결하기 위해 간단하게 Thread를 통해 구현이 가능합니다.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new Thread(()->{
            socket.connect(new InetSocketAddress("1.1.1.1",1234));
            is = socket.getInputStream();
            os = socket.getOutputStream();
        }).start();
    }

위 방법은 별도의 Thread를 선언하지 않고 구현하는 방법으로

new Thread를 통해 Socket Connect 작업을 sub Thread로 넘겼기 때문에

MainThread와는 별도로 동작하고 해당 에러 또한 해결이 가능합니다.

 

여기서 많은분들이 혼동하시는 부분은 Handler를 이용해서 처리해도 되냐고 물어보시는데

Handler작업은 엄밀히 말해서 MainThread에서 동작하기 때문에 sub Thread와는 다른 개념입니다.

 

먼저 위 코드에서 new Thread를 통해 구현이 되면 코드가 약간 지저분한 느낌이 있습니다.

나중에 코드를 읽을때에도 정확히 무슨 부분인지 명시적으로 파악이 되지 않기 때문에

좀 더 깔끔한 코드를 위해서는 다음과 같은 코드가 좋다 생각됩니다.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        NetWorkConnect net = new NetWorkConnect();
        net.start();
    }
    
    
    class NetWorkConnect extends Thread {
        @Override
        public void run() {
            socket.connect(new InetSocketAddress("1.1.1.1",1234));
            is = socket.getInputStream();
            os = socket.getOutputStream();
        }
    }

명시적인 Thread를 정의하고 MainThread에서는 해당 Thread를 호출하는 방식으로 사용하면

이 부분이 NetworkConnct를 실행하는 부분이구나라고 한 번에 파악이 되기 때문에

되도록이면 코드에도 어느 정도 정리가 필요합니다

728x90
반응형

댓글