IonicFramework v8 cannot use WebSocket correctly in Android. Error code 1006, but it runs normally in Chrome

useEffect(() => {
    const ws = new WebSocket("ws://192.168.2.174:9090");

    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      console.log(data);
    };

    ws.onopen = () => {
      console.log("WebSocket 连接已打开");
    }

    ws.onclose = () => {
      console.log("WebSocket 连接已关闭");
    }

    ws.onerror = (error) => {
      console.log("WebSocket 连接出错", error);
    }

    return () => {
      ws.close();
    };
  }, [])

capacitor.config.ts

import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'io.ionic.starter',
  appName: 'myApp',
  webDir: 'dist',
  plugins: {},
  server: {
    androidScheme: "http",
  }
};

export default config;

package.json

{
  "name": "myApp",
  "private": true,
  "version": "0.0.1",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "test.e2e": "cypress run",
    "test.unit": "vitest",
    "lint": "eslint"
  },
  "dependencies": {
    "@capacitor/android": "7.2.0",
    "@capacitor/app": "7.0.1",
    "@capacitor/browser": "^7.0.1",
    "@capacitor/core": "7.2.0",
    "@capacitor/haptics": "7.0.1",
    "@capacitor/keyboard": "7.0.1",
    "@capacitor/status-bar": "7.0.1",
    "@ionic/react": "^8.5.0",
    "@ionic/react-router": "^8.5.0",
    "@types/react-router": "^5.1.20",
    "@types/react-router-dom": "^5.3.3",
    "ionicons": "^7.4.0",
    "react": "19.0.0",
    "react-dom": "19.0.0",
    "react-router": "^5.3.4",
    "react-router-dom": "^5.3.4",
    "ros2d": "github:Neoplanetz/ros2djs-ros2",
    "ros3d": "^1.1.0",
    "roslib": "^1.4.1",
    "vconsole": "^3.15.1",
    "zustand": "^5.0.5"
  },
  "devDependencies": {
    "@capacitor/cli": "7.2.0",
    "@testing-library/dom": ">=7.21.4",
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^16.2.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/react": "19.0.10",
    "@types/react-dom": "19.0.4",
    "@types/roslib": "^1.3.5",
    "@vitejs/plugin-legacy": "^5.0.0",
    "@vitejs/plugin-react": "^4.0.1",
    "cypress": "^13.5.0",
    "eslint": "^9.20.1",
    "eslint-plugin-react": "^7.32.2",
    "eslint-plugin-react-hooks": "^5.1.0",
    "eslint-plugin-react-refresh": "^0.4.19",
    "globals": "^15.15.0",
    "jsdom": "^22.1.0",
    "terser": "^5.4.0",
    "typescript": "^5.1.6",
    "typescript-eslint": "^8.24.0",
    "vite": "~5.2.0",
    "vitest": "^0.34.6"
  },
  "description": "An Ionic project"
}

From what I see in your screenshots, it is working on Android but not Chrome? Your title says it is working in Chrome :thinking:

Thank you for your answer! The first image is taken from an Android phone, and the second image is taken from Chrome. The fact is that websocket cannot be linked in Android, but it can be in Chrome. They are the same set of code. What shall I do?

I have found a solution. Add android:usesCleartextTraffic="true" to AndroidManifest.xml . See here and here

But now my process is that after executing ionic cap sync, ionic cap sync will regenerate the AndroidManifest.xml file, which contains:

<?xml version='1.0' encoding='utf-8'?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:amazon="http://schemas.amazon.com/apk/res/android">
<application  >

</application>

</manifest>

Then I need to manually add android:usesCleartextTraffic="true". Where can I directly configure the content of AndroidManifest.xml?

When you run ionic cap run android -l for debugging, usesCleartextTraffic gets auto added to the manifest.

For production, you should be using wss.

But, the capacitor.config.ts has an option under server.cleartext for debugging purposes too. See the notes about it here - Capacitor Configuration | Capacitor Documentation cap run mentioned above actually adds this temporarily which in turn configures the manifest.

You can also set cleartext for specific hosts. See Unable to carryout HTTP post on Android - #2 by twestrick