Notice
Recent Posts
Recent Comments
Link
투케이2K
159. (TWOK/UTIL) [Android/Java] C_Bluetooth_Spp_Server_Module : 블루투스 SPP 통신 서버 모듈 클래스 본문
투케이2K 유틸파일
159. (TWOK/UTIL) [Android/Java] C_Bluetooth_Spp_Server_Module : 블루투스 SPP 통신 서버 모듈 클래스
투케이2K 2025. 2. 23. 12:57[설 명]
프로그램 : Android / Java
설 명 : C_Bluetooth_Spp_Server_Module : 블루투스 SPP 통신 서버 모듈 클래스
[소스 코드]
package com.example.javaproject.C_Module;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import androidx.core.app.ActivityCompat;
import com.example.javaproject.C_Util;
import com.example.javaproject.S_FinalData;
import com.example.javaproject.S_Log;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.UUID;
public class C_Bluetooth_Spp_Server_Module {
/**
* // --------------------------------------------------------------------------------------
* TODO [클래스 설명]
* // --------------------------------------------------------------------------------------
* 1. [설명] : 블루투스 SPP 통신 사용 모듈
* // --------------------------------------------------------------------------------------
* 2. 필요 퍼미션 : 필요 퍼미션 권한 : 위치 및 GPS 권한 , 블루투스 권한 - SCAN , ADVERTISE , CONNECT
*
* // TODO [공통]
* <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
* <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
*
* <uses-permission android:name="android.permission.BLUETOOTH"/>
* <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
* <uses-feature android:name="android.hardware.bluetooth_le" />
*
* // TODO [안드로이드 12 이상 : S 버전]
* <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
* <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
* <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
* // --------------------------------------------------------------------------------------
* */
/**
* // --------------------------------------------------------------------------------------
* TODO [빠른 로직 찾기 : 주석 로직 찾기]
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*
* // --------------------------------------------------------------------------------------
*/
// ------------------------------------------------------------------------------------------
// TODO [사용 방법]
// ------------------------------------------------------------------------------------------
/*
try {
new Thread(){
@Override
public void run(){
try {
// --------------------------------------
// TODO [1]. [서버 모듈 클래스 인스턴스 초기화]
// --------------------------------------
C_Bluetooth_Spp_Server_Module c_socket_server_module = C_Bluetooth_Spp_Server_Module.getInstance();
c_socket_server_module.setContext(A_Intro.this);
// --------------------------------------
// TODO [2]. [서버 활성 수행]
// --------------------------------------
if(c_socket_server_module.openServer() == true) { // TODO [소켓 서버 열기 성공 상태 확인]
}
else {
S_Log._E_("C_Bluetooth_Spp_Server_Module :: openServer :: 서버 활성 실패", null);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
catch (Exception e) {
e.printStackTrace();
}
*/
// ------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------
// TODO [전역 변수 선언]
// ------------------------------------------------------------------------------------------
private String ACTIVITY_NAME = "C_Bluetooth_Spp_Server_Module";
private Context mMainCtx; // [컨텍스트]
private static final UUID UUID_ARRAY[] = {
UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"), // TODO [Client : SmartPhone / Server : SmartPhone]
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // TODO [Client : SmartPhone / Server : Device]
};
private BluetoothAdapter bluetoothAdapter; // [블루투스 어댑터]
BluetoothServerSocket mServer = null; // [서버 소켓]
BluetoothSocket mSocket = null; // [클라이언트 소켓]
Thread mThread = null; // [서버 스레드]
private InputStream inputStream; // [메시지 수신 스트림]
private OutputStream outputStream; // [메시지 송신 스트림]
// ------------------------------------------------------------------------------------------
// TODO [콘텍스트 지정]
// ------------------------------------------------------------------------------------------
public void setContext(Context ctx) {
mMainCtx = ctx;
}
// ------------------------------------------------------------------------------------------
// TODO [인스턴스 생성]
// ------------------------------------------------------------------------------------------
public static C_Bluetooth_Spp_Server_Module getInstance() {
return C_Bluetooth_Spp_Server_Module.LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final C_Bluetooth_Spp_Server_Module INSTANCE = new C_Bluetooth_Spp_Server_Module();
}
// ------------------------------------------------------------------------------------------
// TODO [블루투스 소켓 서버 활성 수행]
// ------------------------------------------------------------------------------------------
public synchronized boolean openServer() {
// [변수 선언]
final boolean[] isConnection = {false};
String M_LOG = "";
// [로직 처리 수행]
try {
if (mMainCtx != null) {
// [블루투스 지원 가능 기기 및 활성 상태 확인]
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
M_LOG = "[Error] :: 블루투스 기능 지원 여부 확인 필요 (Bluetooth is not supported on this device)";
} else {
if (bluetoothAdapter.isEnabled() == false) {
M_LOG = "[Error] :: 블루투스 기능 활성 상태 확인 필요 (Bluetooth isEnabled False)";
} else {
// [기능 사용에 필요한 권한 부여 상태 확인]
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // TODO [안드로이드 12 이상]
if (ActivityCompat.checkSelfPermission(mMainCtx, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mMainCtx, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mMainCtx, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mMainCtx, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mMainCtx, Manifest.permission.BLUETOOTH_ADVERTISE) != PackageManager.PERMISSION_GRANTED) {
M_LOG = "[Error] :: 안드로이드 12 이상 - 블루투스 기능 사용 퍼미션 권한 확인 필요 (Permission Not Granted)";
}
} else { // TODO [안드로이드 12 미만]
if (ActivityCompat.checkSelfPermission(mMainCtx, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(mMainCtx, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
M_LOG = "[Error] :: 안드로이드 12 미만 - 블루투스 기능 사용 퍼미션 권한 확인 필요 (Permission Not Granted)";
}
}
// TODO [에러 발생한 적이 없는 경우 : 상위에서 방어 로직 통과한 경우]
if (C_Util.stringNotNull(M_LOG) == false) {
if (this.mServer != null) { // TODO [소켓이 널이 아닌 경우]
M_LOG = "[Error] :: 블루투스 서버 소켓 이미 활성 된 상태 (Server Socket Not Null)";
} else { // TODO [소켓이 널인 경우]
// TODO [서버 소켓 생성]
mServer = bluetoothAdapter.listenUsingRfcommWithServiceRecord(ACTIVITY_NAME, UUID_ARRAY[0]);
M_LOG = "[Success] :: Bluetooth Socket Server Open (" + String.valueOf(bluetoothAdapter.getName()) + ")";
// TODO [리턴 변수 삽입]
isConnection[0] = true;
// TODO [실시간 클라이언트 메시지 수신 확인] : 1회 연결 후 클라이언트 접속 해제시 break 탈출
mThread = new Thread(new Runnable() {
@Override
public void run() {
try {
// ------------------------------------------------
// TODO [클라이언트 소켓 접속 허용 설정]
mSocket = mServer.accept();
// ------------------------------------------------
// TODO [스트림 초기화]
inputStream = mSocket.getInputStream();
outputStream = mSocket.getOutputStream();
// ------------------------------------------------
// TODO [while 메시지 수신 상태 확인]
byte[] buffer = new byte[1024];
int bytes;
while (true) {
try {
// TODO [클라이언트로부터 데이터 수신]
bytes = inputStream.read(buffer);
String receivedData = new String(buffer, 0, bytes);
String client = "Client Mac :: " + String.valueOf(mSocket.getRemoteDevice().getAddress());
// [로그 출력]
S_Log._W_("[클라이언트 >> 서버] :: 전달 받은 메시지 확인", new String[]{
"Client Info :: " + String.valueOf(client),
"Client Message :: " + String.valueOf(receivedData)
});
// TODO [클라이언트로 메시지 전송 수행]
if (outputStream != null) {
try {
outputStream.write(receivedData.getBytes());
S_Log._W_("[서버 >> 클라이언트] :: 전송 메시지 확인", new String[]{
"Client Info :: " + String.valueOf(client),
"Send Message :: " + String.valueOf(receivedData)
});
} catch (Exception e) {
e.printStackTrace();
}
} else {
S_Log._E_(ACTIVITY_NAME + " :: openServer :: Server To Client Message Send Fail :: outputStream is null", null);
}
}
catch (Exception ey){
ey.printStackTrace();
S_Log._E_(ACTIVITY_NAME + " :: openServer :: Server While Break", null);
break; // TODO [루프 탈출]
}
} // TODO [End While]
// ------------------------------------------------
} catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
// [Exception 발생 시 소켓 연결 종료]
closeSocket();
}
}
});
mThread.start(); // [스레드 수행]
}
}
}
}
}
else {
M_LOG = "[Error] :: mMainCtx Is Null";
}
}
catch (Exception e){
e.printStackTrace();
// [로그 삽입]
M_LOG = "[Exception] :: " + String.valueOf(e.getMessage());
// [Exception 발생 시 소켓 연결 종료]
closeSocket();
}
S_Log._W_(ACTIVITY_NAME + " :: openServer :: 블루투스 서버 소켓 활성 수행", new String[]{
"M_LOG :: " + M_LOG,
"RETURN :: " + isConnection[0]
});
// [리턴 반환 수행]
return isConnection[0];
}
// ------------------------------------------------------------------------------------------
// TODO [서버 소켓 연결 종료]
// ------------------------------------------------------------------------------------------
public synchronized void closeSocket() {
// [변수 선언]
String M_LOG = "";
// [로직 처리 수행]
try {
// [서버 소켓 닫기]
if (mServer != null){
mServer.close();
mServer = null;
}
// [클라이언트 소켓 닫기]
if(this.mSocket != null) {
mSocket.close();
mSocket = null;
}
// [스트림 초기화]
if (inputStream != null){
inputStream.close();
inputStream = null;
}
if (outputStream != null){
outputStream.close();
outputStream = null;
}
// [스레드 닫기]
if (mThread != null){
mThread.interrupt();
}
M_LOG = "[Success] :: bluetoothServerSocket Closed";
}
catch (Exception e) {
S_Log._printStackTrace_(null, S_FinalData.LOG_BUG_STATE, null, e);
M_LOG = "[Exception] :: " + String.valueOf(e.getMessage());
}
S_Log._E_(ACTIVITY_NAME + " :: closeSocket :: 블루투스 서버 소켓 연결 종료 수행", new String[]{ "M_LOG :: " + String.valueOf(M_LOG) });
}
} // TODO [클래스 종료]
반응형
'투케이2K 유틸파일' 카테고리의 다른 글
Comments