BLE는 내가 추가하는 기능을 해낼 수 없어 Bluetooth-Classic으로 재도전 한다.
1. 패키지 설치하기
npm install react-native-bluetooth-classic
npx expo install expo-build-properties
npm install expo-dev-client
2. 디바이스 스캔 및 연결
useBlutoothClassic.js
import { useEffect, useState, useRef } from 'react';
import axios from "axios";
import AsyncStorage from "@react-native-async-storage/async-storage";
import BluetoothClassic from 'react-native-bluetooth-classic';
import BluetoothRequestPermissions from './BluetoothRequestPermissions';
const UseBluetoothClassic = () => {
const discoveredDevices = useRef(new Map()); // 장치를 저장할 Map
const [allDevices, setAllDevices] = useState([]); // 연결 가능한 주변 Bluetooth 장치 목록
const [connectedDevice, setConnectedDevice] = useState(null); // 연결된 장치
const [isScanning, setIsScanning] = useState(false); // 스캔 상태
const [token, setToken] = useState(null);
// AsyncStorage에서 토큰 가져오기
useEffect(() => {
const fetchToken = async () => {
try {
const storedToken = await AsyncStorage.getItem('token');
setToken(storedToken);
} catch (error) {
console.error('토큰 가져오기 실패:', error);
}
};
fetchToken();
}, []);
const scanForPeripherals = async () => {
if (BluetoothClassic.isScanning) {
return;
}
discoveredDevices.current.clear(); // 새로운 스캔 시작 시 기존 장치 목록 초기화
setIsScanning(true); // 스캔 시작
try {
// Bluetooth 활성화 확인
const isEnabled = await BluetoothClassic.isBluetoothEnabled();
if (!isEnabled) {
console.error("블루투스가 활성화 되지 않았습니다.");
return;
}
// Bluetooth 장치 검색 시작
BluetoothClassic.startDiscovery();
// 장치 발견 이벤트 처리
const onDeviceDiscovered = (device) => {
if (device.name !== device.id) { // 대개 폰이면 id와 name이 같지 않음
if (!discoveredDevices.current.has(device.id)) {
discoveredDevices.current.set(device.id, device);
// 상태 업데이트 (중복 없이)
setAllDevices((prevDevices) => {
// 장치가 기존 목록에 없으면 추가
if (!prevDevices.some((prevDevice) => prevDevice.id === device.id)) {
console.log(`새로운 장치 추가: ${device.name}`);
return [...prevDevices, device];
}
return prevDevices;
});
}
}
};
BluetoothClassic.onDeviceDiscovered(onDeviceDiscovered);
// 10초 후 스캔 중지
const timeoutId = setTimeout(() => {
BluetoothClassic.cancelDiscovery(); // 스캔 중지
setIsScanning(false); // 스캔 종료 표시
console.log("스캔 종료 (타임아웃)");
}, 10000);
// 타임아웃 및 스캔 종료 처리
return () => {
clearTimeout(timeoutId);
BluetoothClassic.cancelDiscovery();
setIsScanning(false);
};
} catch (error) {
console.error("스캔 오류:", error.message);
setIsScanning(false);
}
};
useEffect(() => {
const initializeBLE = async () => {
const permissionGranted = await BluetoothRequestPermissions();
console.log("권한 요청 결과:", permissionGranted);
if (permissionGranted) {
console.log("useBluetoothClassic - Bluetooth 권한이 부여되었습니다.");
scanForPeripherals(); // 스캔 시작
} else {
console.log("useBluetoothClassic - Bluetooth 권한이 거부되었습니다.");
}
};
initializeBLE();
return () => {
if (isScanning) {
BluetoothClassic.cancelDiscovery();
setIsScanning(false); // 스캔 종료 표시
console.log("스캔 종료 (클린업)");
}
};
}, []);
async function connectToDevice(deviceId) {
try {
// 연결 시도
const device = await BluetoothClassic.connectToDevice(deviceId);
if (device) {
setConnectedDevice(device); // 연결된 장치를 상태로 저장
console.log('장치 연결 성공:', device.name);
return true; // 연결 성공
} else {
return false; // 연결 실패
}
} catch (error) {
console.log('연결 오류:', error.message);
return false; // 연결 실패
}
}
return {
allDevices,
scanForPeripherals,
connectedDevice,
connectToDevice
};
};
export default UseBluetoothClassic;
bluetooth.js
function Step2Screen({ route }) {
const { permissionGranted = false, cardId } = route.params || {};
const [recipients, setRecipients] = useState([]);
const [recipientStatuses, setRecipientStatuses] = useState({});
const { scanForPeripherals, connectToDevice, isConnected, sendData, successSend, allDevices } = useBLE();
const [isScanning, setIsScanning] = useState(false);
useEffect(() => {
function Step2Screen({ route }) {
setRecipients(allDevices || []);
}, [allDevices]);
const handlePressRecipient = async (id, cardId) => {
setRecipientStatuses((prevStatuses) => ({
...prevStatuses,
[id]: '요청 중...'
}));
try {
// 디바이스 연결 시도
await connectToDevice(id);
if (isConnected) {
// 연결이 성공한 경우, cardId 전송 시도
await sendData(cardId);
// 4. 카드 ID 전송이 성공한 경우
if (successSend) {
setRecipientStatuses((prevStatuses) => ({
...prevStatuses,
[id]: '공유 완료됨'
}));
} else {
setRecipientStatuses((prevStatuses) => ({
...prevStatuses,
[id]: '전송 실패'
}));
}
} else {
console.log('디바이스 연결 실패 이유 : ', error.toString());
setRecipientStatuses((prevStatuses) => ({
...prevStatuses,
[id]: '연결 실패'
}));
}
} catch (error) {
console.log('오류 발생:', error.toString());
setRecipientStatuses((prevStatuses) => ({
...prevStatuses,
[id]: '오류 발생'
}));
}
}
'졸업 프로젝트' 카테고리의 다른 글
[SSOP] 졸업 프로젝트 회고록 | 1020 MZ 세대들의 자기소개를 도와주는 앱 서비스 (2) | 2025.01.06 |
---|---|
[React native - Expo] Bluetooth-Classic (2) 데이터 전송 및 수신 (2) | 2025.01.06 |
[React Native - Expo] BLE 블루투스 기능 _ (3) 디바이스 연결, 데이터 전송 (1) | 2025.01.06 |
[React Native - Expo] BLE 블루투스 기능 _ (2) 권한 설정, 디바이스 스캔 (3) | 2024.11.05 |
[React Native - Expo] BLE 블루투스 기능 _ (1) 환경설정, 안드로이드 폰에 앱 설치 (3) | 2024.10.31 |