android.os.NetworkOnMainThreadException при попытке использовать сервис

Я пытаюсь создать приложение, которое постоянно читает данные SBS-1 с сервера, на котором выполняется dump1090. Я подумал, что для этого лучше использовать Service, а не AsyncTask, поскольку, по крайней мере, его жизненный цикл будет независимым от компонентов пользовательского интерфейса, плюс AFAIK AsyncTasks следует использовать для коротких операций.

Вот мой код:

@Override
public void onCreate() {
    super.onCreate();
    try {
        //TODO: NetworkOnMainThread error
        socket = new Socket(SERVER_URL, SERVER_PORT);
        socketConnected = true;
        inputStream = socket.getInputStream();
        diStream = new DataInputStream(inputStream);
        readerOpen = true;
        ConnectSocket connectSocket = new ConnectSocket();
        Log.d(getClass().toString(), "Socket created!");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Однако, как только я запускаю приложение, это происходит:

FATAL EXCEPTION: main
Process: com.example.[APP_NAME], PID: 2317
java.lang.RuntimeException: Unable to create service com.example.[APP_NAME].services.SocketService: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2887)
at android.app.ActivityThread.-wrap4(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1427)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
at java.net.InetAddress.lookupHostByName(InetAddress.java:431)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
at java.net.InetAddress.getAllByName(InetAddress.java:215)
at java.net.Socket.tryAllAddresses(Socket.java:109)
at java.net.Socket.<init>(Socket.java:178)
at java.net.Socket.<init>(Socket.java:150)
at com.example.[APP_NAME].services.SocketService.onCreate(SocketService.java:50)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2877)
at android.app.ActivityThread.-wrap4(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1427) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:148) 
at android.app.ActivityThread.main(ActivityThread.java:5417) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

Что я делаю неправильно? Нужно ли добавлять новый поток для запуска моего сервиса?

3 ответа

Android не разрешает сетевые вызовы в главном потоке, так как это приведет к нежелательным задержкам в главном потоке, поэтому по умолчанию выдает ошибку.

Для выполнения сетевых вызовов вы можете использовать Threads и AsyncTask для выполнения фонового сетевого вызова.

Самый простой способ выполнять сетевые вызовы - это использовать AsysncTask, который в основном используется для "сетевых вызовов LowData".

 private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... urls) {

            // params comes from the execute() call: params[0] is the url.
            try {
                return downloadUrl(urls[0]);
            } catch (IOException e) {
                return "Unable to retrieve web page. URL may be invalid.";
            }
        }
        // onPostExecute displays the results of the AsyncTask.
        @Override
        protected void onPostExecute(String result) {
            textView.setText(result);
       }
    }

и для фоновых сетевых вызовов вы можете использовать библиотеки также как "VOLLEY".

Вызывается: android.os.NetworkOnMainThreadException Это означает, что вы должны запускать свой сервис в другом потоке, чем в Main/UI Thread. При попытке доступа к сетевым ресурсам из основного потока вы всегда увидите это исключение. Более подробная информация: Как исправить android.os.NetworkOnMainThreadException?

Попробуйте использовать свой сокет в фоновом процессе. Используйте AsyncTask для этого. У меня была та же проблема, которая была решена. И убедитесь, что вы предоставили разрешения в Манифесте ИНТЕРНЕТА, ACCESS_NETWORK_STATE.

Другие вопросы по тегам