【问题标题】:How to send message from node.js server to Android app?如何将消息从 node.js 服务器发送到 Android 应用程序?
【发布时间】:2017-01-17 02:23:28
【问题描述】:

我正在尝试制作一个简单的应用程序。那就是当我在 android 应用程序中的 edittext 处写一个单词时,例如“Hi”,然后 android 应用程序向 node.js 服务器发送消息“Hi”,node.js 服务器向 android 应用程序发送消息“Hi has sent successflly”。这只是一个例子,实际上我的对象是android向服务器发送数据(消息),并从服务器接收另一个数据(消息)。

问题是这样的。当我在android应用程序上写一个词并按下按钮时,消息传输成功(我可以通过node.js的控制台确认)。但我无法从 node.js 向 android 发送消息 .. 当我按下发送按钮时,我的 android 应用程序关闭了..

android 说的是“java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Activity.runOnUiThread(java.lang.Runnable)' on an null object reference”..

昨天,这个错误没有发生,又发生了另一个错误。 “无法将字符串转换为 JSONObject。”

我会告诉你我的代码。

服务器端(Node.js)

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = 12000;

app.get('/', function(req, res) {
    res.sendFile('index.html');
})

io.on('connection', function(socket) {
    console.log('Android device has been connected');
    socket.on('message', function(data) {
        console.log('message from Android : ' + data);

        Object.keys(io.sockets.sockets);
        Object.keys(io.sockets.sockets).forEach(function (id) {
            console.log("ID : ", id );
            io.to(id).emit('message', data);
            console.log(data + ' has sent successfully');
        })

        /*if (data != null) {
            io.emit('message', {message : data + ' has received successfully'});
        }*/
    })

    socket.on('disconnect', function() {
        console.log('Android device has been disconnected');
    })
})

http.listen(port, function() {
    console.log('Server Start at port number ' + port);
})

客户端(Android)

private Emitter.Listener handleIncomingMessages = new Emitter.Listener(){
        @Override
        public void call(final Object... args){
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    JSONObject data = (JSONObject) args[0];
                    String message;
                    try {
                        message = data.getString("text").toString();
                        Log.i("result", message);
                        addMessage(message);

                    } catch (JSONException e) {
                        Log.e("result", "Error : JSONException");
                        return;
                    } catch (ClassCastException e) {
                        Log.e("result", "Error : ClassCastException");
                        e.printStackTrace();
                        return;
                    }
                }
            });
        }
    };

private void sendMessage(){
    String message = mInputMessageView.getText().toString().trim();
    mInputMessageView.setText("");
    addMessage(message);
    JSONObject sendText = new JSONObject();
    try{
        sendText.put("text", message);
        socket.emit("message", message);
    }catch(JSONException e){

    }
}

private void addMessage(String message) {

    mMessages.add(new Message.Builder(Message.TYPE_MESSAGE)
            .message(message).build());
    // mAdapter = new MessageAdapter(mMessages);
    mAdapter = new MessageAdapter( mMessages);
    mAdapter.notifyItemInserted(0);
    scrollToBottom();
}

private void scrollToBottom() {
    mMessagesView.scrollToPosition(mAdapter.getItemCount() - 1);
}

我已经搜索过其他人问过的类似问题,但它没有给我解决方案。请帮我。感谢您阅读长问题。

p.s 因为我不会说英语,我不擅长英语.. 语法和写作技巧会有很多问题。感谢理解...

【问题讨论】:

  • 您是否尝试过单步执行代码?调试器?在战略位置打印价值?大多数编码都在弄清楚为什么事情不起作用,所以我敦促你学习这项技能。
  • 是的..我真的很想学习调试技能..并且我正在学习调试技能..但是我没有太多时间..因为我必须在两周内完成这项任务。其实我问的只是项目的一部分。。所以我问了。。不过多亏了你的建议
  • 那么,您不会尝试简单地打印出战略位置的值来测试您的假设吗?课程作业是为了促进学习,并表明您理解材料。这里没有人会做你的功课。表明您已经做出了一些努力并提出了与特定问题相关的特定问题。这是一个开始:ericlippert.com/2014/03/05/how-to-debug-small-programs

标签: javascript java android node.js


【解决方案1】:

发生这种情况的原因是因为方法 getActivity() 返回 null。如果在片段与活动分离或活动不再可见后在片段上运行它,则可能会发生这种情况。我会先做一个正常的空检查:

Activity activity = getActivity();
if(activity != null) {
    activity.runOnUiThread(new Runnable() {...}
}

我不熟悉 socket.emit() 方法,但它可能会引发网络异常,因为它在 UI 线程上运行,并且不允许您这样做。如果您想在另一个线程上执行此操作,我建议使用 RxJava/RxAndroid。

如果你想做网络操作,就这样使用它:

Observable
    .fromRunnable(new Runnable {
       void run() {
          // here do your work
       }
     })
    .subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Subscriber<Void>() {
        @Override
        public void onCompleted() {
            // not really needed here
        }

        @Override
        public void onError(Throwable e) {
            // handle errors on UI thread
        }

        @Override
        public void onNext(Void void) {
           // do something on UI thread after run is done
        }
    });

它基本上是做什么的,它从你刚刚在单独的线程上进行的 Callable 调用方法调用,当它结束时,如果没有抛出异常,它会调用 onNext 方法,如果从订阅者类抛出异常,它会调用 onError 方法。

请注意,Response 类不是 RxJava/RxAndroid API 的一部分,您可以根据需要创建它。你可以把它变成一个简单的 POJO 类或任何你需要的东西。如果您不需要响应,您可以使用 Runnable 而不是 Callable,它会正常工作。

为了使它工作,您需要将此依赖项添加到您的模块 Gradle 文件中:

dependencies {
    compile 'io.reactivex:rxandroid:1.2.1'
    compile 'io.reactivex:rxjava:1.1.6'
}

【讨论】:

    猜你喜欢
    • 2019-01-16
    • 2016-05-14
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多