【问题标题】:Socket.io Android NullPointerException and cannot find the causeSocket.io Android NullPointerException,找不到原因
【发布时间】:2018-02-19 10:21:15
【问题描述】:

我正在开发一个使用socket.io java client 的android/ios 应用游戏,以及一个也使用socket.io 的node.js 后端。在 ios 应用程序上,一切正常,但我的分析工具告诉我,在 android 中有很多用户面临致命异常。这里是:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
   at io.socket.client.Socket.onevent(Unknown Source)
   at io.socket.client.Socket.connect(Unknown Source)
   at io.socket.client.Socket.open(Unknown Source)
   at io.socket.client.Socket$2$2.call(Unknown Source)
   at io.socket.emitter.Emitter.on(Unknown Source)
   at io.socket.client.Manager.emitAll(Unknown Source)
   at io.socket.client.Manager.reconnection(Unknown Source)
   at io.socket.client.Manager$7.call(Unknown Source)
   at io.socket.emitter.Emitter.on(Unknown Source)
   at io.socket.parser.Parser$Decoder.add(Unknown Source)
   at io.socket.client.Manager.emitAll(Unknown Source)
   at io.socket.client.Manager.reconnection(Unknown Source)
   at io.socket.client.Manager$2.call(Unknown Source)
   at io.socket.emitter.Emitter.on(Unknown Source)
   at io.socket.engineio.client.Socket.open(Unknown Source)
   at io.socket.engineio.client.Socket.open(Unknown Source)
   at io.socket.engineio.client.Socket$5.call(Unknown Source)
   at io.socket.emitter.Emitter.on(Unknown Source)
   at io.socket.engineio.client.Transport.onError(Unknown Source)
   at io.socket.engineio.client.transports.Polling.pause(Unknown Source)
   at io.socket.engineio.client.transports.Polling$2.call(Unknown Source)
   at io.socket.engineio.parser.Parser.encodePacket(Unknown Source)
   at io.socket.engineio.client.transports.Polling.pause(Unknown Source)
   at io.socket.engineio.client.transports.Polling.pause(Unknown Source)
   at io.socket.engineio.client.transports.PollingXHR$5$1.run(Unknown Source)
   at io.socket.thread.EventThread$2.run(Unknown Source)
   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
   at java.lang.Thread.run(Thread.java:762)

我在 node.js 后端使用 1.7.4 版,socket.io java client 的 0.9.0 版。我尝试了很多方法来摆脱这个异常,但似乎没有什么比在单例或服务中使用这个库更有效。

有没有人也面临这个问题?

如果您需要更多项目代码示例或想查看应用程序(在商店中),请告诉我。

这是来自 android 应用程序的示例代码:

公共类 SocketManager { 私有静态 SocketManager 实例; 私有 Socket 套接字; 公共静态 SocketManager getInstance() { if (instance == null) instance = new SocketManager(); 返回实例; } 私人 SocketManager() { 尝试 { IO.Options 选项 = 新 IO.Options(); options.forceNew = true; socket = IO.socket(ApiConstants.Routes.URL, 选项); socket.on(Socket.EVENT_CONNECT, (dataArray) -> { Log.e("SocketManager", "已连接"); JSONArray 数组 = 新 JSONArray(); array.put(Prefs.getAuthToken()); array.put(Prefs.getGroupId()); socket.emit("updateUserSocket", 数组); }); socket.on(Socket.EVENT_DISCONNECT, (dataArray) -> { Log.e("SocketManager", "断开连接"); }); socket.on(Socket.EVENT_RECONNECT, (dataArray) -> { Log.e("SocketManager", "重新连接"); }); socket.on(Socket.EVENT_ERROR, (dataArray) -> { Log.e("SocketManager", "error"); }); socket.on(Constants.SocketEvents.USER_UPDATED, (dataArray) -> { Log.e("SocketManager", "用户更新"); sendBroadcast(Constants.SocketEvents.USER_UPDATED); }); socket.on(Constants.SocketEvents.USER_SELF_REMOVED, (dataArray) -> { Log.e("SocketManager", "用户自行删除"); sendBroadcast(Constants.SocketEvents.USER_SELF_REMOVED); }); socket.on(Constants.SocketEvents.START_GAME, (dataArray) -> { Log.e("SocketManager", "开始游戏"); sendBroadcast(Constants.SocketEvents.START_GAME); }); socket.on(Constants.SocketEvents.START_VOTING, (dataArray) -> { Log.e("SocketManager", "开始投票"); sendBroadcast(Constants.SocketEvents.START_VOTING); }); socket.on(Constants.SocketEvents.GROUP_DELETED, (dataArray) -> { Log.e("SocketManager", "组已删除"); sendBroadcast(Constants.SocketEvents.GROUP_DELETED); }); socket.on(Constants.SocketEvents.UPDATE_GROUP, (dataArray) -> { Log.e("SocketManager", "更新组"); sendBroadcast(Constants.SocketEvents.UPDATE_GROUP); }); socket.on(Constants.SocketEvents.GAME_P1, (dataArray) -> { Log.e("SocketManager", "game p1"); sendBroadcast(Constants.SocketEvents.GAME_P1); }); socket.on(Constants.SocketEvents.GAME_P2, (dataArray) -> { Log.e("SocketManager", "game p2"); sendBroadcast(Constants.SocketEvents.GAME_P2); }); socket.on(Constants.SocketEvents.GAME_P3, (dataArray) -> { Log.e("SocketManager", "game p3"); sendBroadcast(Constants.SocketEvents.GAME_P3); }); socket.on(Constants.SocketEvents.GAME_P4, (dataArray) -> { Log.e("SocketManager", "game p4"); sendBroadcast(Constants.SocketEvents.GAME_P4); }); } 捕捉(URISyntaxException e){ e.printStackTrace(); } } 私人无效发送广播(字符串事件){ 意图意图 = 新意图(事件); LocalBroadcastManager.getInstance(MyApp.getContext()).sendBroadcast(intent); } 公共无效连接(){ 如果(套接字!= null){ socket.connect(); } } 公共无效断开(){ 如果(套接字!= null){ socket.disconnect(); } } }

【问题讨论】:

  • 安卓应用是原生的吗?
  • Jep,全本地人
  • 能否分享一下代码,此时显示异常
  • 看起来异常来自库本身。但我会更新我的问题,向您展示我在我的 android 应用程序中用于 socket.io 的代码。
  • 在 io.socket.client.Socket.onevent(Unknown Source) 可能有一个参数是未知的。

标签: java android socket.io


【解决方案1】:

通过查看库的源代码,我得出的结论是抛出异常的代码是这样的:

    if (this.connected) {
        if (args.isEmpty()) return;
        String event = args.remove(0).toString();  // HERE
        super.emit(event, args.toArray());
    } else {
        this.receiveBuffer.add(args);
    }

根据上下文,客户端似乎收到了一个 JSON 数组,其第一个元素是 null。所以也许问题是这段代码的结果:

    JSONArray array = new JSONArray();
    array.put(Prefs.getAuthToken());
    array.put(Prefs.getGroupId());
    socket.emit("updateUserSocket", array);

使用null 身份验证令牌运行。


但这有一些可疑之处。堆栈跟踪清楚地表明 Socket.open 正在调用 Socket.connect。但是根据客户端库 0.9.0 版本的源代码,这是不可能的。自己看:

你确定你使用的是那个版本吗?

有一种可能性:当您针对 0.9.0 版本进行编译时,也许您的一些用户使用的版本与已发布的源代码不匹配?

【讨论】:

  • 感谢您的回答!是的,我确定我使用的是 0.9.0 版本,并且我知道有些用户使用的是旧版本的应用程序,其中库的版本是另一个版本,但在我的分析工具中,我可以清楚地看到面临此问题的用户正在使用该应用程序的最新版本。我会尝试确保 Prefs.getAuthToken() 现在不返回 null。
  • 那么你如何解释stacktrace和源代码的不一致呢?
  • 我不知道为什么会这样。也只有大约 10% 的用户有这个问题。在 build.gradle 中: implementation('io.socket:socket.io-client:0.9.0')
  • 我不是要求解释它是如何发生的。我质疑它是否会发生。或者可能是您向我们展示的堆栈跟踪的准确性。
  • 如果我知道发生这种情况的原因,我可以解决这个问题,但我没有。我向您展示的堆栈跟踪来自 Crashlytics。我找到该异常原因的问题是我无法重现它,无论是使用模拟器还是真实设备。
【解决方案2】:

我不确定,但可能的原因是您的服务器在您更改首选项后断开连接(重新启动?)。我做了一个解决方法,以消除类似下面的错误。

socket.emit("updateUserSocket", array);
            socket.disconnect();
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    socket.connect();
                }
            }, 500);

如果您知道受此首选项更改影响的特定事件,您可以禁用并重新启动事件处理程序。在您的情况下,它可能是:

socket.off(Constants.SocketEvents.USER_UPDATED, yourEmitterListener);
socket.emit("updateUserSocket", array);
    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            socket.on(Constants.SocketEvents.USER_UPDATED, yourEmitterListener);
        }
    }, 500); 

【讨论】:

    猜你喜欢
    • 2021-04-22
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多