Android Socket IO в службе, получая исключение NullPointerException

Я бегу Gottox's Socket IO client для Android. Я начинаю соединение в IntentService и планирование отключения соединения в той же службе.

Я получаю NullPointerException на socket.disconnect(); линия, но не могу понять, почему. Сокет SocketIO является переменной уровня класса и Socket IO Соединение уже открыто, когда я пытаюсь отключиться.

Так почему я получаю NPE?

public class SocketIOService extends IntentService {

public static final String KEY_ACTION = "action";
public static final String ACTION_START = "start";
public static final String ACTION_STOP = "stop";

private Preferences prefs;
private SocketIO socket;

public SocketIOService() {
    super("com.test.test.SocketIOService");
}

@Override
protected void onHandleIntent(Intent intent) {
    String action = intent.getStringExtra(KEY_ACTION);

    if (action.equalsIgnoreCase(ACTION_START)) {
        Log.v("SOCKET IO SERVICE", "STARTED");
        prefs = new Preferences(this);

        // Socket IO connection
        try {
            socket = new SocketIO("http://test.test.com:8002");
            SocketIO.setDefaultSSLSocketFactory(SSLContext.getDefault());
            socket.connect(new IOCallback() {

                @Override
                public void onMessage(JSONObject json, IOAcknowledge ack) {
                    try { Log.v("SOCKET IO SERVER SAID", json.toString(2)); } 
                    catch (JSONException e) { e.printStackTrace(); }
                }

                @Override
                public void onMessage(String data, IOAcknowledge ack) {
                    Log.v("SOCKET IO SERVER SAID", data);
                }

                @Override
                public void onError(SocketIOException socketIOException) {
                    Log.e("SOCKET IO", "ERROR");
                    socketIOException.printStackTrace();
                }

                @Override
                public void onDisconnect() {
                    Log.v("SOCKET IO CONNECTION", "TERMINATED");
                }

                @Override
                public void onConnect() {
                    Log.v("SOCKET IO CONNECTION", "ESTABLISHED");
                }

                @Override
                public void on(String event, IOAcknowledge ack, Object... args) {
                    Log.v("SERVER TRIGGERED EVENT", event);
                }
            });

            // This line is cached until the connection is established.
            socket.emit("userid", prefs.getUserId());
        } 
        catch (MalformedURLException e) { e.printStackTrace(); }
        catch (NoSuchAlgorithmException e1) { e1.printStackTrace(); }
    }

    if (action.equalsIgnoreCase(ACTION_STOP)) {
        Log.v("SOCKET IO SERVICE", "STOPPED");
        socket.disconnect();
        stopSelf();
    }

}

}

LogCat

04-13 20:04:49.314: E/AndroidRuntime(15025): FATAL EXCEPTION: IntentService[com.test.test.SocketIOService]
04-13 20:04:49.314: E/AndroidRuntime(15025): java.lang.NullPointerException
04-13 20:04:49.314: E/AndroidRuntime(15025):    at com.test.test.SocketIOService.onHandleIntent(SocketIOService.java:89)
04-13 20:04:49.314: E/AndroidRuntime(15025):    at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
04-13 20:04:49.314: E/AndroidRuntime(15025):    at android.os.Handler.dispatchMessage(Handler.java:99)
04-13 20:04:49.314: E/AndroidRuntime(15025):    at android.os.Looper.loop(Looper.java:137)
04-13 20:04:49.314: E/AndroidRuntime(15025):    at android.os.HandlerThread.run(HandlerThread.java:60)

2 ответа

Решение

IntentService не работает так же, как обычные сервисы. Как только он достигает конца onHandleIntent, он останавливается сам. Вероятно, происходит то, что служба устанавливает соединение через сокет, понимает, что она закончила свою работу и останавливает себя. Затем, когда намерение с действием ACTION_STOP Когда Android запущен, Android создает новый экземпляр вашего сервиса и доставляет Намерение, но этот экземпляр не создал экземпляр сокета.

Способ подтвердить это будет добавить android.util.Log.d("SocketIOService", "" + hashCode()); в начале onHandleIntent, затем действуйте как обычно. Проверьте свои журналы, чтобы видеть, являются ли hashCodes одинаковыми - я ожидаю, что они будут отличаться, указывая, что они - различные экземпляры службы.

Вам, вероятно, нужно вместо этого использовать обычный Сервис и управлять собственным рабочим потоком в нем.

Сначала вы должны проверить на ноль, как показано в кодах ниже:

if (action.equalsIgnoreCase(ACTION_STOP)) {
    if (socket != null) {
        socket.disconnect();            
    }
    stopSelf();
}

Это предотвратит любую NullPointerException ошибка при попытке закрыть сокет.

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