Skip to content

feat: ✨ Native Websocket Plugin (uses okhttp) #1335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

UnschooledGamer
Copy link
Collaborator

@UnschooledGamer UnschooledGamer commented May 30, 2025

Adds Native Websocket Cordova Plugin (using okhttp)

Important

plugin initialise(using okhttp singleton client) & destroy(closing okhttp builder clients) are to be completed. While the plugin is functional but those methods are important for plugin lifecycles. Also, custom headers support to be added.

Features

  • ✅ WebSocket API-like interface
  • ✅ Event support: onopen, onmessage, onerror, onclose
  • extensions and readyState properties
  • listClients() to list active connections
  • ✅ Support for protocols
  • listClients() to list active connections
  • ✅ Compatible with Cordova for Android
Usage

Usage

Import

const WebSocketPlugin = cordova.websocket;

Connect to WebSocket

WebSocketPlugin.connect("wss://example.com/socket", ["protocol1", "protocol2"], customHeaders)
  .then(ws => {
    ws.onopen = (e) => console.log("Connected!", e);
    ws.onmessage = (e) => console.log("Message:", e.data);
    ws.onerror = (e) => console.error("Error:", e);
    ws.onclose = (e) => console.log("Closed:", e);

    ws.send("Hello from Cordova!");
    ws.close();
  })
  .catch(err => console.error("WebSocket connection failed:", err));

API Reference

Methods

  • WebSocketPlugin.connect(url, protocols, headers)

    • Connects to a WebSocket server.
    • url: The WebSocket server URL.
    • protocols: (Optional) An array of subprotocol strings.
    • headers (object, optional): Custom headers as key-value pairs.
    • Returns: A Promise that resolves to a WebSocketInstance.
  • WebSocketPlugin.listClients()

    • Lists all stored webSocket instance IDs.
    • Returns: Promisethat resolves to an array of instanceId strings.
  • WebSocketPlugin.send(instanceId, message)

    • same as WebSocketInstance.send(message) but needs instanceId.
    • Returns: Promise that resolves.
  • WebSocketPlugin.close(instanceId, code, reason)

    • same as WebSocketInstance.close(code, reason) but needs instanceId.
    • Returns: Promise that resolves.
  • WebSocketInstance.send(message)

    • Sends a message to the server.
    • Throws an error if the connection is not open.
  • WebSocketInstance.close(code, reason)

    • Closes the connection.
    • code: (Optional) If unspecified, a close code for the connection is automatically set: to 1000 for a normal closure, or otherwise to another standard value in the range 1001-1015 that indicates the actual reason the connection was closed.
    • reason: A string providing a custom WebSocket connection close reason (a concise human-readable prose explanation for the closure). The value must be no longer than 123 bytes (encoded in UTF-8).

Properties of WebSocketInstance

  • onopen: Event listener for connection open.

  • onmessage: Event listener for messages received.

  • onclose: Event listener for connection close.

  • onerror: Event listener for errors.

  • readyState: (number) The state of the connection.

    • 0 (CONNECTING): Socket created, not yet open.
    • 1 (OPEN): Connection is open and ready.
    • 2 (CLOSING): Connection is closing.
    • 3 (CLOSED): Connection is closed or couldn't be opened.
  • extensions: (string) Extensions negotiated by the server (usually empty or a list).


@UnschooledGamer UnschooledGamer self-assigned this May 30, 2025
@UnschooledGamer UnschooledGamer added the enhancement New feature or request label May 30, 2025
@bajrangCoder bajrangCoder requested a review from Copilot May 30, 2025 16:10
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Introduces a native WebSocket Cordova plugin for Android using OkHttp, providing a JavaScript WebSocket-like interface.

  • Added a JS bridge (www/websocket.js) implementing connect() and WebSocketInstance
  • Implemented Cordova plugin classes (WebSocketPlugin.java, WebSocketInstance.java) using OkHttp for real WebSocket support
  • Updated plugin.xml, plugin package.json, root package.json, and README.md for installation and usage

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/plugins/websocket/www/websocket.js JS API: connect() returns WebSocketInstance and routes events
src/plugins/websocket/src/android/WebSocketPlugin.java CordovaPlugin routes actions (connect, send, close, listener)
src/plugins/websocket/src/android/WebSocketInstance.java OkHttp WebSocket listener with event marshaling to JS
src/plugins/websocket/plugin.xml Registers JS module and Android sources, declares OkHttp framework
src/plugins/websocket/package.json Plugin metadata, keywords, and license
src/plugins/websocket/README.md Usage guide and API reference
package.json Added plugin reference under cordovaPlugins and project deps
Comments suppressed due to low confidence (1)

src/plugins/websocket/src/android/WebSocketInstance.java:15

  • [nitpick] Core WebSocketInstance behavior (e.g., event callbacks and state transitions) lacks tests. Consider adding unit or integration tests to cover the listener methods.
public class WebSocketInstance extends WebSocketListener {

import java.util.HashMap;
import java.util.UUID;

// @TODO: plugin init & plugin destroy(closing okhttp clients) lifecycles.
Copy link
Preview

Copilot AI May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugin init and destroy lifecycles are marked as TODO but not implemented. Implement proper initialization and cleanup (e.g., closing OkHttp clients) to prevent resource leaks.

Copilot uses AI. Check for mistakes.

this.onerror = null;
this.url = url;

exec((event) => {
Copy link
Preview

Copilot AI May 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing null as the error callback to exec may hide native errors. Consider providing an error handler to propagate failures back to JavaScript.

Copilot uses AI. Check for mistakes.

@UnschooledGamer
Copy link
Collaborator Author

+1, copilot suggestions seem ok-ish. I'll add them by testing out.

UnschooledGamer and others added 3 commits May 31, 2025 12:21
… functionality

- Updated `WebSocketPlugin.connect` to accept custom headers.
- Enhanced `WebSocketInstance.close` method to allow specifying close code and reason.
- Added `WebSocketPlugin.listClients` method to list active WebSocket instances.
- Updated JavaScript interface to support new features and improved documentation.
…ging and error handling

- Updated `WebSocketInstance.send` and `close` methods to include detailed logging for better debugging.
- Modified `WebSocketPlugin` to handle close operation errors and provide appropriate feedback to the callback context.
- Ensured proper binding of event handlers in the JavaScript WebSocket interface for consistent context handling.
@bajrangCoder bajrangCoder requested a review from Copilot May 31, 2025 16:11
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds a native WebSocket Cordova plugin for Android using OkHttp, exposing a JS API that mimics the browser WebSocket interface and managing connections natively.

  • Introduces a JS module (websocket.js) with connect, send, close, and listClients methods plus event handlers.
  • Implements WebSocketPlugin.java and WebSocketInstance.java on Android, leveraging OkHttp for actual socket work.
  • Updates plugin.xml, package.json, and README.md for plugin registration, metadata, and documentation.

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/plugins/websocket/www/websocket.js JS wrapper providing promise-based connect, send, close, listClients
src/plugins/websocket/src/android/WebSocketPlugin.java CordovaPlugin execute logic, instance map, lifecycle management
src/plugins/websocket/src/android/WebSocketInstance.java OkHttp WebSocketListener handling events and sending to JS
src/plugins/websocket/plugin.xml Plugin manifest, Android feature and source-file declarations
src/plugins/websocket/package.json Plugin npm metadata and cordova integration settings
src/plugins/websocket/README.md Usage instructions and API reference
package.json Adds plugin to host app’s dependencies
Comments suppressed due to low confidence (2)

src/plugins/websocket/www/websocket.js:68

  • [nitpick] The exported 'send' and 'close' helper functions shadow the instance methods with the same names. Consider renaming them (e.g., 'sendById' / 'closeById') to improve clarity.
const send = function(instanceId, message) {

src/plugins/websocket/www/websocket.js:54

  • The core API methods (connect, send, close, listClients) lack accompanying unit or integration tests. Consider adding tests to validate success and error flows.
const connect = function(url, protocols = null, headers = null) {


// TODO: plugin init & plugin destroy(closing okhttp clients) lifecycles. (✅)
public class WebSocketPlugin extends CordovaPlugin {
private static final HashMap<String, WebSocketInstance> instances = new HashMap<>();
Copy link
Preview

Copilot AI May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The static HashMap 'instances' is not thread-safe and may lead to race conditions under concurrent access. Consider switching to a ConcurrentHashMap or synchronizing access.

Copilot uses AI. Check for mistakes.

<plugin id="cordova-plugin-websocket" version="0.0.1" xmlns="http://apache.org/cordova/ns/plugins/1.0">
<name>cordova-plugin-websocket</name>
<description>Cordova Websocket</description>
<license>MIT</license>
Copy link
Preview

Copilot AI May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The license in plugin.xml is set to MIT, but package.json specifies Apache-2.0. Please align the license entries to avoid confusion for consumers.

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants