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
ошибка при попытке закрыть сокет.