npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

expo-nearby-connections

v1.0.0

Published

P2P connections library for Expo. Supports Android and iOS.

Downloads

13

Readme

Expo Nearby Connection Library

Introduction

The Expo Nearby Connection Library enables peer-to-peer (P2P) connections between mobile devices. It is an Expo wrapper for Android and iOS, with Android using Google's Nearby Connections API and iOS using Apple's Multipeer Connectivity framework. This library allows users to discover nearby devices, establish connections, and exchange data seamlessly.

Note: It does not yet support cross-platform P2P connections between Android and iOS devices.

Getting Started

Installation

Run the following command to install the library:

yarn add expo-nearby-connections

or you can use the expo cli to install the library:

npx expo install expo-nearby-connections

Expo Plugin

Update your app.json or app.config.ts file:

{
  "name": "Awesome Chat",
  "plugins": [
    [
      "expo-nearby-connections",
      {
        "bonjourServicesName": "awesome-chat",
        "localNetworkUsagePermissionText": "$(PRODUCT_NAME) need access to your local network to discover nearby devices"
      }
    ]
  ]
}

or you can just use the plugin without the props.

{
  "name": "Awesome Chat",
  "plugins": ["expo-nearby-connections"]
}

Setup Permissions

For now this library isn't support for permission handler yet. You can use other library to handle permissions, something like react-native-permissions. Google Nearby Connections on Android requires a few specific permissions to use the library. For more information, you can check Android's documentation.

import {
  PERMISSIONS,
  RESULTS,
  checkMultiple,
  requestMultiple,
} from "react-native-permissions";

async function checkAndRequestPermission(): Promise<boolean> {
  const permissions =
    Platform.OS === "ios"
      ? [PERMISSIONS.IOS.BLUETOOTH]
      : [
          PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION,
          PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
          PERMISSIONS.ANDROID.BLUETOOTH_ADVERTISE,
          PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
          PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
          PERMISSIONS.ANDROID.NEARBY_WIFI_DEVICES,
        ];

  const checkPermissionStatus = await checkMultiple(permissions);

  const isAllGranted = Object.values(checkPermissionStatus).every((value) => {
    return (
      value === RESULTS.GRANTED ||
      value === RESULTS.UNAVAILABLE ||
      value === RESULTS.LIMITED
    );
  });

  if (isAllGranted) {
    return true;
  }

  // Request permission
  const result = await requestMultiple(permissions);

  const requestIsGranted = Object.values(result).every((value) => {
    return (
      value === RESULTS.GRANTED ||
      value === RESULTS.UNAVAILABLE ||
      value === RESULTS.LIMITED
    );
  });

  return requestIsGranted;
}

Detailed API Usage

Constants

Strategy

Overview of connection strategies in Nearby Connections for Android.

enum Strategy {
  P2P_CLUSTER = 1,
  P2P_STAR = 2,
  P2P_POINT_TO_POINT = 3,
}

Function Handlers

startAdvertise()

Initiate devices to broadcast a connection to other devices.

function startAdvertise(
  name: string,
  strategy?: Strategy = Strategy.P2P_STAR // only for android
): Promise<string>;
import { startAdvertise } from "expo-nearby-connections";

startAdvertise("My Device Name Or ID", Strategy.P2P_STAR)
  .then((peerId) => {
    setMyPeerId(peerId);
  })
  .catch((error) => {
    console.log("Error in startAdvertise: ", error);
  });

stopAdvertise()

Stop advertising a connection.

function stopAdvertise(): Promise<void>;
import { stopAdvertise } from "expo-nearby-connections";

stopAdvertise()
  .then(() => {
    // handler after stop advertising
  })
  .catch((error) => {
    console.log("Error in stopAdvertise: ", error);
  });

startDiscovery()

Initiate devices to discover a nearby devices.

function startDiscovery(
  name: string,
  strategy?: Strategy = Strategy.P2P_STAR // only for android
): Promise<string>;
import { startDiscovery } from "expo-nearby-connections";

startDiscovery("My Device Name Or ID", Strategy.P2P_STAR)
  .then((peerId) => {
    setMyPeerId(peerId);
  })
  .catch((error) => {
    console.log("Error in startDiscovery: ", error);
  });

stopDiscovery()

Stop discovering a nearby devices.

function stopDiscovery(): Promise<void>;
import { stopDiscovery } from "expo-nearby-connections";

stopDiscovery()
  .then(() => {
    // handler after stop discovering
  })
  .catch((error) => {
    console.log("Error in stopDiscovery: ", error);
  });

requestConnection()

Request a connection to a nearby device.

function requestConnection(advertisePeerId: string): Promise<void>;
import { requestConnection } from "expo-nearby-connections";

requestConnection(advertisePeerId)
  .then(() => {
    // handler after request connection
  })
  .catch((error) => {
    console.log("Error in requestConnection: ", error);
  });

acceptConnection()

Accept a connection from a nearby device.

function acceptConnection(targetPeerId: string): Promise<void>;
import { acceptConnection } from "expo-nearby-connections";

acceptConnection(targetPeerId)
  .then(() => {
    // handler after accept connection
  })
  .catch((error) => {
    console.log("Error in acceptConnection: ", error);
  });

rejectConnection()

Reject a connection from a nearby device.

function rejectConnection(targetPeerId: string): Promise<void>;
import { rejectConnection } from "expo-nearby-connections";

rejectConnection(targetPeerId)
  .then(() => {
    // handler after reject connection
  })
  .catch((error) => {
    console.log("Error in rejectConnection: ", error);
  });

disconnect()

disconnect from a connected nearby devices.

function disconnect(
  connectedPeerId?: string // for android only
): Promise<void>;
import { disconnect } from "expo-nearby-connections";

disconnect(connectedPeerId)
  .then(() => {
    // handler after disconnect
  })
  .catch((error) => {
    console.log("Error in disconnect: ", error);
  });

sendText()

Send text to a connected nearby devices.

function sendText(connectedPeerId: string, text: string): Promise<void>;
import { sendText } from "expo-nearby-connections";

sendText(connectedPeerId, text)
  .then(() => {
    // handler after send text
  })
  .catch((error) => {
    console.log("Error in sendText: ", error);
  });

Event Handlers

onInvitationReceived()

listener for incoming invitation request connection from nearby devices.

function onInvitationReceived(
  (data: {peerId: string; name: string}) => void
): Function;
import { onInvitationReceived } from "expo-nearby-connections";

const unsubscribe = onInvitationReceived(({ peerId, name }) => {
  // handler
});

unsubscribe();

onConnected()

listener for connected to nearby devices.

function onConnected(
  (data: {peerId: string; name: string}) => void
): Function;
import { onConnected } from "expo-nearby-connections";

const unsubscribe = onConnected(({ peerId, name }) => {
  // handler
});

unsubscribe();

onDisconnected()

listener for disconnected from nearby devices.

function onDisconnected(
  (data: {peerId: string}) => void
): Function;
import { onDisconnected } from "expo-nearby-connections";

const unsubscribe = onDisconnected(({ peerId }) => {
  // handler
});

unsubscribe();

onPeerFound()

listener for found nearby devices.

function onPeerFound(
  (data: {peerId: string; name: string}) => void
): Function;
import { onPeerFound } from "expo-nearby-connections";

const unsubscribe = onPeerFound(({ peerId, name }) => {
  // handler
});

unsubscribe();

onPeerLost()

listener for lost nearby devices.

function onPeerLost(
  (data: {peerId: string}) => void
): Function;
import { onPeerLost } from "expo-nearby-connections";

const unsubscribe = onPeerLost(({ peerId }) => {
  // handler
});

unsubscribe();

onTextReceived()

listener for text received from nearby devices.

function onTextReceived(
  (data: {peerId: string; text: string}) => void
): Function;
import { onTextReceived } from "expo-nearby-connections";

const unsubscribe = onTextReceived(({ peerId, text }) => {
  // handler
});

unsubscribe();

Basic Setup

this is the basic setup for using the library.

Advertise a connection to other devices

import * as NearbyConnections from "expo-nearby-connection";

...

// Advertise a connection
useEffect(() => {
    NearbyConnections.startAdvertise("My Device Name Or ID")
        .then((peerId) => {
            setMyPeerId(peerId);
        }).catch((error) => {
            // error handler
        })

    return () => {
        stopAdvertise();
    }
}, [])

// Listen for incoming connections
useEffect(() => {
    const onInvitationListener = NearbyConnections.onInvitationReceived((data) => {
        // handler when discovery device is requesting connection
        NearbyConnections.acceptConnection(data.peerId)
    })

    const onConnectedListener = NearbyConnections.onConnected((data) => {
        // handler when the advertise device is accepted the request connection
    })

    const onDisconnectedListener = NearbyConnections.onDisconnected((data) => {
        // handler when discovery device is disconnected
    })

    return () => {
        onInvitationListener();
        onConnectedListener();
        onDisconnectedListener();
    }
}, [])

Discover nearby devices

import * as NearbyConnections from "expo-nearby-connection";

...

// Discover a connection
useEffect(() => {
    NearbyConnections.startDiscovery("My Device Name Or ID")
        .then((peerId) => {
            setMyPeerId(peerId);
        }).catch((error) => {
            // error handler
        })

    return () => {
        stopDiscovery();
    }
}, [])

// Listen for discovered devices
useEffect(() => {
    const onPeerFoundListener = NearbyConnections.onPeerFound((data) => {
        setDiscoveredPeers((peers) => [...peers, data]);
    })

    const onPeerLostListener = NearbyConnections.onPeerLost((data) => {
        setDiscoveredPeers((peers) =>
            peers.filter((peer) => peer.peerId !== data.peerId)
        );
    })

    return () => {
        onPeerFoundListener();
        onPeerLostListener();
    }
})

// Listen for connection state that coming from advertised devices
useEffect(() => {
    const onConnectedListener = NearbyConnections.onConnected((data) => {
        // handler when the advertise device is accepted the request connection
    })

    const onDisconnectedListener = NearbyConnections.onDisconnected((data) => {
        // handler when the advertise device is rejected the request connection
    })

    return () => {
        onConnectedListener();
        onDisconnectedListener();
    }
}, [])

const handleRequestConnection = (selectedPeerId: string) => {
    NearbyConnections.requestConnection(selectedPeerId);
}

Sending and Receiving Text

import * as NearbyConnections from "expo-nearby-connection";

...

// Listen to incoming text messages
useEffect(() => {
    const onTextReceivedListener = NearbyConnections.onTextReceived((data) => {
        setMessages((message) => [...message, {
            peerId: data.peerId,
            text: data.text
        }]);
    })

    return () => {
        onTextReceivedListener();
    }
})

const handleSendText = (message: string) => {
    NearbyConnections.sendText(connectedPeerId, message);
}

Contributing

We welcome contributions! Please submit a pull request or file an issue on our GitHub repository.