반응형

안드로이드의 앱과  PC의  JAVA 서버 프로그램 간에 Serial Port Profile(SPP)를 이용한 블루투스 통신을 다룹니다.  SPP는 블루투스를 이용하여 시리얼 통신을 무선으로 대체할 수 있도록 합니다.




1. 자바 코드 사용 방법

2. 페어링 및 COM 포트 추가

3. 실행 결과

4. 코드 설명

5. 소스코드
    5.1. PC용 JAVA 코드
         5.1.1. Server.java
    5.2. 안드로이드 코드
        5.2.1. AndroidManifest.xml
        5.2.2. activity_main.xml
        5.2.3. MainActivity.java



2015. 12.  5 최초작성

2019. 11. 26  Android 코드를 androidx로 수정 

2021. 10. 17  PC 코드 실행시 에러 해결

                      Caused by: java.lang.NoClassDefFoundError: javax/bluetooth/BluetoothStateException

 

                     Android 코드 및 연동 테스트는 아직 다시 못했습니다. 



1. 자바 코드 사용 방법

 

1. https://eclipse.org/downloads/eclipse-packages/  에서 Eclipse IDE for Java Developers 항목에 있는 Windows x86_64 다운로드 받습니다.  

 




압축을 풀면 eclipse 폴더가 생성됩니다. 원하는 위치에 이동시켜 사용할 수도 있습니다.  

 




eclipse.exe 파일을 선택하고 마우스 오른쪽 버튼을 누릅니다.

메뉴에서 작업 표시줄에 고정을 선택하거나 보내기 > 바탕 화면에 바로가기 만들기를 선택합니다.

 


현재는 이클립스에 포함된 JRE를 사용하기 때문에 추가 설치없이 이클립스 실행이 가능합니다.


이클립스를 실행하려면 JDK가 필요합니다. 아래 링크에서  Java SE Development Kit 를 다운로드 받아 설치하세요.
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html


또는 Android Studio에 포함된 JRE를 사용할 수 있습니다. 
아래 경로를 시스템 변수 path에 추가하세요.

C:\Program Files\Android\Android Studio\jre\bin\




2. 이클립스를 실행시키면 워크스페이스 경로를 물어봅니다. Workspace 항목에 자바 프로젝트를 저장할 원하는 경로를 적어줍니다.

 

Use this as the default and do not ask again을 체크하면 이후 워크스페이스 경로를 다시 물어보지 않고 설정한 경로를 사용하게 됩니다.

뒤에서 이 경로를 확인해야 하니 기억해두세요.  Launch를 클릭합니다.

 




3. 메뉴에서 File > New > Java Project를 선택합니다.  Project name을 적어주고 Finish를 클릭합니다.

 



무시해도 됩니다. Don’t Create를 클릭하세요. 

 




4. Package Explorer에서 프로젝트의 src 폴더를 클릭하고 마우스 오른쪽 버튼을 누릅니다. 메뉴에서 New >  File을 선택합니다.

 




5. New File 창에서 File name을 적어주고 Finish를 클릭합니다. 

 



 Package Explorer에서 프로젝트의 src 폴더 아래에 추가한 자바파일이 보이게 됩니다. 

 




6. http://snapshot.bluecove.org/distribution/download/2.1.1-SNAPSHOT/2.1.1-SNAPSHOT.63에서 bluecove-2.1.1-SNAPSHOT.jar를 다운로드 받습니다. 

 

http://www.java2s.com/Code/Jar/b/Downloadbluecove211jar.htm 에서 다운로드 받으세요. )



프로젝트 폴더에 libs 폴더를 만들어서 그 안에 복사해줍니다.

프로젝트 폴더 위치는 앞에서 정한 워크스페이스 경로입니다.

 



이클립스에서 프로젝트 이름을 클릭하고 F5키를 눌러줘야  Package Explorer에서 libs 폴더와 추가한 bluecove-2.1.1.jar 파일이 보입니다.

 




7. Package Explorer에서 프로젝트 이름을 클릭하고 마우스 오른쪽 버튼을 누릅니다. 메뉴에서 Properties를 선택합니다.

 




8. Properties 창의 왼쪽에 있는 패널에서 Java Build Path를 클릭합니다.

 




8. Libraries 탭을 클릭합니다. 그리고나서 Classpath를 클릭한 후, 오른쪽에 보이는 버튼들 중에서 Add JARs..를 클릭합니다.

 




9. libs 폴더에 있는 bluecove-2.1.1.jar 파일을 선택하고 OK를 클릭합니다.

 




10. Libraries 탭의 Classpath 항목에 bluecove-2.1.1.jar 파일을 확인할 수 있습니다.

OK를 클릭합니다.

 

Apply and Close 버튼을 클릭합니다. 

 



 Project Explorer의  Referenced Libraries에서도 추가한 bluecove-2.1.1-SNAPSHOT.jar 파일을 확인할 수 있습니다.

 



11. 본 포스팅 마지막에 있는 PC용 자바 코드를 프로젝트의 자바 파일에 복사해줍니다.

 




12. 실행시켜보면 다음과 같은 로그가 보이게 됩니다.

 

[Sun Oct 17 07:54:39 KST 2021] Local Bluetooth device...

 

BlueCove version 2.1.1-SNAPSHOT on winsock

[Sun Oct 17 07:54:40 KST 2021] address: F8AC6555F207

[Sun Oct 17 07:54:40 KST 2021] name: WEBNAUTES-PC

[Sun Oct 17 07:54:40 KST 2021] Opened connection successful.

[Sun Oct 17 07:54:40 KST 2021] Server is now running.

[Sun Oct 17 07:54:40 KST 2021] wait for client requests...

 

 

2. 페어링 및 COM 포트 추가

블루투스 디바이스 간에 데이터를 송수신하려면 먼저 페어링을 해야 합니다.  

한쪽에서 자신을 검색할 수 있도록 해주고 상대방이 자신을 찾아서 페어링을 요청하여 양쪽의 인증번호가 동일한지 확인하고 양쪽에서 등록을 해줘야 페어링이 이루어집니다.

 

안드로이드 폰과  윈도우가 설치된  PC간의 페어링 과정을 예로 들어 보겠습니다.  

윈도우 버전마다 페어링 과정이 조금씩 차이가 있지만 거의 동일합니다.  

여기에서는 windows 10 RS2를 기준으로 합니다. 



1. 안드로이드 폰의 설정에서 블루투스를 활성화해줍니다.  이 화면을 유지하면 PC에서 안드로이드폰이 검색됩니다 .

 




2.  윈도우의 작업 표시줄 오른쪽 끝에 있는 블루투스 아이콘을 더블클릭합니다.

 

  




3. “Bluetooth 또는 기타 디바이스 추가”를 클릭합니다.




3.  추가할 디바이스 유형으로 Bluetooth를 선택합니다.

 




4.  추가할 안드로이드폰을 선택합니다.  이 시점에서 안드로이드폰의  블루투스 설정 화면이 켜져있어야 합니다. 화면이 꺼져있으면 찾지 못합니다. 

 




5.  PC와 안드로이드 폰에서 똑같은 숫자가 뜨는지 확인하고  각각 연결과 등록을 선택합니다.

 

 




6.  연결됨으로 표시되면 완료 버튼을 클릭합니다. 

 



화면 오른쪽 아래에 장치 설정 중 메시지가 보이는데

 



다시 장치 설정 완료 메시지가 보일 때까지  잠시 기다립니다.

 




7.  PC에서 안드로이드폰이 연결됨에서 페이링됨으로 변경됩니다.

 



안드로이드폰에서는 등록된 기기 항목에 PC가 추가됩니다.

 



여기까지 해도  포스팅에 포함된 코드를 사용하여 정상적으로 안드로이드와 PC 간에 블루투스 통신이 이루어집니다. 하지만 문제가 발생한다면 8번부터 진행하세요..




8. 윈도우의 블루투스 설정 창을 아래로 스크롤해서 혹은 오른쪽에 위치한  추가 Bluetooth 옵션을 클릭합니다.

 




9. Bluetooth 설정 창의 COM 포트 탭에서 추가를 클릭합니다.

 




10.  “수신(장치에서 연결 시작)”을 선택하고 확인 버튼을 클릭합니다.

 




11. 수신용으로 포트가 추가됩니다.  확인을 클릭하여 Bluetooth 설정 창을 닫습니다.

 

 

 

 

 

3. 실행 결과

 

1. 이클립스에서 Ctrl + F11을 눌러서 자바 서버프로그램을 실행시킵니다.  

아래와 같은 메시지가 보입니다..

 

[Mon Apr 24 15:26:11 KST 2017] Local Bluetooth device...

 

BlueCove version 2.1.1-SNAPSHOT on winsock

[Mon Apr 24 15:26:12 KST 2017] address: F8633F2710E0

[Mon Apr 24 15:26:12 KST 2017] name: NOTE

[Mon Apr 24 15:26:12 KST 2017] Opened connection successful.

[Mon Apr 24 15:26:12 KST 2017] Server is now running.

[Mon Apr 24 15:26:12 KST 2017] wait for client requests...




2. 안드로이드폰에서 앱을 실행시키면 페이링되어있는 디바이스 목록을 보여주는데 이중에  PC를 선택해줍니다.

 




3. 연결에 성공하면 상단에  connected to PC이름이라는 메시지가 출력됩니다.

서버에서 보내준 메시지가 출력됩니다. 

 



이클립스에서  안드로이드 폰의 주소를 출력하며 접속되었다는 것을 확인할 수 있습니다. 

현재 접속된 클라이언트 수는 1입니다. 

[Mon Apr 24 15:27:36 KST 2017] 현재 접속 중인 클라이언트 수: 1
[Mon Apr 24 15:27:36 KST 2017] Open streams...
[Mon Apr 24 15:27:36 KST 2017] Remote device
[Mon Apr 24 15:27:36 KST 2017] address: 5C70A3D86B57
[Mon Apr 24 15:27:36 KST 2017] Client is connected...
[Mon Apr 24 15:27:36 KST 2017] wait for client requests...
[Mon Apr 24 15:27:36 KST 2017] Me : 에코 서버에 접속하셨습니다.
[Mon Apr 24 15:27:36 KST 2017] Me : 보내신 문자를 에코해드립니다.
[Mon Apr 24 15:27:36 KST 2017] ready




4. 안드로이드 폰의 앱에서 문자열을 입력한 후,  SEND를 누르면

 

   



입력한 문자가 다시  에코되는 것을 볼 수 있습니다.

 



이클립스에서도 수신된 문자를 확인 할 수 있으며, 서버가 에코해주었음이 표시됩니다.

 

[Mon Apr 24 15:31:18 KST 2017] 5C70A3D86B57: 한글
[Mon Apr 24 15:31:18 KST 2017] Me : 한글
[Mon Apr 24 15:31:18 KST 2017] ready




5. 다른 안드로이드폰에서 서버에 접속하여 문자열을 보내면 똑같이 동작합니다. 

현재 접속된 클라이언트 수는 2입니다. 

 

[Mon Apr 24 15:36:08 KST 2017] 현재 접속 중인 클라이언트 수: 2
[Mon Apr 24 15:36:08 KST 2017] Open streams...
[Mon Apr 24 15:36:08 KST 2017] Remote device
[Mon Apr 24 15:36:08 KST 2017] address: BCF5AC7C3A47
[Mon Apr 24 15:36:08 KST 2017] Client is connected...
[Mon Apr 24 15:36:08 KST 2017] wait for client requests...
[Mon Apr 24 15:36:08 KST 2017] Me : 에코 서버에 접속하셨습니다.
[Mon Apr 24 15:36:08 KST 2017] Me : 보내신 문자를 에코해드립니다.
[Mon Apr 24 15:36:08 KST 2017] ready
[Mon Apr 24 15:36:13 KST 2017] BCF5AC7C3A47: 태스트
[Mon Apr 24 15:36:13 KST 2017] Me : 태스트
[Mon Apr 24 15:36:13 KST 2017] ready




6. 안드로이드 폰에서 백버튼을 눌러서 앱을 종료하면 클라언트가 접속을 끊었음을 알려줍니다. 

현재 접속중인 클라이언트 수는 1로 줄어듭니다.

[Mon Apr 24 15:44:24 KST 2017] Client has been disconnected
[Mon Apr 24 15:44:24 KST 2017] 현재 접속 중인 클라이언트 수: 1




7. 서버를 종료하기 위해서는 이클립스 콘솔창에 있는 빨간 사각형 아이콘을  클릭합니다. 

 



그리고 빨간색 사각형으로 표시한 X아이콘을 클릭합니다 

 

 

 

 

4. 코드 설명

1. 디바이스에서 블루투스를 지원하는지 체크합니다.

 

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
showErrorDialog("This device is not implement Bluetooth.");
return;
}




2. 디바이스의 블루투스 기능이 활성화 되어있는지 체크합니다.

활성화되어 있지 않다면 사용자에게 블루투스를 켜도록 요청합니다.

 

if (!mBluetoothAdapter.isEnabled()) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, REQUEST_BLUETOOTH_ENABLE);
}






3. 블루투스가 활성화 되어 있다면 showPairedDevicesListDialog() 메소드를 호출합니다.

 

if (!mBluetoothAdapter.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_BLUETOOTH_ENABLE);
}
else {
Log.d(TAG, "Initialisation successful.");

showPairedDevicesListDialog();
}





4. 페어링 되어 있는 블루투스 장치들의 목록을 보여줍니다.

목록에서 블루투스 장치를 선택하면 선택한 디바이스를 인자로 하여 ConnectTask AsyncTask를 실행합니다.

 

public void showPairedDevicesListDialog()
{
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
final BluetoothDevice[] pairedDevices = devices.toArray(new BluetoothDevice[0]);

if ( pairedDevices.length == 0 ){
showQuitDialog( "No devices have been paired.\n"
+"You must pair it with another device.");
return;
}

String[] items;
items = new String[pairedDevices.length];
for (int i=0;i<pairedDevices.length;i++) {
items[i] = pairedDevices[i].getName();
}

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Select device");
builder.setCancelable(false);
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();

// Attempt to connect to the device
ConnectTask task = new ConnectTask(pairedDevices[which]);
task.execute();
}
});
builder.create().show();
}



 

 

 

5. 시리얼 통신(SPP)을 하기 위한 RFCOMM 블루투스 소켓을 생성합니다. (ConnectTask)

 

mBluetoothDevice = bluetoothDevice;
mConnectedDeviceName = bluetoothDevice.getName();

//SPP
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

try {
mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);

 

 

6. 주변 블루투스 디바이스 찾는 것을 중지합니다.

 

mBluetoothAdapter.cancelDiscovery();



7. 블루투스 소켓을 성공적으로 생성했다면 ConnectedTask AsyncTask를 실행합니다. 

 

@Override
protected void onPostExecute(Boolean isSucess) {

if ( isSucess ) {
connected(mBluetoothSocket);
}

  ...........................................

public void connected( BluetoothSocket socket ) {
mConnectedTask = new ConnectedTask(socket);
mConnectedTask.execute();
}





8. 실제 데이터를 주고 받는 처리를 ConnectedTask에서 합니다. 

doInBackground 메소드에서 대기하며 수신되는 문자열이 있으면 받아서  버퍼에 저장합니다.

write 메소드는 문자열을 전송할 때 호출되어 집니다. 

 

private class ConnectedTask extends AsyncTask<Void, String, Boolean> {

    .....................................................

@Override
protected Boolean doInBackground(Void... params) {

byte [] readBuffer = new byte[1024];
int readBufferPosition = 0;


while (true) {

if ( isCancelled() ) return false;

try {

int bytesAvailable = mInputStream.available();

if(bytesAvailable > 0) {

byte[] packetBytes = new byte[bytesAvailable];

mInputStream.read(packetBytes);

for(int i=0;i<bytesAvailable;i++) {

byte b = packetBytes[i];
if(b == '\n')
{
byte[] encodedBytes = new byte[readBufferPosition];
System.arraycopy(readBuffer, 0, encodedBytes, 0,
encodedBytes.length);
String recvMessage = new String(encodedBytes, "UTF-8");

readBufferPosition = 0;

Log.d(TAG, "recv message: " + recvMessage);
publishProgress(recvMessage);
}
else
{
readBuffer[readBufferPosition++] = b;
}
}
}
} catch (IOException e) {

Log.e(TAG, "disconnected", e);
return false;
}
}

}

    ..............................................................................

void write(String msg){

msg += "\n";

try {
mOutputStream.write(msg.getBytes());
mOutputStream.flush();
} catch (IOException e) {
Log.e(TAG, "Exception during send", e );
}

mInputEditText.setText(" ");
}
}




5. 소스코드

5.1. PC용 JAVA 코드

5.1.1. Server.java

 

/*
*
* webnautes@naver.com
*
* 참고
* http://www.kotemaru.org/2013/10/30/android-bluetooth-sample.html
*/

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;

import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector; 
import javax.microedition.io.StreamConnection; 
import javax.microedition.io.StreamConnectionNotifier; 
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Date;


public class Server{
 
    public static void main(String[] args){
   
   
log("Local Bluetooth device...\n");
       
    LocalDevice local = null;
try {

local = LocalDevice.getLocalDevice();
} catch (BluetoothStateException e2) {

}  

    log( "address: " + local.getBluetoothAddress() );
    log( "name: " + local.getFriendlyName() );
   
   
    Runnable r = new ServerRunable();
    Thread thread = new Thread(r);
    thread.start();
   
    }
   
     
    private static void log(String msg) { 
   
        System.out.println("["+(new Date()) + "] " + msg); 
    }

}


class ServerRunable implements Runnable{
 
//UUID for SPP
final UUID uuid = new UUID("0000110100001000800000805F9B34FB", false);
    final String CONNECTION_URL_FOR_SPP = "btspp://localhost:"
    + uuid +";name=SPP Server";
 
    private StreamConnectionNotifier mStreamConnectionNotifier = null
    private StreamConnection mStreamConnection = null;
    private int count = 0;
 
   
@Override
public void run() {

    try {
   
mStreamConnectionNotifier = (StreamConnectionNotifier) Connector
.open(CONNECTION_URL_FOR_SPP);

log("Opened connection successful.");
} catch (IOException e) {

log("Could not open connection: " + e.getMessage());
return;
}
 

    log("Server is now running.");

   
   
        while(true){
       
        log("wait for client requests...");

try {

mStreamConnection = mStreamConnectionNotifier.acceptAndOpen();
} catch (IOException e1) {

log("Could not open connection: " + e1.getMessage() );
}

       
count++;
log("현재 접속 중인 클라이언트 수: " + count);


        new Receiver(mStreamConnection).start();
        }

}

       
   
    class Receiver extends Thread {
   
    private InputStream mInputStream = null;
        private OutputStream mOutputStream = null;
        private String mRemoteDeviceString = null;
        private StreamConnection mStreamConnection = null;
       
       
        Receiver(StreamConnection streamConnection){
       
        mStreamConnection = streamConnection;

try {
   
mInputStream = mStreamConnection.openInputStream();
mOutputStream = mStreamConnection.openOutputStream();

log("Open streams...");
} catch (IOException e) {

log("Couldn't open Stream: " + e.getMessage());

Thread.currentThread().interrupt();
return;
}


try {
       
RemoteDevice remoteDevice
= RemoteDevice.getRemoteDevice(mStreamConnection);

        mRemoteDeviceString = remoteDevice.getBluetoothAddress();
       
log("Remote device");
log("address: "+ mRemoteDeviceString);
       
} catch (IOException e1) {

log("Found device, but couldn't connect to it: " + e1.getMessage());
return;
}

log("Client is connected...");
        }
       
       
    @Override
public void run() {
   
try {

    Reader mReader = new BufferedReader(new InputStreamReader
        ( mInputStream, Charset.forName(StandardCharsets.UTF_8.name())));

    boolean isDisconnected = false;
   
Sender("에코 서버에 접속하셨습니다.");
Sender( "보내신 문자를 에코해드립니다.");
   
while(true){

log("ready");

       
            StringBuilder stringBuilder = new StringBuilder();
            int c = 0;
           
           
while ( '\n' != (char)( c = mReader.read()) ) {

if ( c == -1){

log("Client has been disconnected");

count--;
log("현재 접속 중인 클라이언트 수: " + count);

isDisconnected = true;
Thread.currentThread().interrupt();

break;
}

stringBuilder.append((char) c);
}

            if ( isDisconnected ) break;
           
            String recvMessage = stringBuilder.toString();
        log( mRemoteDeviceString + ": " + recvMessage );

            Sender(recvMessage);
}

} catch (IOException e) {

log("Receiver closed" + e.getMessage());
}
}
   

    void Sender(String msg){
       
            PrintWriter printWriter = new PrintWriter(new BufferedWriter
            (new OutputStreamWriter(mOutputStream,
            Charset.forName(StandardCharsets.UTF_8.name()))));
       
    printWriter.write(msg+"\n");
    printWriter.flush();
   
    log( "Me : " + msg );
    }
}
   
   
    private static void log(String msg) { 
   
        System.out.println("["+(new Date()) + "] " + msg); 
    }
       
}  





5.2. 안드로이드 코드

5.2.1. AndroidManifest.xml

앱에서 블루투스를 사용하기 위해 필요한 퍼미션을 추가해줍니다.

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.tistory.webnautes.android_bluetooth_client">

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />



5.2.2. activity_main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:paddingBottom="10dp"
    android:paddingTop="10dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="connection state : "/>

        <TextView
            android:id="@+id/connection_status_textview"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text=""/>

    </LinearLayout>

    <LinearLayout
        android:weightSum="1"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/input_string_edittext"
            android:hint="input text here"
            android:layout_weight="0.8"
            android:layout_width="0dp"
            android:layout_height="wrap_content"/>

        <Button
            android:id="@+id/send_button"
            android:layout_weight="0.2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Send" />
    </LinearLayout>

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/message_listview"/>

</LinearLayout>




5.2.3. MainActivity.java

 

/*
*
* webnautes@naver.com
*
* 참고
* https://github.com/googlesamples/android-BluetoothChat
* http://www.kotemaru.org/2013/10/30/android-bluetooth-sample.html
*/


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;


public class MainActivity extends AppCompatActivity
{
    private final int REQUEST_BLUETOOTH_ENABLE = 100;

    private TextView mConnectionStatus;
    private EditText mInputEditText;

    ConnectedTask mConnectedTask = null;
    static BluetoothAdapter mBluetoothAdapter;
    private String mConnectedDeviceName = null;
    private ArrayAdapter<String> mConversationArrayAdapter;
    static boolean isConnectionError = false;
    private static final String TAG = "BluetoothClient";

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button sendButton = (Button)findViewById(R.id.send_button);
        sendButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                String sendMessage = mInputEditText.getText().toString();
                if ( sendMessage.length() > 0 ) {
                    sendMessage(sendMessage);
                }
            }
        });
        mConnectionStatus = (TextView)findViewById(R.id.connection_status_textview);
        mInputEditText = (EditText)findViewById(R.id.input_string_edittext);
        ListView mMessageListview = (ListView) findViewById(R.id.message_listview);

        mConversationArrayAdapter = new ArrayAdapter<>( this,
                android.R.layout.simple_list_item_1 );
        mMessageListview.setAdapter(mConversationArrayAdapter);


        Log.d( TAG, "Initalizing Bluetooth adapter...");

        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            showErrorDialog("This device is not implement Bluetooth.");
            return;
        }

        if (!mBluetoothAdapter.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, REQUEST_BLUETOOTH_ENABLE);
        }
        else {
            Log.d(TAG, "Initialisation successful.");

            showPairedDevicesListDialog();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if ( mConnectedTask != null ) {

            mConnectedTask.cancel(true);
        }
    }


    private class ConnectTask extends AsyncTask<Void, Void, Boolean> {

        private BluetoothSocket mBluetoothSocket = null;
        private BluetoothDevice mBluetoothDevice = null;

        ConnectTask(BluetoothDevice bluetoothDevice) {
            mBluetoothDevice = bluetoothDevice;
            mConnectedDeviceName = bluetoothDevice.getName();

            //SPP
            UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");

            try {
                mBluetoothSocket = mBluetoothDevice.createRfcommSocketToServiceRecord(uuid);
                Log.d( TAG, "create socket for "+mConnectedDeviceName);

            } catch (IOException e) {
                Log.e( TAG, "socket create failed " + e.getMessage());
            }

            mConnectionStatus.setText("connecting...");
        }


        @Override
        protected Boolean doInBackground(Void... params) {

            // Always cancel discovery because it will slow down a connection
            mBluetoothAdapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket
            try {
                // This is a blocking call and will only return on a
                // successful connection or an exception
                mBluetoothSocket.connect();
            } catch (IOException e) {
                // Close the socket
                try {
                    mBluetoothSocket.close();
                } catch (IOException e2) {
                    Log.e(TAG, "unable to close() " +
                            " socket during connection failure", e2);
                }

                return false;
            }

            return true;
        }


        @Override
        protected void onPostExecute(Boolean isSucess) {

            if ( isSucess ) {
                connected(mBluetoothSocket);
            }
            else{

                isConnectionError = true;
                Log.d( TAG,  "Unable to connect device");
                showErrorDialog("Unable to connect device");
            }
        }
    }


    public void connected( BluetoothSocket socket ) {
        mConnectedTask = new ConnectedTask(socket);
        mConnectedTask.execute();
    }



    private class ConnectedTask extends AsyncTask<Void, String, Boolean> {

        private InputStream mInputStream = null;
        private OutputStream mOutputStream = null;
        private BluetoothSocket mBluetoothSocket = null;

        ConnectedTask(BluetoothSocket socket){

            mBluetoothSocket = socket;
            try {
                mInputStream = mBluetoothSocket.getInputStream();
                mOutputStream = mBluetoothSocket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "socket not created", e );
            }

            Log.d( TAG, "connected to "+mConnectedDeviceName);
            mConnectionStatus.setText( "connected to "+mConnectedDeviceName);
        }


        @Override
        protected Boolean doInBackground(Void... params) {

            byte [] readBuffer = new byte[1024];
            int readBufferPosition = 0;


            while (true) {

                if ( isCancelled() ) return false;

                try {

                    int bytesAvailable = mInputStream.available();

                    if(bytesAvailable > 0) {

                        byte[] packetBytes = new byte[bytesAvailable];

                        mInputStream.read(packetBytes);

                        for(int i=0;i<bytesAvailable;i++) {

                            byte b = packetBytes[i];
                            if(b == '\n')
                            {
                                byte[] encodedBytes = new byte[readBufferPosition];
                                System.arraycopy(readBuffer, 0, encodedBytes, 0,
                                        encodedBytes.length);
                                String recvMessage = new String(encodedBytes, "UTF-8");

                                readBufferPosition = 0;

                                Log.d(TAG, "recv message: " + recvMessage);
                                publishProgress(recvMessage);
                            }
                            else
                            {
                                readBuffer[readBufferPosition++] = b;
                            }
                        }
                    }
                } catch (IOException e) {

                    Log.e(TAG, "disconnected", e);
                    return false;
                }
            }

        }

        @Override
        protected void onProgressUpdate(String... recvMessage) {

            mConversationArrayAdapter.insert(mConnectedDeviceName + ": " + recvMessage[0], 0);
        }

        @Override
        protected void onPostExecute(Boolean isSucess) {
            super.onPostExecute(isSucess);

            if ( !isSucess ) {


                closeSocket();
                Log.d(TAG, "Device connection was lost");
                isConnectionError = true;
                showErrorDialog("Device connection was lost");
            }
        }

        @Override
        protected void onCancelled(Boolean aBoolean) {
            super.onCancelled(aBoolean);

            closeSocket();
        }

        void closeSocket(){

            try {

                mBluetoothSocket.close();
                Log.d(TAG, "close socket()");

            } catch (IOException e2) {

                Log.e(TAG, "unable to close() " +
                        " socket during connection failure", e2);
            }
        }

        void write(String msg){

            msg += "\n";

            try {
                mOutputStream.write(msg.getBytes());
                mOutputStream.flush();
            } catch (IOException e) {
                Log.e(TAG, "Exception during send", e );
            }

            mInputEditText.setText(" ");
        }
    }


    public void showPairedDevicesListDialog()
    {
        Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
        final BluetoothDevice[] pairedDevices = devices.toArray(new BluetoothDevice[0]);

        if ( pairedDevices.length == 0 ){
            showQuitDialog( "No devices have been paired.\n"
                    +"You must pair it with another device.");
            return;
        }

        String[] items;
        items = new String[pairedDevices.length];
        for (int i=0;i<pairedDevices.length;i++) {
            items[i] = pairedDevices[i].getName();
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Select device");
        builder.setCancelable(false);
        builder.setItems(items, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();

                ConnectTask task = new ConnectTask(pairedDevices[which]);
                task.execute();
            }
        });
        builder.create().show();
    }



    public void showErrorDialog(String message)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Quit");
        builder.setCancelable(false);
        builder.setMessage(message);
        builder.setPositiveButton("OK"new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                if ( isConnectionError  ) {
                    isConnectionError = false;
                    finish();
                }
            }
        });
        builder.create().show();
    }


    public void showQuitDialog(String message)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Quit");
        builder.setCancelable(false);
        builder.setMessage(message);
        builder.setPositiveButton("OK"new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                finish();
            }
        });
        builder.create().show();
    }

    void sendMessage(String msg){

        if ( mConnectedTask != null ) {
            mConnectedTask.write(msg);
            Log.d(TAG, "send message: " + msg);
            mConversationArrayAdapter.insert("Me:  " + msg, 0);
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == REQUEST_BLUETOOTH_ENABLE) {
            if (resultCode == RESULT_OK) {
                //BlueTooth is now Enabled
                showPairedDevicesListDialog();
            }
            if (resultCode == RESULT_CANCELED) {
                showQuitDialog("You need to enable bluetooth");
            }
        }
    }


}



 

반응형

해본 것을 문서화하여 기록합니다.
부족함이 있지만 도움이 되었으면 합니다.


포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
질문을 남겨주면 가능한 빨리 답변드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기

댓글을 달아 주세요

">
  1. 이전 댓글 더보기
  2. thumbnail
    알로베나
    2018.09.27 09:27

    작성자님 안녕하세요.안드로이드에서 라즈베리파이로 보내는 통신을 성공을 하였습니다.
    혹시 라즈베리파이에서 안드로이드 블루투스으로 값을 받아오려고합니다 . 혹시 관련예제나 도움될 사이트가 있을까요??

  3. thumbnail
    이틀동안이나 삽질했습니다ㅠㅠ
    2018.10.30 21:03

    감사합니다. 덕분에 라즈베리를 블루투스 서버로 사용할 수 있게 됐네요!!
    그런데 이 라즈베리파이가 윈도우랑 달라서 이클립스 컴파일할때 계속 오류가 나더라구요
    이틀 동안 삽질하다가 결국 해냈습니다

    정보 필요하신 분들은 여기에 적어놨으니 보시면 될 것 같네요.
    https://blog.naver.com/hch0821/221388267237

  4. thumbnail
    dbstjdlk
    2018.12.26 09:38

    안녕하세요 좋은정보 많이 얻어갑니다.
    한가지 질문이 있는데요.
    위에 소스대로 하고 라즈베리파이와 연동해서 메세지까지 주는것은 되었는데
    메세지를 길게 ex) 안녕하세요 라고 보낸후에
    짧게 ex)안녕 이라고 보내면 안녕 뒤에 전에보냈던 하세요가 뒤따라 붙는데
    이걸 어떻게 해결해주면 좋을까요?

  5. thumbnail
    안녕하세요
    2019.03.11 13:55

    안드로이드에서 문자작성해 전송하는 것이 아니라 버튼에 값을 지정해 놓고 버튼을 누를 때 마다 지정해 놓은 값을 전송하는 어플을 만들고 싶은데 안드로이드코드에서 어느부분을 손대야 할 지 잘 모르겠습니다. 어느부분을 어떤식으로 고쳐야 할 지 조언 부탁드립니다.

  6. thumbnail
    안녕하세요
    2019.03.12 13:42

    void sendMessage(String msg){

    if ( mConnectedTask != null ) {
    mConnectedTask.write(msg);
    Log.d(TAG, "send message: " + msg);
    mConversationArrayAdapter.insert("Me: " + msg, 0);
    }
    }

    이부분을 버튼마다 하나씩 만들어 주면 되는 건가요??

  7. thumbnail
    kimkh0471@g.skku.edu
    2019.05.03 10:24

    안녕하세요. 작성자님의 글을 읽고 블루투스를 이용하여 라즈베리파이와 통신하는데 큰 도움을 받았습니다.

    연결 및 통신 이후 앱 디자인을 수정하던 중 액티비티를 추가해서 전환하게 될 경우, 통신 쪽 문제인지 라즈베리파이로 문자열 전송이 이루어 지지 않았습니다.

    Bluetoothchat 예제 및 구글링을 통해서 service로 어떻게 구현을 하려고 했는데, 해결이 되지 않아 글을 남깁니다.

    혹시 블루투스를 서비스로 해서 앱 제작을 해본 적이 있으신가요?

  8. thumbnail
    zofhf123@naver.com
    2019.05.09 19:26

    pc 서버 자바소스 컴파일 하는데 log( "address: " + local.getBluetoothAddress() ); 에서 오류가 나는데요
    콘솔창에 Exception in thread "main" java.lang.NullPointerException at Server.main(Server.java:38) 이렇게 뜹니다.
    NullPointerException뜨는 이유가 뭘까요...

  9. thumbnail
    young
    2019.05.28 19:46

    블루투스를 이용해서 안드로이드에서 gpio 를 제어할수있나요?

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2019.05.28 20:39 신고

      가능합니다..

      참고로 다음은 아두이노와 한 결과입니다.

      Android 앱에서 ESP8266 WiFi 모듈을 연결한 Arduino Uno 제어하기
      https://webnautes.tistory.com/816

  10. thumbnail
    Favicon of https://kamilake.com BlogIcon Kamilake

    많은 답변 달아 주시느라 수고하셨습니다 :) 지금 시도해보고 있습니다. 감사합니다!

  11. thumbnail
    roes2002
    2019.09.22 20:44

    안녕하세요 좋은 정보 항상 감사합니다. 다름이 아니라 제가 이 포스팅을 보고 안드로이드 스튜디오(스마트폰 단말)에서 이클립스 서버로 텍스트와 이미지를 보내는것을 성공하였는데, 반대로 서버에서 텍스트와 이미지를 보내 단말에서 받아 띄우는 과정을 2주일 넘게 해결을 못하고 있습니다. 혹시 그 방법이나 코드를 알려주실 수 있나요?

  12. thumbnail
    자바공부
    2019.09.30 19:19

    안녕하세요. 질문과 조언을 받고싶어서 댓글남겨요. HM-11이 달려있는 드론과 립모션을 자바를 이용해서 블루투스 페어링을 하고싶은데 하는방법과 과정을 알수있을까요? 블루투스 마스터/슬레이브 자바코드 예시를 찾고싶은데 HM-11과 관련된 글이나 정보가 부족하고 찾지 못하고있어요.

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2019.10.01 01:35 신고

      찾아봤는데.. 아두이노 코드만 보이는 군요..

      https://seeeddoc.github.io/Bluetooth_V4.0_HM-11_BLE_Module/


      아래 링크에 따르면 HM-10과 HM-11이 같은 칩셋을 사용한다고 합니다.
      http://fab.cba.mit.edu/classes/863.15/doc/tutorials/programming/bluetooth.html


      상대적으로 자료가 많은 HM-10 자료를 참고하여 시도해보면 어떨까 싶네요.

  13. thumbnail
    디코딩관련
    2019.10.01 18:35

    안녕하세요 지금 블루투스 통신을 통한 라즈베리파이-안드로이드 관련 작품을 만들고 있는데요
    라즈베리파이에서 보낸 한글이 안드로이드에서 출력 될 때 \uc774\uc'324 이런식으로 받아져서 찾아보니
    디코딩을 해줘야 한다고 하더라구요 그런데 recvMessage를 String recvMessage2 = URLDecoder.decode(recvMessage, "UTF-8"); 이런식으로 해줘도 똑같은 결과가 뜨더라구요
    혹시 이와 관련되서 도움을 얻을 수 있을까요

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2019.10.01 21:34 신고

      다음처럼 해서 출력해보니

      try {
      String decodeStr = URLDecoder.decode("\uc774\uc324", "UTF-8");
      Log.d("@@@", decodeStr);
      } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      Log.d("@@@", e.toString());
      }


      다음처럼 한글로 출력됩니다.
      이쌤


      좀 더 확인해보세요.

  14. thumbnail
    RPIMAN
    2020.05.26 18:50

    혹시 코드에서 UUID 부분은 각자 기기에 맞게 변경해야 하나요? 라즈베리와 안드로이드 통신 하려고합니다!

    • thumbnail
      RPIMAN
      2020.05.26 18:57

      그리고 앱에선 connet 되었다고 뜨는데 라즈베리에선 calling accept() 에서 반응이 없습니디ㅏ ㅜㅜ

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2020.05.26 20:33 신고

      UUID는 통신 규약때문에 쓰기 때문에 기기랑 상관없이 동일해야 합니다.

      라즈베리파이에서 동작하려면 bluecove-2.1.1-SNAPSHOT.jar를 사용하도록 해야 하는데 그렇게 설정하셨나요?

      아래 포스트를 참고해보세요

      https://selpman.tistory.com/236

    • thumbnail
      RPIMAN
      2020.05.27 10:19

      감사합니다!!!!!!!ㅜㅜㅜㅜㅜㅜㅜ

    • thumbnail
      RPIMAN
      2020.05.27 14:57

      https://mine-it-record.tistory.com/230

      위 글의 1번 방법을 참고해서 말씀하신 파일을 추가했는데 변화가 없습니다...ㅜㅜ
      계속 calling accept() 에서 반응이 없습니다 ㅜㅜ

    • thumbnail
      RPIMAN
      2020.05.27 18:12

      제가 이것저것 하다가 port를 3에서 1로 변경하고 연결하였습니다. 그런데 accepted connection from (mac주소) 라고는 떳는데 그뒤로 다시 calling accept() 가 뜨네여ㅛ ㅜㅜㅜㅜ

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2020.05.27 19:36 신고

      제 코드를 보고 테스트를 진행한 포스트니 그대로 따라하면 될겁니다. 차근차근 다시 따라하며 문제가 발생하지 않나 다시 확인해보세요

    • thumbnail
      RPIMAN
      2020.05.27 20:59

      네 다시 포스트를 보고 그대로 진행 하겠습니다 ㅜㅜ

      https://webnautes.tistory.com/1137?category=699571 이포스트에서

      8번에 agent 부분에 agent on 을 하면 agent is already registered 라고 뜹니다.
      그래서 다시 agent off후 on을하면 agent registered라고 정상적으로 떠서 진행하였습니다.

      그리고 18번에 quit를 하면 agent unregistered 와 그아래에있는 부분이 안뜨는데 관련이 있나요??

      안드로이드 스튜디오와 라즈베리 사용중인데 잘 안됩니다 ㅜㅜ

    • thumbnail
      RPIMAN
      2020.05.27 22:33

      다시해보니 됬습니다.. 감사합니다!!

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2020.05.27 22:34 신고

      다행입니다

  15. thumbnail
    drainsource
    2020.06.28 17:29

    안녕하세요. 제가 원하는건 보낸 문자를 다시 리턴하는게 아니라 txt파일 속의 내용을 리턴해주는건데
    예를 들어서 무작위 메세지를 보내더라도 text.txt 란 파일 안의 텍스트가 출력되는거에요.
    자바에서는 구현했는데 안드로이드 스튜디오에서는 어떻게 해야할지 모르겠더라구요.
    혹시 안드로이드 스튜디오 어디 부분을 수정해야 그렇게 될 수 있는지 가르쳐주실 수 있나요?

  16. thumbnail
    kkko
    2020.08.10 10:45

    작성자님 안드로이드 화면 회전시 블루투스 서버에 재접속해야되는 현상이 나타나는데 해결법을 아시는지 질문올립니다.

  17. thumbnail
    Favicon of https://soon-lifestyle.tistory.com BlogIcon 조금만 더

    라즈베리와 안드로이드 블루투스 통신을 하고 있어서 블로그를 참고 하게 되었는데 연결되지 않는 다는 문구 만 계속 뜸니다.
    라즈베리에서 따로 속성처리를 해야하는건가요 ? 아님 다른 방법이 있을까요??

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2020.12.03 18:56 신고

      이글을 보셨나요?
      Raspberry Pi 3와 Android 앱 간에 Bluetooth 통신 테스트

      https://webnautes.tistory.com/995

    • thumbnail
      Favicon of https://soon-lifestyle.tistory.com BlogIcon 조금만 더
      2020.12.04 15:42 신고

      올려주신 https://webnautes.tistory.com/995 이 링크도참고하였는데 어플 을 raspberry pi 와 블루투스 연결 버튼을 누르면 Unable to connect device 로 떠서 연결 부터가
      안된다고 알람이 뜹니다....

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2020.12.04 16:37 신고

      그럼 X 윈도우 환경에서 해보세요. 방법은 윈도우랑 거의 유사합니다

  18. thumbnail
    2021.01.30 21:26

    비밀댓글입니다

  19. thumbnail
    Favicon of https://mangoinjuice.tistory.com BlogIcon 망고인쥬스

    블루투스 기능이 없는 PC라 블루투스 동글을 이용해서(BlueSoleil) 하려고 합니다
    Bluecove에 BlueSoleil과 관련된 코드가 있던데 오류가 나는건 잘 모르겠네요 ㅠㅠ
    안에 들어가봐도 예외처리한 내용들인데 아직 초보라 그런지... 도움을 구해봅니다 ㅠㅠ

    [Fri Mar 19 15:29:40 KST 2021] Local Bluetooth device...
    이까지는 잘 나옵니다..!

    오류내용은 다음과 같습니다.
    Exception in thread "main" java.lang.UnsatisfiedLinkError: 'int com.intel.bluetooth.BluetoothStackBlueSoleil.getLibraryVersion()'
    at com.intel.bluetooth.BluetoothStackBlueSoleil.getLibraryVersion(Native Method)
    at com.intel.bluetooth.BlueCoveImpl.setBluetoothStack(BlueCoveImpl.java:964)
    at com.intel.bluetooth.BlueCoveImpl.detectStack(BlueCoveImpl.java:502)
    at com.intel.bluetooth.BlueCoveImpl.access$500(BlueCoveImpl.java:69)
    at com.intel.bluetooth.BlueCoveImpl$1.run(BlueCoveImpl.java:1044)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:691)
    at com.intel.bluetooth.BlueCoveImpl.detectStackPrivileged(BlueCoveImpl.java:1042)
    at com.intel.bluetooth.BlueCoveImpl.getBluetoothStack(BlueCoveImpl.java:1035)
    at javax.bluetooth.LocalDevice.getLocalDeviceInstance(LocalDevice.java:75)
    at javax.bluetooth.LocalDevice.getLocalDevice(LocalDevice.java:95)
    at Server.main(Server.java:42)

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2021.03.19 15:58 신고

      구글에서 찾아봐도 버전을 바꾸어서 해결되었다는 말만 보이네요.

      https://stackoverflow.com/a/13937436


      블루투스 동작이 잘되는지 확인하고 문제없다면 라이브러리 버전을 바꿔서 해보는 수밖에 없어보입니다

    • thumbnail
      Favicon of https://mangoinjuice.tistory.com BlogIcon 망고인쥬스
      2021.03.19 16:01 신고

      도전해보겠습니다...! 댓글 빨리 달아주셔서 감사합니다...! ㅠㅠ

  20. thumbnail
    Favicon of https://blue-orange.tistory.com BlogIcon 미사구돌

    하 완전 프로젝트 관리를 계속 해주셔가지고 잘 돌아가네요.
    이클립스가 뭔가 프로젝트 안에 모듈을 만드는 구조로 되어있어서
    라이브러리 추가시 "modulepath"로 넣어야 하나 봅니다. 아니면 제가 프로젝트를 처음 만들때 모듈이 생기도록 한 것인지 ㅋㅋㅋ

    아무튼 완전 좋은 예제고 좋은 추우천추천 프로젝트라구요 감사합니다.

  21. thumbnail
    Favicon of https://adc6981.tistory.com BlogIcon 개미31

    안녕하세요
    코딩 공부하는 학생입니다.
    어플에서 발생한 약간의 오류는 모두 정상적으로 해결했습니다.
    하지만 이클립스에서 발생한 오류를 해결하지 못했습니다.
    블로그에 나와있는 내용을 천천히 따라해 가며 모든 설정을 하고
    코드 복사후 실행을 해봤는데 아래와 같은 오류가 나왔습니다.
    Error: Unable to initialize main class Server
    Caused by: java.lang.NoClassDefFoundError: javax/bluetooth/BluetoothStateException
    이러한 에러가 나왔는데, 어떻게 해결해야 하나요..?

    • thumbnail
      Favicon of https://webnautes.tistory.com BlogIcon webnautes
      2021.10.17 08:04 신고

      포스트를 업데이트했습니다. jar 파일 추가하는 부분이 바뀌어서 발생한 에러였습니다.