@videosdk.live/react-native-sdk
Version:
<h1 align="center"> <img src="https://static.videosdk.live/videosdk_logo_website_black.png"/><br/> <p align="center"> Video SDK React Native App <br/> <a href="https://videosdk.live/">videosdk.live</a> </p> </h1>
365 lines (339 loc) • 10.6 kB
JavaScript
import { useEffect } from "react";
import {
NativeModules,
Platform,
NativeEventEmitter,
DeviceEventEmitter,
PermissionsAndroid,
} from "react-native";
import {
MicrophoneDeviceInfo as AudioDeviceInfo,
CameraDeviceInfo as OldCameraDeviceInfo,
Constants,
} from "@videosdk.live/react-sdk";
import InCallManager from "@videosdk.live/react-native-incallmanager";
/**
*
* @param {{
* onAudioDeviceChanged?: Function | undefined,
* }}
*
* * @returns {{
* getDevices: () => Promise<Array<DeviceInfo>>;
* getAudioDeviceList: () => Promise<Array<AudioDeviceInfo>>;
* getCameras: () => Promise<Array<CameraDeviceInfo>>;
* checkPermission: (permission? : Permission) => Promise<Map<string, boolean>>;
* requestPermission: (permission? : Permission) => Promise<Map<string, boolean>>;
* checkBlueToothPermission:()=> Promise<boolean>
* requestBluetoothPermission:()=> Promise<boolean>
* }}
* */
const useMediaDevice = ({ onAudioDeviceChanged = (data) => {} } = {}) => {
var eventEmitter;
if (Platform.OS == "ios") {
const { InCallManager } = NativeModules;
eventEmitter = new NativeEventEmitter(InCallManager);
}
useEffect(() => {
InCallManager.start({ media: "video" });
const callback = async (data) => {
const devices = await getAudioDeviceList();
if (Platform.OS == "ios") {
if (data["selectedAudioDevice"].includes("Headphone")) {
data["selectedAudioDevice"] = "WIRED_HEADSET";
} else if (data["selectedAudioDevice"].includes("Bluetooth")) {
data["selectedAudioDevice"] = "BLUETOOTH";
} else if (data["selectedAudioDevice"].includes("Speaker")) {
data["selectedAudioDevice"] = "SPEAKER_PHONE";
} else if (
data["selectedAudioDevice"].includes("Microphone") ||
data["selectedAudioDevice"].includes("Receiver")
) {
data["selectedAudioDevice"] = "EARPIECE";
}
}
data["availableDevices"] = devices;
devices.forEach((element) => {
if (element["deviceId"] == data["selectedAudioDevice"]) {
data["selectedAudioDevice"] = element;
}
});
onAudioDeviceChanged(data);
return data;
};
if (Platform.OS == "ios") {
eventEmitter.addListener("onAudioDeviceChanged", callback);
return () => {
eventEmitter.removeAllListeners("onAudioDeviceChanged");
};
} else {
DeviceEventEmitter.addListener("onAudioDeviceChanged", callback);
return () => {
DeviceEventEmitter.removeAllListeners("onAudioDeviceChanged");
};
}
}, []);
/**
*
* @param {Permission} permission
* @returns {Promise<Map<string, boolean>>}
*/
async function checkPermission(permission) {
if (!permission) {
permission = Constants.permission.AUDIO_AND_VIDEO;
}
const permissionMap = new Map();
if (
permission.includes(Constants.permission.VIDEO) ||
permission.includes(Constants.permission.AUDIO_AND_VIDEO)
) {
let allowed = true;
try {
const res = await InCallManager.checkCameraPermission(); // 'granted' | 'denied'
if (res == "denied" || res == "undetermined") {
allowed = false;
}
} catch (e) {
allowed = false;
throw Error("Device does not support camera permission check", e);
}
permissionMap.set(Constants.permission.VIDEO, allowed);
}
if (
permission.includes(Constants.permission.AUDIO) ||
permission.includes(Constants.permission.AUDIO_AND_VIDEO)
) {
let allowed = true;
try {
const res = await InCallManager.checkRecordPermission(); // 'granted' | 'denied'
if (res == "denied" || res == "undetermined") {
allowed = false;
}
} catch (e) {
allowed = false;
throw Error("Device does not support microphone permission check", e);
}
permissionMap.set(Constants.permission.AUDIO, allowed);
}
return permissionMap;
}
/**
*
* @param {Permission} permission
* @returns {Promise<Map<string, boolean>>}
*/
async function requestPermission(permission) {
if (!permission) {
permission = Constants.permission.AUDIO_AND_VIDEO;
}
const permissionMap = new Map();
if (
permission.includes(Constants.permission.VIDEO) ||
permission.includes(Constants.permission.AUDIO_AND_VIDEO)
) {
let videoMediaStream;
const constraints = { audio: false, video: true };
let permissionGranted = true;
try {
videoMediaStream = await navigator.mediaDevices.getUserMedia(
constraints
);
} catch (ex) {
permissionGranted = false;
let message;
if (ex.name === "SecurityError") {
message =
"Oops! It seems like camera access was denied or dismissed. To proceed, kindly grant access through your App settings.";
} else if (ex.name === "DOMException") {
message =
"Please ensure your camera is connected and turned on, and that the camera driver is installed and up-to-date.";
} else {
message = `Something unexpected occur, Exception info: ${ex}`;
}
throw new Error(message);
}
if (videoMediaStream) {
videoMediaStream.getTracks().forEach(function (track) {
track.stop();
});
}
permissionMap.set(Constants.permission.VIDEO, permissionGranted);
}
if (
permission.includes(Constants.permission.AUDIO) ||
permission.includes(Constants.permission.AUDIO_AND_VIDEO)
) {
let audioMediaStream;
const constraints = { audio: true, video: false };
let permissionGranted = true;
try {
audioMediaStream = await navigator.mediaDevices.getUserMedia(
constraints
);
} catch (ex) {
permissionGranted = false;
let message;
if (ex.name === "SecurityError") {
message =
"Oops! It seems like mic access was denied or dismissed. To proceed, kindly grant access through your App settings.";
} else if (ex.name === "DOMException") {
message = "Please ensure your mic is connected and turned on.";
} else {
message = `Something unexpected occur, Exception info: ${ex}`;
}
throw new Error(message);
}
if (audioMediaStream) {
audioMediaStream.getTracks().forEach(function (track) {
track.stop();
});
}
permissionMap.set(Constants.permission.AUDIO, permissionGranted);
}
return permissionMap;
}
/**
*
* @returns {Promise<boolean>}
*/
async function checkBlueToothPermission() {
if (Platform.OS == "ios") {
throw Error(
"checkBlueToothPermission() method is not supported on the iOS platform"
);
}
let permission =
Platform.Version >= 31
? "android.permission.BLUETOOTH_CONNECT"
: "android.permission.BLUETOOTH";
return PermissionsAndroid.check(permission)
.then((status) => {
return status;
})
.catch((ex) => {
throw Error("Exception in Bluetooth checking permission", ex);
});
}
/**
*
* @returns {Promise<boolean>}
*/
async function requestBluetoothPermission() {
if (Platform.OS == "ios") {
throw Error(
"requestBluetoothPermission() method is not supported on the iOS platform"
);
}
let permissionGranted = false;
let permission =
Platform.Version >= 31
? "android.permission.BLUETOOTH_CONNECT"
: "android.permission.BLUETOOTH";
try {
const granted = await PermissionsAndroid.request(permission, {
title:
"This Permission will help you to communicate over Bluetooth Peripherals",
buttonNegative: "Cancel",
buttonPositive: "OK",
});
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
permissionGranted = true;
} else {
console.log("Bluetooth Connect Permission Denied");
}
} catch (ex) {
throw Error("Exception in Bluetooth requesting permission", ex);
}
return permissionGranted;
}
/**
*
* @returns {Promise<Array<DeviceInfo>>}
*/
async function getDevices() {
let audioDeviceList = await getAudioDeviceList();
const devices = [];
audioDeviceList.forEach((element) => {
devices.push(element);
});
const cameraDeviceList = await getCameras();
cameraDeviceList.forEach((element) => {
devices.push(element);
});
return devices;
}
/**
*
* @returns {Promise<Array<AudioDeviceInfo>>}
*/
async function getAudioDeviceList() {
let devices = await InCallManager.getAudioDeviceList();
const audioDevices = [];
if (devices) {
if (devices.length > 0) {
if (
devices.includes("WIRED_HEADSET") ||
devices.includes("BLUETOOTH")
) {
removeItemFromArray(devices, "EARPIECE");
}
for (const device of devices) {
audioDevices.push(new AudioDeviceInfo(device, "", "audio", device));
}
}
}
return audioDevices;
}
function removeItemFromArray(arr, value) {
var index = arr.indexOf(value);
if (index > -1) {
arr.splice(index, 1);
}
return arr;
}
/**
*
* @returns {Promise<Array<CameraDeviceInfo>>}
*/
async function getCameras() {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
const cameras = [];
for (const device of devices) {
if (device.kind == "videoinput") {
cameras.push(
new CameraDeviceInfo(
device.deviceId,
device.groupId,
"video",
device.label,
device.facing == "environment" ? "back" : device.facing
)
);
}
}
return cameras;
} catch (error) {
console.error(`An error occurred in getCameras(), ${error.message}`);
}
}
return {
getDevices,
getAudioDeviceList,
getCameras,
checkPermission,
requestPermission,
checkBlueToothPermission,
requestBluetoothPermission,
};
};
class CameraDeviceInfo extends OldCameraDeviceInfo {
constructor(deviceId, groupId, kind, label, facing) {
super(deviceId, groupId, kind, label);
/**
* @type {string}
*/
this.facingMode = facing;
}
}
export default useMediaDevice;