我试图制作一个简单的应用程序。那就是当我在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因为我不是英语,我不擅长英语..语法和写作技巧会有很多问题。谢谢理解...
答案 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'
}