我使用主活动类中的以下代码连接到Socket.io服务器。
private Socket socket; {
Options opts = new IO.Options();
opts.reconnection=true;
socket = IO.socket("Server ip",opts);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
Log.w("Connection","Ok");
}
});
}
它在另一个线程中自动连接。然后,如果用户按下后退按钮,我将按以下行运行:
this.finish();
所以,我正在关闭活动,然后我正在使用这样的onDestroy()
方法:
@Override
protected void onDestroy() {
super.onDestroy();
Log.w("Destry","ok");
socket.disconnect();
socket=null;
}
但是,当我再次启动我的应用时,nullPointerException
socket
变量就崩溃了。
如果我使用System.exit(0)
代替this.finish()
,那么当我再次启动应用时,它运行良好而没有NullPointerException
我认为在调用this.finish()
方法并且我不想使用System.exit(0)
我该如何解决这个问题?
编辑:崩溃日志
02-12 22:52:22.304: E/AndroidRuntime(14804): FATAL EXCEPTION: EventThread
02-12 22:52:22.304: E/AndroidRuntime(14804): java.lang.NullPointerException
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.impact.ribony.MainActivity$2.call(MainActivity.java:275)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.access$701(Socket.java:18)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket$5.run(Socket.java:166)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.thread.EventThread.exec(EventThread.java:50)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.emit(Socket.java:162)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.onconnect(Socket.java:353)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.onpacket(Socket.java:276)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket.access$100(Socket.java:18)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Socket$2$2.call(Socket.java:101)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.ondecoded(Manager.java:377)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.access$1200(Manager.java:20)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager$3.call(Manager.java:351)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.parser.Parser$Decoder.add(Parser.java:156)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.ondata(Manager.java:369)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager.access$1000(Manager.java:20)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.socketio.client.Manager$2.call(Manager.java:342)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Socket.onPacket(Socket.java:485)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Socket.access$900(Socket.java:29)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Socket$5.call(Socket.java:288)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.emitter.Emitter.emit(Emitter.java:117)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.Transport.onPacket(Transport.java:121)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling.access$700(Polling.java:15)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling$2.call(Polling.java:122)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.parser.Parser.decodePayload(Parser.java:251)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling._onData(Polling.java:132)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.Polling.onData(Polling.java:104)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.engineio.client.transports.PollingXHR$5$1.run(PollingXHR.java:113)
02-12 22:52:22.304: E/AndroidRuntime(14804): at com.github.nkzawa.thread.EventThread$2.run(EventThread.java:75)
02-12 22:52:22.304: E/AndroidRuntime(14804): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-12 22:52:22.304: E/AndroidRuntime(14804): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-12 22:52:22.304: E/AndroidRuntime(14804): at java.lang.Thread.run(Thread.java:841)
答案 0 :(得分:5)
这是我正在运行的服务来处理我的SocketIO连接。我为你清理了它,所以你可以重复使用它。
public class SocketIOConnection extends Service {
//you need constants to tell servise and activity what you are sending a message for
public static final int REGISTER_CHAT_ACTIVITY = 1;
public static final int MESSAGE_RECEIVED = 2;
final Messenger mMessenger = new Messenger(new IncomingHandler());
Messenger chat;
private Socket socket;
@Override
public void onCreate() {
try {
socket = IO.socket("IP HERE");
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
}
}).on("connected", new Emitter.Listener() {
@Override
public void call(Object... args) {
emitUserId();
}
})on("message", new Emitter.Listener() {
@Override
public void call(Object... args) {
//for example you are receiving a message with event name "message"
//you now send the information you need to update the UI
// to the activity which is actually showing the UI
//in this case i have a messenger (see above) named chat
//which is initiated below
//for now we just send a message
chat.send(Message.obtain(null, MESSAGE_RECEIVED, args[0])); //if you have more than one object (it is not a json) you can send the whole args array and handle it in the activity
}
});
//and add all the other on listeners here
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (socket != null) {
socket.disconnect();
socket.connect();
} else {
try {
socket = IO.socket("IP HERE");
socket.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
//handle messages sent to service here
//second parameter in Message.obtain() is stored in msg.what
//so you need a switch case for the handling
switch(){
case REGISTER_CHAT_ACTIVITY:
chat = msg.replyTo;
break;
}
}
}
public class LocalBinder extends Binder {
SocketIOConnection getService() {
return SocketIOConnection.this;
}
}
}
在您的活动中,您只需添加以下内容:
public class MyChatActivity extends Activity {
public static Messenger mService = null;
public final Messenger mMessenger = new Messenger(new IncomingHandler());
public boolean mIsBound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout_id);
doBindService();
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
mService = new Messenger(service);
try {
Message msg = Message.obtain(null, SocketIOConnection.REGISTER_CHAT_ACTIVITY);
msg.replyTo = mMessenger;
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName className) {
mService = null;
}
};
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SocketIOConnection.MESSAGE_RECEIVED:
//here you have the objects sent to you via the socket
//you passed them as the third parameter of Message.obtain()
Object message = msg.obj;
//you can cast the object to the type you want and update the UI as you wish with the object
break;
default:
super.handleMessage(msg);
}
}
}
public void doBindService() {
if (!mIsBound) {
context.bindService(new Intent(context,
SocketIOConnection.class), mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
}
}
如果您想了解活动和服务之间的沟通方式,可以阅读this文章。
编辑: 在您的活动中覆盖此方法:
public void doUnbindService() {
if (mIsBound) {
unbindService(mConnection);
mIsBound = false;
}
}
@Override
protected void onPause() {
doUnbindService();
stopService(new Intent(yourActivity.class, SocketIOConnection.class));
super.onPause();
}
@Override
protected void onDestroy() {
doUnbindService();
stopService(new Intent(yourActivity.class, SocketIOConnection.class));
super.onDestroy();
}