如何从node.js服务器向Android应用程序发送消息?

时间:2017-01-17 02:23:29

标签: javascript java android node.js

我试图制作一个简单的应用程序。那就是当我在android应用程序中的edittext中写一个单词,如“Hi”,然后android app发送消息“Hi”到node.js服务器和node.js服务器发送消息“你已成功发送”到Android应用程序。这只是一个例子,实际上我的对象是android向服务器发送数据(消息),并从服务器接收另一个数据(消息)。

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

android所说的是“java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'void android.app.Activity.runOnUiThread(java.lang.Runnable)'”..

昨天,没有发生此错误,发生了其他错误。 “无法将字符串强制转换为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因为我不是英语,我不擅长英语..语法和写作技巧会有很多问题。谢谢理解...

1 个答案:

答案 0 :(得分: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方法如果从Subscriber类抛出异常。

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

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

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