私はAndroidアプリをsocket.ioチャットサーバーに接続するのに問題があります。Gottoxが作成したsocket.io-Java-clientを使用しています。 https://github.com/Gottox/socket.io-Java-client
サーバーはポート7000上でローカルに実行されます。Androidエミュレーターを使用しているため、10.0.2.2:7000を使用してサーバーにアクセスしています。
助けていただければ幸いです。SSLの経験はあまりありません。実用的なソリューションが見つかった場合は、それも投稿します。
Node.jsサーバー
var express = require('express');
var app = express();
var server = require('http').createServer(app).listen(7000);
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(client){
client.on('message', function(err, msg){
client.broadcast.emit('message', msg);
});
});
package.json
{
"name": "simplechat",
"version": "0.0.1",
"main": "app.js",
"dependencies": {
"express" : "~4.0.0",
"socket.io" : "~0.9.13"
}
}
Android:SendMessageActivity
public class SendMessageActivity extends Activity {
private static final String SERVER_ADDRESS = "https://10.0.2.2:7000";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_send_message);
System.out.println("Sever: " + SERVER_ADDRESS);
try {
SocketIO socket = new SocketIO(new URL(SERVER_ADDRESS), new IOCallback() {
@Override
public void onDisconnect() {
System.out.println("disconnected");
}
@Override
public void onConnect() {
System.out.println("connected");
}
@Override
public void onMessage(String s, IOAcknowledge ioAcknowledge) {
}
@Override
public void onMessage(JSONObject jsonObject, IOAcknowledge ioAcknowledge) {
}
@Override
public void on(String event, IOAcknowledge ioAcknowledge, Object... objects) {
}
@Override
public void onError(SocketIOException e) {
e.printStackTrace();
}
});
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
Androidの許可
<uses-permission
Android:name="Android.permission.INTERNET">
</uses-permission>
エラーコード
08-09 16:07:28.224 8411-8441/com.example.puma.chatexample W/System.err﹕ io.socket.SocketIOException: Error while handshaking
08-09 16:07:28.225 8411-8441/com.example.puma.chatexample W/System.err﹕ at io.socket.IOConnection.handshake(IOConnection.Java:322)
08-09 16:07:28.225 8411-8441/com.example.puma.chatexample W/System.err﹕ at io.socket.IOConnection.access$600(IOConnection.Java:39)
08-09 16:07:28.225 8411-8441/com.example.puma.chatexample W/System.err﹕ at io.socket.IOConnection$ConnectThread.run(IOConnection.Java:199)
08-09 16:07:28.226 8411-8441/com.example.puma.chatexample W/System.err﹕ Caused by: Java.lang.NullPointerException: Attempt to invoke virtual method 'javax.net.ssl.SSLSocketFactory javax.net.ssl.SSLContext.getSocketFactory()' on a null object reference
08-09 16:07:28.226 8411-8441/com.example.puma.chatexample W/System.err﹕ at io.socket.IOConnection.handshake(IOConnection.Java:302)
08-09 16:07:28.227 8411-8441/com.example.puma.chatexample W/System.err﹕ ... 2 more
実際に問題を解決しました。 PCのローカルIP http://192.168.0.xxx:70 を使用し、アプリはエミュレーターからチャットサーバーに接続できました。なぜこれが機能するのかわかりませんが、将来誰かを助けるかもしれません:)
更新:
これが私がプロジェクトを構造化した方法です。ソケット接続を処理するシングルトンクラスを作成しましたAndroid side(サービスとしてもできます)。メッセージを受信すると、シングルトンクラスはアプリの他の部分にインテントをブロードキャストします。その後、関連するアクティビティでブロードキャストレシーバーがインテントを取得します。
Androidサイド(シングルトン):
public class SocketSingleton {
private static SocketSingleton instance;
private static final String SERVER_ADDRESS = "http://1.2.3.4:1234";
private SocketIO socket;
private Context context;
public static SocketSingleton get(Context context){
if(instance == null){
instance = getSync(context);
}
instance.context = context;
return instance;
}
public static synchronized SocketSingleton getSync(Context context){
if (instance == null) {
instance = new SocketSingleton(context);
}
return instance;
}
public SocketIO getSocket(){
return this.socket;
}
private SocketSingleton(Context context){
this.context = context;
this.socket = getChatServerSocket();
this.friends = new ArrayList<Friend>();
}
private SocketIO getChatServerSocket(){
try {
SocketIO socket = new SocketIO(new URL(SERVER_ADDRESS), new IOCallback() {
@Override
public void onDisconnect() {
System.out.println("disconnected");
}
@Override
public void onConnect() {
System.out.println("connected");
}
@Override
public void on(String event, IOAcknowledge ioAcknowledge, Object... objects) {
if (event.equals("chatMessage")) {
JSONObject json = (JSONObject) objects[0];
ChatMessage chatMessage = new ChatMessage(json);
Intent intent = new Intent();
intent.setAction("newChatMessage");
intent.putExtra("chatMessage", chatMessage);
context.sendBroadcast(intent);
}
}
@Override
public void onError(SocketIOException e) {
e.printStackTrace();
}
});
return socket;
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
return null;
}
}
Android Side(activity):
public class ChatActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
IntentFilter newChatMessageFilter = new IntentFilter("newChatMessage");
this.registerReceiver(new MessageReceiver(), newChatMessageFilter);
...
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent){
final ChatMessage chatMessage =(ChatMessage) intent.getExtras().get("chatMessage");
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter.add(chatMessage);
mAdapter.notifyDataSetChanged();
}
});
}
}
}
サーバー側:
var express = require('express');
var app = express();
var server = require('http').createServer(app).listen(1234);
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(client){
console.log("client connected: " + client.id);
client.on("sendTo", function(chatMessage){
console.log("Message From: " + chatMessage.fromName);
console.log("Message To: " + chatMessage.toName);
io.sockets.socket(chatMessage.toClientID).emit("chatMessage", {"fromName" : chatMessage.fromName,
"toName" : chatMessage.toName,
"toClientID" : chatMessage.toClientID,
"msg" : chatMessage.msg});
});
});
私はこれがOPの投稿に本当に答えていないことを知っていますが、興味があるかもしれない人のために、これはあなたのAndroidとNode.jsサーバーと通信するために作ったチュートリアルです-追加のライブラリなし-:
https://causeyourestuck.io/2016/04/27/node-js-Android-tcpip/
これは、最後にどのように見えるかの前兆です。
Client socket = new Client("192.168.0.8", 1234);
socket.setOnEventOccurred(new Client.OnEventOccurred() {
@Override
public void onMessage(String message) {
}
@Override
public void onConnected(Socket socket) {
socket.send("Hello World!");
socket.disconnect();
}
@Override
public void onDisconnected(Socket socket, String message) {
}
});
socket.connect();
Pumaは、SocketIOを使用してソケット接続を実装する方法について既に回答しています。これには貢献する新しいものは何もありません。ただし、Socket.ioのJavaライブラリの実装も紹介するため、仲間の初心者を支援する試みです。
Socket.IOには、独自のJava Github の実装があり、これに従ってAndroid/Java用のソケットアプリケーションを作成できます。
これをビルドに含めますgradle
compile ('io.socket:socket.io-client:0.8.3') {
// excluding org.json which is provided by Android
exclude group: 'org.json', module: 'json'
}
アプリで許可を与える:
<uses-permission Android:name="Android.permission.INTERNET" />
Androidコード:コードの構造は、Nodeでコーディングする方法と似ています。 socket.onのmessageは、ノードのsocket.on( 'message'、...)に似ています
import io.socket.client.Socket; import io.socket.client.IO; import io.socket.emitter.Emitter; final Socket socket; try{ socket = IO.socket("http://192.168.1.1:8080"); socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() { @Override public void call(Object... args) { socket.emit("message", "hi"); socket.disconnect(); } }).on("message", new Emitter.Listener() { //message is the keyword for communication exchanges @Override public void call(Object... args) { socket.emit("message", "hi"); } }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() { @Override public void call(Object... args) {} }); socket.connect(); } catch(Exception e){ }
Socket.ioを使用して通常のソケットを作成します
私が聞いたように、あなたはエミュレータネットワークがあなたのPCのものと異なっています。変更できる場合は、PCと同じネットワークに接続されている実際の電話でこれを試してください。
おそらくping 10.0.2.2
エミュレータから、またはPCからエミュレータへの逆方向。