为什么在活动销毁后它会在服务上抛出android.os.NetworkOnMainThreadException?

时间:2016-08-17 00:18:41

标签: android service networkonmainthread

我正在使用服务检查服务器状态并注意用户。 它的工作正常,直到应用程序的活动被破坏。 即使活动被破坏但我每次都失败,我也会保留服务。 有什么建议吗?

服务:

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 个答案:

答案 0 :(得分:2)

错误就像异常所说的那样,你在主(UI)线程上做网络工作。

要理解为什么你需要知道new Handler()绑定到创建它的线程,这可能是主线程,因为它是在构建服务期间创建的。

这意味着在handler.post(..)调用中完成的工作将在主线程上执行,从而导致异常。

要解决此问题,请使用AsyncTask或确保Handler在创建时绑定到其他Looper。