UNPKG

react-native-ble-nitro

Version:

High-performance React Native BLE library built on Nitro Modules - drop-in replacement for react-native-ble-plx

88 lines (87 loc) 4.07 kB
import { AndroidConfig, WarningAggregator, withAndroidManifest, withInfoPlist, } from 'expo/config-plugins'; const BLUETOOTH_PERMISSIONS = [ 'android.permission.BLUETOOTH', 'android.permission.BLUETOOTH_ADMIN', 'android.permission.ACCESS_COARSE_LOCATION', 'android.permission.ACCESS_FINE_LOCATION', ]; const BLUETOOTH_PERMISSIONS_API_31 = [ 'android.permission.BLUETOOTH_SCAN', 'android.permission.BLUETOOTH_ADVERTISE', 'android.permission.BLUETOOTH_CONNECT', ]; export const withBleNitroAndroid = (config, props = {}) => { const { isBackgroundEnabled = false, neverForLocation = false } = props; return withAndroidManifest(config, (config) => { const androidManifest = config.modResults; // Add required permissions AndroidConfig.Permissions.ensurePermissions(config.modResults, [ ...BLUETOOTH_PERMISSIONS, ...BLUETOOTH_PERMISSIONS_API_31, ]); // Add uses-feature for BLE if (!androidManifest.manifest['uses-feature']) { androidManifest.manifest['uses-feature'] = []; } const usesFeatures = androidManifest.manifest['uses-feature']; // Add BLE feature requirement const bleFeature = { $: { 'android:name': 'android.hardware.bluetooth_le', 'android:required': (isBackgroundEnabled ? 'true' : 'false'), }, }; if (!usesFeatures.find((f) => f.$?.['android:name'] === 'android.hardware.bluetooth_le')) { usesFeatures.push(bleFeature); } // Handle location permission settings for Android 12+ if (neverForLocation) { // Add neverForLocation attribute to location permissions for Android 12+ const permissions = androidManifest.manifest['uses-permission'] || []; permissions.forEach((permission) => { if (permission.$?.['android:name'] === 'android.permission.ACCESS_FINE_LOCATION' || permission.$?.['android:name'] === 'android.permission.ACCESS_COARSE_LOCATION') { permission.$['android:usesPermissionFlags'] = 'neverForLocation'; } }); } return config; }); }; export const withBleNitroIOS = (config, props = {}) => { const { modes, bluetoothAlwaysPermission = 'Allow $(PRODUCT_NAME) to connect to bluetooth devices' } = props; return withInfoPlist(config, (config) => { // Add NSBluetoothAlwaysUsageDescription if (bluetoothAlwaysPermission !== false) { config.modResults.NSBluetoothAlwaysUsageDescription = bluetoothAlwaysPermission; } // Add background modes if specified if (modes && modes.length > 0) { const backgroundModes = modes.map(mode => `bluetooth-${mode}`); if (!config.modResults.UIBackgroundModes) { config.modResults.UIBackgroundModes = []; } backgroundModes.forEach(mode => { if (!config.modResults.UIBackgroundModes.includes(mode)) { config.modResults.UIBackgroundModes.push(mode); } }); } return config; }); }; const withBleNitro = (config, props = {}) => { // Validate props if (props.neverForLocation && !props.isBackgroundEnabled) { WarningAggregator.addWarningForPlatform('android', 'react-native-ble-nitro', 'neverForLocation is set to true but isBackgroundEnabled is false. ' + 'This might cause issues with BLE scanning on some Android devices.'); } if (props.modes && props.modes.some(mode => !['peripheral', 'central'].includes(mode))) { WarningAggregator.addWarningForPlatform('ios', 'react-native-ble-nitro', 'Invalid background mode specified. Only "peripheral" and "central" are supported.'); } // Apply platform-specific configurations config = withBleNitroAndroid(config, props); config = withBleNitroIOS(config, props); return config; }; export default withBleNitro;