쨍쨍
#4. AI Smart Home_SocketActivity 본문
[ SocketActivity 의 기능 ]
SocketActivity 클래스는 스마트홈 시스템에서 서버와의 소켓 연결을 관리하는 역할을 담당합니다. 이 클래스는 서버와의 데이터 전송 및 수신, 로그인 및 회원가입 처리, 센서 데이터 요청 및 처리 등을 수행합니다.
모든 클래스에서 직접 소켓 연결을 처리할 수도 있지만, SocketActivity 클래스를 통해 중앙 집중식으로 소켓 통신을 관리함으로써 서버와의 연결이 끊어지지 않도록 안정적으로 유지할 수 있습니다. 연결이 끊어지더라도, 자동 재연결을 시도하여 시스템의 안정성을 높입니다. 또한 스마트홈 시스템 특성상 서버와의 지속적인 실시간 데이터 수신이 중요하므로, SocketActivity 클래스는 핵심 통신 기능을 담당하며, 안정적인 운영을 돕습니다.
[ SocketActivity.java ]
import android.util.Log;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.io.IOException;
public class SocketActivity {
private static final String TAG = "SocketActivity";
private static final String SERVER_IP = "ip 주소";
private static final int SERVER_PORT = 12345;
private static SocketActivity instance;
private Socket socket;
private PrintWriter writer;
private BufferedReader reader;
private OnDataReceivedListener dataListener;
private boolean isConnecting = false;
private boolean isLoginInProgress = false; // 로그인 진행 상태 플래그
private boolean isConnected = false; // 재연결을 위한 상태 플래그
private SocketActivity() { }
public static synchronized SocketActivity getInstance() {
if (instance == null) {
instance = new SocketActivity();
}
return instance;
}
public void setDataListener(OnDataReceivedListener listener) {
this.dataListener = listener; // 전달받은 리스너를 설정
}
public void connectToServer(OnDataReceivedListener listener) {
if (isConnecting) return;
isConnecting = true;
dataListener = listener;
new Thread(() -> {
try {
socket = new Socket(SERVER_IP, SERVER_PORT);
socket.setSoTimeout(60000); // 타임아웃을 60초로 설정
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
Log.d(TAG, "Connected to server");
//'']
isConnected = true;
requestDataFromServer();
receiveDataFromServer(); // 데이터 수신을 한 번만 호출
sendRequestSensorData();
RequestTipData();
} catch (IOException e) {
Log.e(TAG, "Failed to connect to server: " + e.getMessage());
if (dataListener != null) {
dataListener.onDataReceived("Connection failed");
}
} finally {
isConnecting = false;
}
}).start();
}
public void sendData(String data) {
if (isSocketConnected()) {
new Thread(() -> {
writer.println(data);
writer.flush();
Log.d(TAG, "Data sent to server: " + data);
}).start();
} else {
Log.e(TAG, "Socket is not connected. Cannot send data.");
}
}
boolean isSocketConnected() {
return socket != null && socket.isConnected() && !socket.isClosed();
}
// 회원가입 데이터
public void sendSignupData(String username, String name, String phone, String password) {
if (isSocketConnected()) {
new Thread(() -> {
String message = "REGISTER," + username + "," + name + "," + phone + "," + password;
writer.println(message);
writer.flush();
Log.d(TAG, "회원가입 :Sent signup data to server: " + message);
}).start();
} else {
Log.e(TAG, "Socket is not connected. Cannot send signup data.");
}
}
// 로그인 데이터
public void sendLoginData(String username, String password) {
if (isLoginInProgress) {
Log.d(TAG, "Login request is already in progress.");
return; // 중복 요청 방지
}
isLoginInProgress = true; // 로그인 진행 중 상태 설정
if (isSocketConnected()) {
new Thread(() -> {
writer.println("Login_Data");
writer.flush();
String message = username + "," + password;
writer.println(message);
writer.flush();
Log.d(TAG, "로그인: Sent login data to server: " + message);
isLoginInProgress = false; // 요청 완료 후 초기화
}).start();
} else {
Log.e(TAG, "Socket is not connected. Attempting to reconnect and resend login data.");
connectToServer(data -> {
sendLoginData(username, password); // 재연결 후 로그인 데이터 전송
isLoginInProgress = false; // 요청 완료 후 초기화
});
}
}
// 중복 확인
public void sendUsernameValidationRequest(String username) {
if (isSocketConnected()) {
new Thread(() -> {
String message = "VALIDATE_USER," + username;
writer.println(message);
writer.flush();
Log.d(TAG, "Sent username validation request to server: " + message);
}).start();
} else {
Log.e(TAG, "Socket is not connected. Cannot send username validation request.");
}
}
// 날씨를 받아오는 코드 (main)
void requestDataFromServer() {
if (writer != null) {
String message = "REQUEST_DATA";
writer.println(message);
writer.flush();
Log.d(TAG, "Sent request to server: " + message);
} else {
Log.e(TAG, "Writer is null. Cannot send request.");
}
}
// 날씨 데이터 + 센서 데이터 받아오는 코드 (home)
void sendRequestSensorData() {
if (writer != null) {
String message = "MAIN_DATA";
writer.println(message);
writer.flush();
Log.d(TAG, "Sent request to server: " + message);
} else {
Log.e(TAG, "Writer is null. Cannot send request.");
}
}
// GPT Api 받아오는 코드
void RequestTipData() {
if (writer != null) {
String message = "Tip_DATA";
writer.println(message);
writer.flush();
Log.d(TAG, "Sent request to server: " + message);
} else {
Log.e(TAG, "Writer is null. Cannot send request.");
}
}
private void receiveDataFromServer() {
new Thread(() -> {
try {
String line;
while (isSocketConnected() && (line = reader.readLine()) != null) {
//line = line.trim().replaceAll("[\\s\\u0000-\\u001F\\u007F]", ""); // 특수 문자 제거
line = line.replaceAll("[\\u0000-\\u001F\\u007F]", "");
Log.d(TAG, "Processed data received from server: '" + line + "'");
// 센서 데이터인지 확인하여 별도 처리
if (line.startsWith("SENSOR_DATA")) {
String sensorData = line.substring("SENSOR_DATA".length());
Log.d(TAG, "Received sensor data: " + sensorData);
if (dataListener != null) {
dataListener.onDataReceived(sensorData); // 센서 데이터 전달
dataListener.onDataReceived(line); // 응답을 클라이언트로 전달
}
} else {
// 그 외 데이터 처리
if (dataListener != null) {
dataListener.onDataReceived(line);
}
}
}
} catch (SocketTimeoutException e) {
Log.e(TAG, "Socket read timed out: " + e.getMessage());
attemptReconnect();
} catch (IOException e) {
Log.e(TAG, "Error reading from server: " + e.getMessage());
disconnect();
}
}).start();
}
private void attemptReconnect() {
disconnect();
try {
Thread.sleep(5000); // 5초 대기 후 재연결 시도
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
connectToServer(dataListener);
}
public void disconnect() {
try {
if (writer != null) writer.close();
if (reader != null) reader.close();
if (socket != null) socket.close();
Log.d(TAG, "Disconnected from server");
} catch (IOException e) {
Log.e(TAG, "Failed to disconnect: " + e.getMessage());
} finally {
isLoginInProgress = false; // 연결이 끊어졌을 때 초기화
isConnecting = false;
}
}
public interface OnDataReceivedListener {
void onDataReceived(String data);
}
}
'프로그래밍 코드 > Android Studio' 카테고리의 다른 글
#6. Al Smart Home_TipActivity (1) | 2024.12.17 |
---|---|
#5. Al Smart Home_HomeActivty (3) | 2024.12.17 |
AI 심리 분석 프로그램 도담이 (1) | 2024.07.22 |
#3. AI Smart Home_MainActivity (0) | 2024.03.13 |
#2. AI Smart Home_RegisterActivity (0) | 2024.03.13 |