native-bridge-js

1.0.3 • Public • Published

native-bridge-js

npm version License npm downloads minified size

🌉 A lightweight JavaScript bridge for bi-directional communication between web apps and native apps (iOS/Android) via WebView.

Supports:

  • call() – Call native methods (Promise-based)
  • on() – Listen to native events (e.g., GPS, push)
  • Cross-platform: iOS & Android
  • Zero dependencies
  • Works with React, Vue, vanilla JS

📦 Installation

npm install native-bridge-js

In Your Web App (JavaScript)

import nativeBridge from 'native-bridge-js';

// 1. Call native method
nativeBridge.call('requestLocation')
  .then(location => console.log('📍', location))
  .catch(err => console.error('❌', err));

// 2. Listen to real-time events
nativeBridge.on('batteryUpdate', (data) => {
  console.log(`🔋 ${data.level}% charged`);
});

// 3. Send data to native
nativeBridge.send('logEvent', { name: 'profile_view' });

// 4. Register a custom command (Command Pattern)
nativeBridge.registerCommand('sayHello', (name) => `Hello, ${name}!`);

// 5. Execute a registered command
const greeting = nativeBridge.executeCommand('sayHello', 'World');
console.log(greeting); // "Hello, World!"

// 6. Unregister a command
nativeBridge.unregisterCommand('sayHello');

Command Pattern API

The command pattern allows you to register, execute, and unregister custom commands on the bridge instance:

  • registerCommand(commandName, handler) – Register a command handler function.
  • executeCommand(commandName, ...args) – Execute a registered command with arguments.
  • unregisterCommand(commandName) – Remove a command handler.

This is useful for modular, decoupled logic and advanced integrations.

Native App: Sample Integration Code

iOS Webview (Swift)

  1. Setup WebView
import WebKit
class WebViewController: UIViewController, WKScriptMessageHandler {
    var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Configure WebView
        let config = WKWebViewConfiguration()
        config.userContentController.add(self, name: "NativeBridge")
        
        webView = WKWebView(frame: view.bounds, configuration: config)
        view.addSubview(webView)

        // Load your web app
        if let url = Bundle.main.url(forResource: "index", withExtension: "html") {
            webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent())
        }
    }
}
  1. Handle Messages from JS
func userContentController(_ controller: WKUserContentController, didReceive message: WKScriptMessage) {
    guard let body = message.body as? [String: Any],
          let method = body["method"] as? String,
          let callbackId = body["callbackId"] as? Int else { return }

    switch method {
    case "requestLocation":
        let response = ["callbackId": callbackId, "data": ["lat": 37.7749, "lng": -122.4194]]
        executeJs("window.NativeBridge(\(toJson(response)!))")

    case "share":
        if let text = (body["data"] as? [String: Any])?["text"] as? String {
            showShareSheet(text)
        }

    default:
        let error = ["callbackId": callbackId, "error": "Unknown method"]
        executeJs("window.NativeBridge(\(toJson(error)!))")
    }
}
  1. Helper Functions
private func executeJs(_ js: String) {
    webView.evaluateJavaScript(js) { _, error in
        if let error = error {
            print("JS Error: $error)")
        }
    }
}

private func toJson(_ dict: [String: Any]) -> String? {
    guard let data = try? JSONSerialization.data(withJSONObject: dict),
          let str = String( data, encoding: .utf8) else { return nil }
    return str
}

private func showShareSheet(_ text: String) {
    let activity = UIActivityViewController(activityItems: [text], applicationActivities: nil)
    present(activity, animated: true)
}
  1. Push Events to Web
func sendBatteryUpdate(level: Int) {
    let event = ["method": "batteryLevel", "data": ["level": level]]
    executeJs("window.NativeBridge(\(toJson(event)!))")
}
  1. Then in JS:
nativeBridge.on('batteryLevel', (data) => {
  console.log(`🔋 ${data.level}%`);
});

Android (Kotlin) – WebView

  1. Setup WebView
class WebActivity : AppCompatActivity() {
    private lateinit var webView: WebView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        webView = WebView(this)
        setContentView(webView)
        webView.settings.javaScriptEnabled = true
        webView.addJavascriptInterface(NativeBridgeInterface(), "AndroidBridge")
        webView.loadUrl("file:///android_asset/index.html")
    }
}
  1. Handle JS Messages
@Suppress("unused")
inner class NativeBridgeInterface {

    @JavascriptInterface
    fun postMessage(jsonString: String) {
        try {
            val json = JSONObject(jsonString)
            val method = json.getString("method")
            val callbackId = json.getInt("callbackId")

            when (method) {
                "requestLocation" -> {
                    val data = JSONObject().apply {
                        put("lat", 37.7749)
                        put("lng", -122.4194)
                    }
                    val response = JSONObject().apply {
                        put("callbackId", callbackId)
                        put("data", data)
                    }
                    runJs("window.NativeBridge($response)")
                }

                "share" -> {
                    val text = json.getJSONObject("data").getString("text")
                    shareText(text)
                }

                else -> {
                    val error = JSONObject().apply {
                        put("callbackId", callbackId)
                        put("error", "Unknown method: $method")
                    }
                    runJs("window.NativeBridge($error)")
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}
  1. Helper Functions
private fun runJs(js: String) {
    webView.evaluateJavascript(js, null)
}

private fun shareText(text: String) {
    val intent = Intent(Intent.ACTION_SEND).apply {
        type = "text/plain"
        putExtra(Intent.EXTRA_TEXT, text)
    }
    startActivity(Intent.createChooser(intent, "Share"))
}
  1. Push Events to Web
private fun sendLocationUpdate(lat: Double, lng: Double) {
    val js = """
        window.NativeBridge({
            "method": "locationUpdate",
            "data": { "lat": $lat, "lng": $lng }
        })
    """.trimIndent()
    webView.evaluateJavascript(js, null)
}
  1. Then in JS:
nativeBridge.on('locationUpdate', (loc) => {
  console.log('📍', loc.lat, loc.lng);
});

Package Sidebar

Install

npm i native-bridge-js

Weekly Downloads

95

Version

1.0.3

License

MIT

Unpacked Size

61.5 kB

Total Files

8

Last publish

Collaborators

  • kosalpen