2016-08-17 4 views
1

Я использую службу для проверки состояния сервера и уведомления пользователя об этом. Он отлично работает, пока активность приложения не будет уничтожена. Я сохраняю службу, даже если действие уничтожается, но если сбой происходит каждый раз. Любые предложения?Почему он выбрасывает android.os.NetworkOnMainThreadException на службе после уничтожения активности?

Услуги:

package com.vasil.wall.chss.MP; 

import android.app.NotificationManager; 
import android.app.PendingIntent; 
import android.content.Context; 
import android.content.Intent; 
import android.os.IBinder; 
import android.os.Binder; 
import android.os.Handler; 
import android.support.v4.app.NotificationCompat; 

import android.os.Handler; 
import java.util.TimerTask; 
import java.util.Timer; 
import org.peter.cucker.Single; 

import android.util.Log; 
import android.os.AsyncTask; 

import com.vasil.wall.R; 

public class OpponentService extends android.app.Service { 

    private boolean mRunning;//state 
    private static String service_tag = "MyService"; 
    private NotificationManager nm; 
    private static final int NOTIFICATION_ID_CONNECTED = 0; 

    private final int requestPeriod = 4000;//20seconds 
    final Handler handler = new Handler(); 
    private Timer timer = new Timer(); 
    private TimerTask invitesListenerServiceTask; 
    private InvitesManager incomingIvitesManager = new InvitesManager(); 

    public class LocalBinder extends Binder 
    { 
     public OpponentService getService() 
     { 
      return OpponentService.this; 
     } 
    } 

    private final IBinder mBinder = new LocalBinder(); 

    @Override 
    public IBinder onBind(final Intent intent) 
    { 
     Log.d(service_tag, "onBindService"); 
     return mBinder; 
    } 

    @Override 
    public boolean onUnbind(final Intent intent) 
    { 
     Log.d(service_tag, "onUnbindService"); 
     return super.onUnbind(intent); 
    } 

    @Override 
    public void onCreate() 
    { 
     mRunning = false; 
     super.onCreate(); 
     Log.d(service_tag, "onCreateService"); 
     nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 
    } 

    @Override 
    public int onStartCommand(final Intent intent, final int flags, final int startId) 
    { 
     if (!mRunning) { 
      mRunning = true; 
     } 
     ii_listener_start(MPapi.getinstance().get_gameid(getApplicationContext())); 
     return START_STICKY; 
     //return START_NOT_STICKY; 
    } 

    @Override 
    public void onDestroy() 
    { 
     mRunning = false; 
     ii_listener_cancel(); 
     super.onDestroy(); 
     Log.d(service_tag, "onDestroyService"); 
    } 

    public void ii_listener_start(final int createdgame_id) { 
     invitesListenerServiceTask = new TimerTask() { 
      @Override 
      public void run() { 

       handler.post(new Runnable() { 
        public void run() { 
         incomingIvitesManager.get_invites_from_server(createdgame_id); 
         if (!incomingIvitesManager.RES_GETINVITES.equals("") && 
          !incomingIvitesManager.RES_GETINVITES.equals("invite")) { 
          ii_listener_cancel(); 
          restoreForeground(incomingIvitesManager.RES_GETINVITES); 
          //stopSelf();//stop service 
         } 
         else {} 
        } 
       }); 

      } 
     }; 

     timer.schedule(invitesListenerServiceTask, 0, requestPeriod);// execute in every 4s till success 
    } 

    public void ii_listener_cancel() { 
     //stopSelf();//stop service 
     if (invitesListenerServiceTask != null) 
      invitesListenerServiceTask.cancel(); 
    } 

    public void restoreForeground(String player2) { 
     final NotificationCompat.Builder notification = new NotificationCompat.Builder(OpponentService.this); 
     notification.setSmallIcon(R.drawable.chess_notification); 
     notification.setContentTitle(getString(R.string.app_name)); 
     notification.setContentText(getString(R.string.mp_opponent_ready, player2)); 
     notification.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, Single.class), 0)); 
     notification.setWhen(System.currentTimeMillis()); 
     notification.setOngoing(true); 
     notification.setAutoCancel(true); 
     notification.setVibrate(new long[] { 1000, 1000, 1000, 1000, 1000 }); 
     nm.notify(NOTIFICATION_ID_CONNECTED, notification.getNotification()); 
    } 

} 

журнала:

08-17 01:49:44.662: E/AndroidRuntime(10372): FATAL EXCEPTION: main 

08-17 01:49:44.662: E/AndroidRuntime(10372): android.os.NetworkOnMainThreadException 

08-17 01:49:44.662: E/AndroidRuntime(10372): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at java.net.InetAddress.lookupHostByName(InetAddress.java:385) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at java.net.InetAddress.getAllByName(InetAddress.java:214) 08-17 01:49:44.662: E/AndroidRuntime(10372):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at com.vasil.wall.chss.HttpWorker.getJSONFromUrl(HttpWorker.java:173) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at com.vasil.wall.chss.MP.InvitesManager.get_invites_from_server(InvitesManager.java:82) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at com.vasil.wall.chss.MP.OpponentService$1$1.run(OpponentService.java:97) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at android.os.Handler.handleCallback(Handler.java:615) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at android.os.Handler.dispatchMessage(Handler.java:92) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at android.os.Looper.loop(Looper.java:137) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at android.app.ActivityThread.main(ActivityThread.java:4867) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at java.lang.reflect.Method.invokeNative(Native Method) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at java.lang.reflect.Method.invoke(Method.java:511) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) 

08-17 01:49:44.662: E/AndroidRuntime(10372): at dalvik.system.NativeStart.main(Native Method) 

ответ

1

Ошибка точно так, как говорит исключение, вы делаете вещи сети на главном (UI) нити.

Чтобы понять, почему вы должны знать, что new Handler() привязывается к потоку, на котором он создан, который, по-видимому, будет основным потоком, поскольку он создается во время построения службы.

Это означает, что работа, выполненная в вызове handler.post(..), будет выполнена в основном потоке, вызывая исключение.

Чтобы устранить проблему, используйте либо AsyncTask, либо убедитесь, что обработчик связан с другим Looper при его создании.

+0

Спасибо за ответ. ii_listener_start (MPapi.getinstance(). Get_gameid (getApplicationContext())); - проблема в этой строке. Я поместил строку в поток http://stackoverflow.com/a/20644728 и AsyncTask - он все равно выдает ошибку. –

+1

@VitaliGrabovski Перемещение только этой строки не устранит проблему, потому что '.get_invites_from_server (...)' все еще выполняется с использованием обработчика, который привязан к основному потоку. Вы должны прочитать о параллелизме на Android, потому что вам нужно понять, что делает этот код для решения этой проблемы. – Kiskae

+0

Я заменил обработчик AsyncTask. Он работает сейчас. –

Смежные вопросы