web-dev-qa-db-ja.com

AndroidでSocket.IOを使用すると、常にXHRポーリングエラーが返される

Androidアプリを作成しています。このアプリは、node.jsサーバーで実行されているSocket.IOインスタンスに接続する必要があります。

IOSデバイスを使用してインスタンスに接続してデータを送信しようとすると問題なく動作しますが、Androidデバイスを使用して接続しようとすると失敗します。

私は ネイティブJavaクライアント を使用しています。これは私がAndroid=側で使用しているコードです:

_mManager = new Manager(new URI("https://example.com"));
mSocket = mManager.socket("/users");

// socket events listeners
    mSocket.on(Socket.EVENT_CONNECTING, new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.v(TAG, "Caught EVENT_CONNECTING");
            for (Object obj : args) {
                Log.v(TAG, "Errors :: " + obj);
            }
        }
    }).on(Socket.EVENT_CONNECT, new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.v(TAG, "connected to the backend");
            Log.v(TAG, String.format("JSON Obj to emit: %s", jsonObject.toString()));
            mSocket.emit("hello_packet", jsonObject);
        }
    }).on(Socket.EVENT_RECONNECTING, new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.v(TAG, "Caught EVENT_RECONNECTING");
            for (Object obj : args) {
                Log.v(TAG, "Errors :: " + obj);
            }
        }
    }).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.v(TAG, "Socket disconnected");
        }
    }).on(Socket.EVENT_ERROR, new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.v(TAG, "Caught EVENT_ERROR");
            for (Object obj : args) {
                Log.v(TAG, "Errors :: " + obj);
            }
        }
    }).on(Socket.EVENT_CONNECT_ERROR, new Emitter.Listener() {
        @Override
        public void call(Object... args) {
            Log.v(TAG, "Caught EVENT_CONNECT_ERROR");
            for (Object obj : args) {
                Log.v(TAG, "Errors :: " + obj);
            }
        }
    });

    Log.v(TAG, "Connecting socket");
    mSocket.connect();
_

接続しようとするときはいつでも(基本的にはmSocket.connect();行になるとすぐに)ログに次の行が出力されます。

_05-07 22:41:36.684 15552-15552/com.my.app V/Main Activity: Connecting socket
05-07 22:41:36.699 15552-15858/com.my.app V/Main Activity: Caught EVENT_CONNECTING
05-07 22:41:36.926 15552-15866/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:36.926 15552-15866/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:38.189 15552-15884/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:38.189 15552-15884/com.my.app V/Main Activity: Errors :: 1
05-07 22:41:38.207 15552-15887/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:38.208 15552-15887/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:39.518 15552-15911/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:39.518 15552-15911/com.my.app V/Main Activity: Errors :: 2
05-07 22:41:39.531 15552-15915/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:39.531 15552-15915/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:41.846 15552-15949/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:41.846 15552-15949/com.my.app V/Main Activity: Errors :: 3
05-07 22:41:41.857 15552-15953/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:41.857 15552-15953/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:46.863 15552-16025/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:46.864 15552-16025/com.my.app V/Main Activity: Errors :: 4
05-07 22:41:46.879 15552-16029/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:46.879 15552-16029/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:51.883 15552-16126/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:51.883 15552-16126/com.my.app V/Main Activity: Errors :: 5
05-07 22:41:51.895 15552-16130/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:51.895 15552-16130/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:41:56.900 15552-16236/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:41:56.900 15552-16236/com.my.app V/Main Activity: Errors :: 6
05-07 22:41:56.921 15552-16240/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:41:56.921 15552-16240/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:01.927 15552-16357/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:01.927 15552-16357/com.my.app V/Main Activity: Errors :: 7
05-07 22:42:01.945 15552-16361/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:01.945 15552-16361/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:06.951 15552-16466/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:06.952 15552-16466/com.my.app V/Main Activity: Errors :: 8
05-07 22:42:06.969 15552-16470/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:06.970 15552-16470/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:11.975 15552-16545/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:11.976 15552-16545/com.my.app V/Main Activity: Errors :: 9
05-07 22:42:11.994 15552-16549/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:11.994 15552-16549/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:17.000 15552-16629/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:17.000 15552-16629/com.my.app V/Main Activity: Errors :: 10
05-07 22:42:17.012 15552-16633/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:17.012 15552-16633/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:22.017 15552-16710/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:22.017 15552-16710/com.my.app V/Main Activity: Errors :: 11
05-07 22:42:22.033 15552-16714/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:22.033 15552-16714/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:27.039 15552-16788/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:27.039 15552-16788/com.my.app V/Main Activity: Errors :: 12
05-07 22:42:27.056 15552-16792/com.my.app V/Main Activity: Caught EVENT_CONNECT_ERROR
05-07 22:42:27.056 15552-16792/com.my.app V/Main Activity: Errors :: io.socket.engineio.client.EngineIOException: xhr poll error
05-07 22:42:32.061 15552-16957/com.my.app V/Main Activity: Caught EVENT_RECONNECTING
05-07 22:42:32.062 15552-16957/com.my.app V/Main Activity: Errors :: 13
_

そのため、接続を試行した直後にxhrポーリングエラーが発生し、その後のすべての接続試行で同じ結果が得られます。

Socket.IOライブラリが使用するSSLコンテキストを調整しようとしてもうまくいきませんでしたが、SSL証明書の問題が原因である可能性があるという投稿をいくつか見ました。

Anyoenがこれを機能させるために私が何をできるかを考えているなら、それは素晴らしいことです。

情報やコードのサンプルが不足している場合はお知らせください。追加します。

16
Mor Paz

さらにテストした結果、次のことがわかりました。

  1. さまざまなイベント(EVENT_ERRORなど)が発生したときにソケットをデバッグする場合、キャッチする例外には、到達しようとしたアドレスから受信した応答コードが含まれます。
  2. 私の場合、HTTPでサーバーに到達しようとすると、到達しようとしたURLが自動的にHTTPSアドレスにリダイレクトされたため、301応答コードを受け取りました。
  3. HTTPSアドレスに到達しようとすると、401応答コードを受け取りました-つまり、私のソケットが行った要求はサーバーに到達したが、承認されませんでした-その理由は、ターゲットサーバーに基本認証があったためですオンであり、ソケット要求ヘッダーに必要な資格情報を提供していません。
  4. 必要なヘッダーを提供した後、ソケットサーバーに適切に接続できましたが、リクエストを送信すると失敗し、ソケットは再接続試行ループに戻りました-その理由は、サーバーからサーバーに送信したJSONがmy Android電話は予期された形式ではなく、サーバーはその要求を受信できませんでした。

ソケットリクエストに基本認証ヘッダーを追加するために使用したコード:

// Adding authentication headers when encountering EVENT_TRANSPORT
mSocket.io().on(Manager.EVENT_TRANSPORT, new Emitter.Listener() {
    @Override
    public void call(Object... args) {
        Transport transport = (Transport) args[0];
        // Adding headers when EVENT_REQUEST_HEADERS is called
        transport.on(Transport.EVENT_REQUEST_HEADERS, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.v(TAG, "Caught EVENT_REQUEST_HEADERS after EVENT_TRANSPORT, adding headers");
                Map<String, List<String>> mHeaders = (Map<String, List<String>>)args[0];
                mHeaders.put("Authorization", Arrays.asList("Basic bXl1c2VyOm15cGFzczEyMw=="));
            }
        });
    }
});

Socket.IOを使用しようとしたときにXHR Pollエラーが発生した場合は、ソケットサーバーへの接続が利用可能であり、正しく接続していることを確認してください。結局のところ、私の場合はすべて、基本認証を必要とするサーバーを中心に展開し、サーバーに接続するときにそれを提供しませんでした。

また、、この問題を解決しようとしているときにその解決策が少し発生したため-HTTPS経由でサーバーにアクセスしようとすると、通常特別なホスト名ベリファイアや特別な証明書マネージャは必要ありません。このようなソリューションは、アプリのセキュリティに大きな悪影響を与えるため、試して回避してください。

8
Mor Paz

これは、オプションでトランスポートを設定するのを忘れた場合にも発生します

IO.Options opts = new IO.Options();
opts.transports = new String[]{WebSocket.NAME}; //or Polling.NAME 
3

次のように、マニフェストのアプリケーションタグにこのコードを追加する必要があります。

<application 
   ... 
   Android:usesCleartextTraffic="true">
    .... 
<application/>
2
saeed shaikh

また、あなたの助成金かどうかを確認してください

<uses-permission Android:name="Android.permission.INTERNET" />

manifest.xml

また追加

<application 
   ... 
   Android:usesCleartextTraffic="true">
    .... 
<application/>
1
Ragesh D Antony

私の状況で同様の問題を確認できます。開発サーバーへのWebSocket接続をテストしています。 SSLではなく、単純なhttpです。ここに私の状況がありました:

  1. Androidスタジオシミュレーターを使用して、開発サーバーへのアプリのWebSocket接続をテストしました-接続はエラーなしで正常に行われました。
  2. テストしました。 (1)上記のシミュレーターの代わりに実際のデバイス。 "xhr poll error"メッセージで失敗しました。
  3. その後、長い時間をかけて成功しなかったため、AndroidManifest.xmlに以下を追加しました。

    <application ... Android:usesCleartextTraffic="true" ...>

私のプロジェクトは現在API 28をターゲットにしているため、"usesCleartextTraffic"のデフォルトはfalseです。今、すべてが正常に動作しています。

1
YazidEF

私はあなたのコードを使用し、まったく同じ出力を持っていましたが、あなたの解像度ではそれを解決できませんでした。私が見つけた解決策は、X秒ごとにデータを送信することでした。基本的に、送信されるデータがない場合、接続は切断されました。

承認を行う必要はありませんでした。

コードは上記のEVENT_TRANSPORT部分とまったく同じで、EVENT_CONNECTは次のとおりです。

socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            @Override
            public void call(Object... args) {
                Log.d("mylogs", "Socket: Web socket opened");

                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {

                        socket.emit("YOUR_TOPIC", "YOUR_DATA_VALUE");

                        handler.postDelayed(this, 1000);
                    }
                };
                handler.post(runnable);

            }
        })

私はこれをここに残したかったのですが、将来誰かを助けるかもしれない、信じられないかもしれませんが、これは解決するのが厄介な問題でした。「xhrポーリングエラー」は非常にあいまいで、さまざまなことが原因で発生する可能性があります。非常に多くの異なることを試した後、この簡単なコードで解決しました。

0
Ricardo Abreu