Vamos ver como criar uma aplicação React Native para Adnroid que permite a comunicação BLE (Bluetooth Low Energy) com um ESP32. Utilizaremos o React Native para desenvolver um terminal BLE no Android que pode comunicar com um ESP32 NodeMCU ou qualquer outro dispositivo compatível.
Hardware
- Um computador com o React Native e o Node.js instalados
- Um dispositivo Android com BLE
- Um cabo USB para ligar o computador ao dispositivo
- Um dispositivo BLE (ESP32)
Código de gestão BLE para ESP32
Para testar a aplicação React Native, vamos utilizar o código de gestão BLE para o ESP32.
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
BLECharacteristic *pCharacteristic = NULL;
std::string msg;
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
}
}
};
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
Serial.println("Client connected");
}
void onDisconnect(BLEServer* pServer) {
Serial.println("Client disconnected");
BLEDevice::startAdvertising(); // needed for reconnection
}
};
void setup() {
Serial.begin(115200);
Serial.println("1- Download and install an BLE Terminal Free");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to ESP32BLE");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
BLEDevice::init("ESP32BLE");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
pAdvertising->start();
Serial.print("Server address:");
Serial.println(BLEDevice::getAddress().toString().c_str());
}
void loop() {
readSerialPort();
//Send data to slave
if(msg!=""){
pCharacteristic->setValue(msg);
msg="";
}
delay(2000);
}
void readSerialPort(){
while (Serial.available()) {
delay(10);
if (Serial.available() >0) {
char c = Serial.read(); //gets one byte from serial buffer
msg += c; //add to String
}
}
Serial.flush(); //clean buffer
}
Adicionamos a função BLEServerCallbacks à gestão do servidor BLE para detetar a desconexão e iniciar a publicidade para poder voltar a ligar o ESP32.
pServer->setCallbacks(new MyServerCallbacks());
Aplicação React Native para gestão BLE
Para gerir a comunicação BLE (Bluetooth Low Energy) no dispositivo Android, utilizamos a biblioteca react-native-ble-manager
npm install react-native-ble-manager --save
Para configurar o projeto de aplicação, siga o tutorial anterior.
No ficheiro App.tsx, para utilizar a biblioteca, importamo-la utilizando o comando
import BleManager from 'react-native-ble-manager';
Estamos a criar um componente funcional que conterá os elementos necessários para gerir a comunicação BLE
let serviceid="4fafc201-1fb5-459e-8fcc-c5c9c331914b";
let caracid="beb5483e-36e1-4688-b7f5-ea07361b26a8";
const BluetoothBLETerminal = () => {
const [devices, setDevices] = useState<any[]>([]);
const [paired, setPaired] = useState<any[]>([]);
const [selectedDevice, setSelectedDevice] = useState<Peripheral>();
const [messageToSend, setMessageToSend] = useState("");
const [receivedMessage, setReceivedMessage] = useState("");
const [isConnected, setIsConnected] = useState(false);
const [intervalId, setIntervalId] = useState<NodeJS.Timer>();
const [isScanning, setIsScanning] = useState(false);
Nota: é possível criar um componente derivado de ReactNative.Components
Gestão de autorizações
Para descobrir e estabelecer ligação a dispositivos Bluetooth, são necessárias pelo menos 3 permissões:
- BLUETOOTH_SCAN
- LIGAÇÃO_DE_DISTRIBUIÇÃO
- LOCALIZAÇÃO_DE_ACESSO
N.B.: estas permissões dependem da versão e do sistema operativo utilizado
Eis as etiquetas a adicionar ao ficheiro AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
No ficheiro App.tsx, criamos a função requestBluetoothPermission()
if (Platform.OS === 'android' && Platform.Version >= 23) {
PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.LIGAÇÃO_DE_DISTRIBUIÇÃO,
PermissionsAndroid.PERMISSIONS.LOCALIZAÇÃO_DE_ACESSO,
]).then(result => {
if (
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.LIGAÇÃO_DE_DISTRIBUIÇÃO'] &&
result['android.permission.LOCALIZAÇÃO_DE_ACESSO'] === 'granted')
||
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.LIGAÇÃO_DE_DISTRIBUIÇÃO'] &&
result['android.permission.LOCALIZAÇÃO_DE_ACESSO'] === 'never_ask_again')
) {
console.log('User accepted');
} else {
console.log('User refused'); }
});
}
Função de gestão BLE
As funções de gestão do Bluetooth LE são as seguintes
- descobrir dispositivos bluetooth startDeviceDiscovery() (utilizo dispositivos emparelhados)
- ligar ao dispositivo connectToDevice()
- disconnectFromDevice()
- enviar mensagens sendMessage()
- ler mensagens da comunicação readData()
N.B.: Neste exemplo, estamos a escrever e a ler a partir da mesma caraterística. Assim, lemos o valor registado premindo o botão
const checkBluetoothEnabled = async () => {
try {
// turn on bluetooth if it is not on
BleManager.enableBluetooth().then(() => {
console.log('Bluetooth is turned on!');
});
} catch (error) {
console.error('BLE is not available on this device.');
}
}
const startScan = () => {
if (!isScanning) {
BleManager.scan([], 5, true)
.then(() => {
console.log('Scanning...');
setIsScanning(true);
})
.catch(error => {
console.error(error);
});
}
};
const startDeviceDiscovery = async () => {
BleManager.getBondedPeripherals().then((bondedPeripheralsArray) => {
// Each peripheral in returned array will have id and name properties
console.log("Bonded peripherals: " + bondedPeripheralsArray.length);
setPaired(bondedPeripheralsArray);
});
/*BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
});*/
}
const connectToDevice = async (device: Peripheral) => {
BleManager.connect(device.id)
.then(() => {
// Success code
console.log("Connected");
setSelectedDevice(device);
setIsConnected(true);
BleManager.retrieveServices(device.id).then(
(deviceInfo) => {
// Success code
console.log("Device info:", deviceInfo);
}
);
})
.catch((error) => {
// Failure code
console.log(error);
});
}
const sendMessage = async () => {
if(selectedDevice && isConnected){
try {
const buffer = Buffer.from(messageToSend);
BleManager.write(
selectedDevice.id,
serviceid,
caracid,
buffer.toJSON().data
).then(() => {
// Success code
console.log("Write: " + buffer.toJSON().data);
})
.catch((error) => {
// Failure code
console.log(error);
});
} catch (error) {
console.error('Error sending message:', error);
}
}
}
const readData = async () => {
if (selectedDevice && isConnected) {
BleManager.read(
selectedDevice.id,
serviceid,
caracid
)
.then((readData) => {
// Success code
console.log("Read: " + readData);
const message = Buffer.from(readData);
//const sensorData = buffer.readUInt8(1, true);
if(receivedMessage.length>300){
setReceivedMessage(""); //reset received message if length higher than 300
}
setReceivedMessage(receivedMessage => receivedMessage + message +"\n" );
console.log("receivedMessage length",receivedMessage.length)
})
.catch((error) => {
// Failure code
console.log("Error reading message:",error);
});
}
}
// disconnect from device
const disconnectFromDevice = (device: Peripheral) => {
BleManager.disconnect(device.id)
.then(() => {
setSelectedDevice(undefined);
setIsConnected(false);
setReceivedMessage("");
clearInterval(intervalId);
console.log("Disconnected from device");
})
.catch((error) => {
// Failure code
console.log("Error disconnecting:",error);
});
};
A função de renderização do ecrã
Para a apresentação, decidimos colocar tudo no mesmo ecrã. Haverá :
- Um título
- La liste des appareils qui n’apparait que si on n’est pas connecté (!isConnected &&)
- Un encart type terminal de communication qui n’apparait que si on est connecté (selectedDevice && isConnected &&)
- TextInput para escrever a mensagem a enviar messageToSend
- Um botão de envio
- Um botão de reprodução
- Uma caixa de texto para apresentar receivedMessage
- Um botão para desligar
return (
<View>
<Text
style={{
fontSize: 30,
textAlign: 'center',
borderBottomWidth: 1,
}}>
AC Bluetooth Terminal
</Text>
<ScrollView>
{!isConnected && (
<>
{/*
<Text>Available Devices:</Text>
{devices.map((device) => (
<Button
key={device.id}
title={device.name || 'Unnamed Device'}
onPress={() => this.connectToDevice(device)}
/>
))}
*/}
<Text>Paired Devices:</Text>
{paired.map((pair: BluetoothDevice) => (
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 2,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{pair.name}</Text>
<Text style={styles.deviceInfo}>{pair.id}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnect()
: connectToDevice(pair)
}
style={styles.deviceButton}>
<Text
style={[
styles.scanButtonText,
{fontWeight: 'bold', fontSize: 12},
]}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
))}
</>
)}
{selectedDevice && isConnected && (
<>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{selectedDevice.name}</Text>
<Text style={styles.deviceInfo}>{selectedDevice.id}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnect()
: connectToDevice(selectedDevice)
}
style={styles.deviceButton}>
<Text
style={styles.scanButtonText}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<TextInput
style={{
backgroundColor: '#888888',
margin: 2,
borderRadius: 15,
flex:3,
}}
placeholder="Enter a message"
value={messageToSend}
onChangeText={(text) => setMessageToSend(text )}
/>
<TouchableOpacity
onPress={() => sendMessage()
}
style={[styles.sendButton]}>
<Text
style={[
styles.scanButtonText,
]}>
SEND
</Text>
</TouchableOpacity>
</View>
<Text>Received Message:</Text>
<TextInput
editable = {false}
multiline
numberOfLines={20}
maxLength={100}
style={{
backgroundColor: '#333333',
margin: 10,
borderRadius: 2,
borderWidth: 1,
borderColor: '#EEEEEE',
textAlignVertical: 'top',
}} >
{receivedMessage}
</TextInput>
</>
)}
</ScrollView>
</View>
);
Resultados
Como o emparelhamento não é gerido pela aplicação, o ESP32 tem de estar emparelhado antes de utilizar a aplicação. Uma vez carregado o código no ESP32, é possível lançar a aplicação no telemóvel utilizando o comando
npx react-native start



Código completo para a aplicação React Native
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* https://github.com/innoveit/react-native-ble-manager
* https://blog.logrocket.com/using-react-native-ble-manager-mobile-app/
*/
import React, {useState, useEffect} from 'react';
import {
StyleSheet,
Dimensions,
View,
ScrollView,
Text,
TextInput,
PermissionsAndroid,
TouchableOpacity,
Platform} from 'react-native';
import BleManager,{Peripheral} from 'react-native-ble-manager';
import { Buffer } from 'buffer';
let serviceid="4fafc201-1fb5-459e-8fcc-c5c9c331914b";
let caracid="beb5483e-36e1-4688-b7f5-ea07361b26a8";
const BluetoothBLETerminal = () => {
const [devices, setDevices] = useState<any[]>([]);
const [paired, setPaired] = useState<any[]>([]);
const [selectedDevice, setSelectedDevice] = useState<Peripheral>();
const [messageToSend, setMessageToSend] = useState("");
const [receivedMessage, setReceivedMessage] = useState("");
const [isConnected, setIsConnected] = useState(false);
const [intervalId, setIntervalId] = useState<NodeJS.Timer>();
const [isScanning, setIsScanning] = useState(false);
const checkBluetoothEnabled = async () => {
try {
// turn on bluetooth if it is not on
BleManager.enableBluetooth().then(() => {
console.log('Bluetooth is turned on!');
});
} catch (error) {
console.error('BLE is not available on this device.');
}
}
const startScan = () => {
if (!isScanning) {
BleManager.scan([], 5, true)
.then(() => {
console.log('Scanning...');
setIsScanning(true);
})
.catch(error => {
console.error(error);
});
}
};
const startDeviceDiscovery = async () => {
BleManager.getBondedPeripherals().then((bondedPeripheralsArray) => {
// Each peripheral in returned array will have id and name properties
console.log("Bonded peripherals: " + bondedPeripheralsArray.length);
setPaired(bondedPeripheralsArray);
});
/*BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
});*/
}
const connectToDevice = async (device: Peripheral) => {
BleManager.connect(device.id)
.then(() => {
// Success code
console.log("Connected");
setSelectedDevice(device);
setIsConnected(true);
BleManager.retrieveServices(device.id).then(
(deviceInfo) => {
// Success code
console.log("Device info:", deviceInfo);
}
);
})
.catch((error) => {
// Failure code
console.log(error);
});
}
const sendMessage = async () => {
if(selectedDevice && isConnected){
try {
const buffer = Buffer.from(messageToSend);
BleManager.write(
selectedDevice.id,
serviceid,
caracid,
buffer.toJSON().data
).then(() => {
// Success code
console.log("Write: " + buffer.toJSON().data);
})
.catch((error) => {
// Failure code
console.log(error);
});
} catch (error) {
console.error('Error sending message:', error);
}
}
}
const readData = async () => {
if (selectedDevice && isConnected) {
BleManager.read(
selectedDevice.id,
serviceid,
caracid
)
.then((readData) => {
// Success code
console.log("Read: " + readData);
const message = Buffer.from(readData);
//const sensorData = buffer.readUInt8(1, true);
if(receivedMessage.length>300){
setReceivedMessage("");
}
setReceivedMessage(receivedMessage => receivedMessage + message +"\n" );
console.log("receivedMessage length",receivedMessage.length)
})
.catch((error) => {
// Failure code
console.log("Error reading message:",error);
});
}
}
/*useEffect(() => {
let intervalId: string | number | NodeJS.Timer | undefined;
if (selectedDevice && isConnected) {
intervalId = setInterval(() => readData(), 100);
setIntervalId(intervalId);
}
return () => {
clearInterval(intervalId);
};
}, [isConnected,selectedDevice]);*/
// disconnect from device
const disconnectFromDevice = (device: Peripheral) => {
BleManager.disconnect(device.id)
.then(() => {
setSelectedDevice(undefined);
setIsConnected(false);
setReceivedMessage("");
clearInterval(intervalId);
console.log("Disconnected from device");
})
.catch((error) => {
// Failure code
console.log("Error disconnecting:",error);
});
/*BleManager.removeBond(peripheral.id)
.then(() => {
peripheral.connected = false;
peripherals.set(peripheral.id, peripheral);
setConnectedDevices(Array.from(peripherals.values()));
setDiscoveredDevices(Array.from(peripherals.values()));
Alert.alert(`Disconnected from ${peripheral.name}`);
})
.catch(() => {
console.log('fail to remove the bond');
});*/
};
useEffect(() => {
checkBluetoothEnabled();
if (Platform.OS === 'android' && Platform.Version >= 23) {
PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
]).then(result => {
if (
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.BLUETOOTH_CONNECT'] &&
result['android.permission.ACCESS_FINE_LOCATION'] === 'granted')
||
(result['android.permission.BLUETOOTH_SCAN'] &&
result['android.permission.BLUETOOTH_CONNECT'] &&
result['android.permission.ACCESS_FINE_LOCATION'] === 'never_ask_again')
) {
console.log('User accepted');
} else {
console.log('User refused'); }
});
}
BleManager.start({showAlert: false}).then(() => {
console.log('BleManager initialized');
startDeviceDiscovery();
}).catch((error) => {
// Failure code
console.log("Error requesting permission:",error);
});
BleManager.checkState().then((state) =>
console.log(`current BLE state = '${state}'.`)
);
BleManager.getConnectedPeripherals([]).then((peripheralsArray) => {
// Success code
console.log("Connected peripherals: " + peripheralsArray.length);
});
BleManager.getBondedPeripherals().then((bondedPeripheralsArray) => {
// Each peripheral in returned array will have id and name properties
console.log("Bonded peripherals: " + bondedPeripheralsArray.length);
//setBoundedDevices(bondedPeripheralsArray);
});
BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
});
/*let stopDiscoverListener = BleManagerEmitter.addListener(
'BleManagerDiscoverPeripheral',
peripheral => {
peripherals.set(peripheral.id, peripheral);
},
);*/
/*let stopConnectListener = BleManagerEmitter.addListener(
'BleManagerConnectPeripheral',
peripheral => {
console.log('BleManagerConnectPeripheral:', peripheral);
peripherals.set(peripheral.id, peripheral);
setConnectedDevices(Array.from(peripherals.values()));
},
);*/
/*let stopScanListener = BleManagerEmitter.addListener(
'BleManagerStopScan',
() => {
setIsScanning(false);
console.log('scan stopped');
BleManager.getDiscoveredPeripherals().then((peripheralsArray) => {
// Success code
console.log("Discovered peripherals: " + peripheralsArray.length);
for (let i = 0; i < peripheralsArray.length; i++) {
let peripheral = peripheralsArray[i];
console.log("item:", peripheral);
//peripheral.connected = true;
peripherals.set(peripheral.id, peripheral);
setDiscoveredDevices(peripheralsArray);
}
});
},
);*/
return () => {
/*stopDiscoverListener.remove();
stopConnectListener.remove();
stopScanListener.remove();*/
};
}, [])
return (
<View style={[styles.mainBody]}>
<Text
style={{
fontSize: 30,
textAlign: 'center',
borderBottomWidth: 1,
}}>
AC BLE Terminal
</Text>
<ScrollView>
{!isConnected && (
<>
<TouchableOpacity
onPress={() => startDeviceDiscovery()
}
style={[styles.deviceButton]}>
<Text
style={[
styles.scanButtonText,
]}>
SCAN
</Text>
</TouchableOpacity>
{/*
<Text>Available Devices:</Text>
{devices.map((device) => (
<Button
key={device.id}
title={device.name || 'Unnamed Device'}
onPress={() => this.connectToDevice(device)}
/>
))}
*/}
<Text>Paired Devices:</Text>
{paired.map((pair,i) => (
<View key={i}
style={{
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 2,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{pair.name}</Text>
<Text style={styles.deviceInfo}>{pair.id}, rssi: {pair.rssi}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnectFromDevice(pair)
: connectToDevice(pair)
}
style={styles.deviceButton}>
<Text
style={[
styles.scanButtonText,
{fontWeight: 'bold', fontSize: 12},
]}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
))}
</>
)}
{selectedDevice && isConnected && (
<>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<View style={styles.deviceItem}>
<Text style={styles.deviceName}>{selectedDevice.name}</Text>
<Text style={styles.deviceInfo}>{selectedDevice.id}, rssi: {selectedDevice.rssi}</Text>
</View>
<TouchableOpacity
onPress={() =>
isConnected
? disconnectFromDevice(selectedDevice)
: connectToDevice(selectedDevice)
}
style={styles.deviceButton}>
<Text
style={styles.scanButtonText}>
{isConnected ? 'Disconnect' : 'Connect'}
</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<TextInput
style={{
backgroundColor: '#888888',
margin: 2,
borderRadius: 15,
flex:3,
}}
placeholder="Enter a message"
value={messageToSend}
onChangeText={(text) => setMessageToSend(text)}
/>
<TouchableOpacity
onPress={() => sendMessage()
}
style={[styles.sendButton]}>
<Text
style={[
styles.scanButtonText,
]}>
SEND
</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
margin: 5,
}}>
<Text style={{textAlignVertical: 'center'}}>Received Message:</Text>
<TouchableOpacity
onPress={() => readData()
}
style={[styles.deviceButton]}>
<Text
style={[
styles.scanButtonText,
]}>
READ
</Text>
</TouchableOpacity>
</View>
<TextInput
editable = {false}
multiline
numberOfLines={20}
maxLength={300}
style={{
backgroundColor: '#333333',
margin: 10,
borderRadius: 2,
borderWidth: 1,
borderColor: '#EEEEEE',
textAlignVertical: 'top',
}} >
{receivedMessage}
</TextInput>
</>
)}
</ScrollView>
</View>
);
};//end of component
//https://medium.com/supercharges-mobile-product-guide/reactive-styles-in-react-native-79a41fbdc404
export const theme = {
smallPhone: 0,
phone: 290,
tablet: 750,
}
const windowHeight = Dimensions.get('window').height;
const styles = StyleSheet.create({
mainBody: {
flex: 1,
justifyContent: 'center',
height: windowHeight,
...Platform.select ({
ios: {
fontFamily: "Arial",
},
android: {
fontFamily: "Roboto",
},
}),
},
scanButtonText: {
color: 'white',
fontWeight: 'bold',
fontSize: 12,
textAlign: 'center',
},
noDevicesText: {
textAlign: 'center',
marginTop: 10,
fontStyle: 'italic',
},
deviceItem: {
marginBottom: 2,
},
deviceName: {
fontSize: 14,
fontWeight: 'bold',
},
deviceInfo: {
fontSize: 8,
},
deviceButton: {
backgroundColor: '#2196F3',
padding: 10,
borderRadius: 10,
margin: 2,
paddingHorizontal: 20,
},
sendButton: {
backgroundColor: '#2196F3',
padding: 15,
borderRadius: 15,
margin: 2,
paddingHorizontal: 20,
},
});
export default BluetoothBLETerminal;