include google_analytics Android Bluetooth 연동 | Yang HeeWoong
Home Android Bluetooth 연동
Post
Cancel

Android Bluetooth 연동

안드로이드 블루투스 기능에 대해 정리하였음.
Android Developer에 있는 내용과 포그라운드 서비스를 이용하여 블루투스 기능을 구현함.

1. 블루투스 권한 설정


1
안드로이드 12부터 새로운 블루투스 권한이 추가됨.

2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void checkPermissions() {
        String[] permission_list = {
                Manifest.permission.BLUETOOTH_CONNECT,
        };
        for (String permission : permission_list) {
            int check = checkCallingOrSelfPermission(permission); // 권한 혀용 여부
            // 권한 거부 상태
            if (check == PackageManager.PERMISSION_DENIED) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    requestPermissions(permission_list, 0); // 권한 허용 여부 Dialog 출력
                }
            } else { // 권한 허용 상태
                permission_state = 1; // 권한 허용 상태로 변경
            }
        }
    }

블루투스 권한을 설정해줘야 블루투스 기능 사용 가능.

2. 앱에서 블루투스 켜기


3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, BT_REQUEST_ENABLE);
// 거부 또는 허용을 눌렀을 때
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case BT_REQUEST_ENABLE:
                if (resultCode == RESULT_OK) {
                    //Toast.makeText(getApplicationContext(), "블루투스 활성화", Toast.LENGTH_LONG).show();
                    binding.tvBluetoothStatus.setTextColor(Color.GREEN);
                    binding.tvBluetoothStatus.setText("Bluetooth ON");
                    binding.btnSearch.setEnabled(true);
                } else if (resultCode == RESULT_CANCELED) {
                    //Toast.makeText(getApplicationContext(), "취소", Toast.LENGTH_LONG).show();
                    binding.tvBluetoothStatus.setTextColor(Color.RED);
                    binding.tvBluetoothStatus.setText("Bluetooth OFF");
                    binding.btnSearch.setEnabled(false);
                }
                break;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

앱에서 블루투스를 켤 수 있도록 설정해줌.

3. 블루투스 장치 스캔


4

1
2
3
 // 블루투스 장치 검색 브로드캐스트 리시버 설정
        IntentFilter filter_search = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(receiver_search, filter_search);
1
2
3
4
5
6
7
8
9
10
        absBinding.btnSearch.setOnClickListener(new View.OnClickListener() { // 주변 블루투스 장치 검색
            @Override
            public void onClick(View view) {
                if (!searchedBTArrayAdapter.isEmpty()) {
                    searchedBluetoothDevice.clear();
                    searchedBTArrayAdapter.notifyDataSetChanged();
                }
                search();
            }
        });
1
2
3
4
5
6
    public void search() {
        if (bluetoothAdapter.isDiscovering()) { // 이미 검색 중인 경우
            bluetoothAdapter.cancelDiscovery(); // 검색 중지
        }
        bluetoothAdapter.startDiscovery();
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    private final BroadcastReceiver receiver_search = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) { // 블루투스 장치 검색 리시버
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                @SuppressLint("MissingPermission")
                String deviceName = device.getName();
                String deviceHardwareAddress = device.getAddress(); // MAC address
                if(deviceName != null && deviceHardwareAddress != null) { // 이름과 주소가 null이 아닌 경우에만 등록
                    Log.i("검색된 기기: ", deviceName);
                    Log.i("검색된 기기 주소", deviceHardwareAddress);
                    searchedHashMap = new HashMap<>();
                    searchedHashMap.put("name", deviceName);
                    searchedHashMap.put("address", deviceHardwareAddress);
                    searchedHashMap.put("connectState", "연결 안됨");
                    searchedBluetoothDevice.add(searchedHashMap);

                    if(pairedBluetoothDevice.size() > 0) {
                        for(int i=0;i<pairedBluetoothDevice.size();i++) { // 등록된 블루투스 장치들과 검색된 블루투스 장치들을 비교하여 중복된 값이 있으면 없앰
                            String name = pairedBluetoothDevice.get(i).get("name");
                            String address = pairedBluetoothDevice.get(i).get("address");
                            if(deviceName.equals(name) && deviceHardwareAddress.equals(address)) {
                                for(int j=0;j<searchedBluetoothDevice.size();j++) {
                                    if (searchedBluetoothDevice.get(j).get("name").equals(name)) {
                                        searchedBluetoothDevice.remove(j);
                                    }
                                }
                            }
                        }
                    }
                    searchedBTArrayAdapter.notifyDataSetChanged();
                }
            }
        }
    };

블루투스를 켜야만 블루투스 장치 검색이 가능하도록 구현.

4. 블루투스 장치 연결


5
6

1
2
3
4
5
6
7
8
9
10
11
12
public ConnectThread(BluetoothDevice device, int pos, int div) {
        mmDevice = device;
        position = pos; // 선택한 장치 포지션 구분
        division = div; // 등록된 기기 또는 검색된 기기 구분
        BluetoothSocket tmp = null;
        try {
            tmp = createBluetoothSocket(mmDevice);
        } catch (IOException e) {
            Log.e(TAG, "Socket's create() method failed", e);
        }
        mmSocket = tmp;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
   public void run() {
        bluetoothAdapter.cancelDiscovery(); // 블루투스 장치 검색 중지
        try {
            mmSocket.connect(); // 블루투스 장치 연결
        } catch (IOException connectException) {
            try {
                mmSocket.close(); // 소켓 닫기
                (BluetoothSearchActivity.context_BS).stopService(new Intent( (BluetoothSearchActivity.context_BS).getApplicationContext(), BluetoothConnectService.class)); // 백그라운드 장치 연결 서비스 중지
            } catch (IOException closeException) {
                Log.e(TAG, "Could not close the client socket", closeException);
            }
            return;
        }
        // 블루투스 장치와 연결 성공 시 ConnectedThread 실행
        manageConnectedSocket(mmSocket);
    }

연결할 블루투스 장치를 누르면 포그라운드 서비스가 시작되고 장치에 연결하는 ConnectThread 실행.

5. 연결된 블루투스 장치의 데이터 수신


1
2
3
4
5
6
7
8
9
10
11
 public ConnectedThread(BluetoothSocket socket) {
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) { }
        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
    public void run() {
        readBufferPosition = 0; 
        readBuffer = new byte[1024]; // 데이터를 수신하기 위한 버퍼 생성
        while (true) {
            try {
                int byteAvailable = mmInStream.available(); // 데이터 수신 확인
                if(byteAvailable > 0) {  // 데이터가 수신된 경우
                    byte[] bytes = new byte[byteAvailable];  // 입력 스트림에서 바이트 단위로 읽음
                    mmInStream.read(bytes);     // 입력 스트림 바이트를 한 바이트씩 읽음
                    for(int i = 0; i < byteAvailable; i++) {
                        byte tempByte = bytes[i];    // 개행문자를 기준으로 나눔(한줄)
                        if(tempByte == '\n') { // readBuffer 배열을 encodedBytes로 복사
                            byte[] encodedBytes = new byte[readBufferPosition];
                            System.arraycopy(readBuffer, 0, encodedBytes, 0, encodedBytes.length);
                            final String text = new String(encodedBytes, "US-ASCII");    // 인코딩된 바이트 배열을 문자열로 변환
                            readBufferPosition = 0;
                            Log.i("수신받은 데이터 값 : ", text);
                            ((MainActivity) MainActivity.context_main).runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText((MainActivity.context_main), "수신 값: " + text, Toast.LENGTH_SHORT).show();
                                }
                            });
                        } // 개행 문자가 아닐 경우
                        else {
                            readBuffer[readBufferPosition++] = tempByte;
                        }
                    }
                }
                Thread.sleep(80); // 0.08초 대기
            } catch (IOException e) {
                break;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (NullPointerException e) {
                e.printStackTrace();
            }
        }
    }

장치가 연결되어 있는 동안 ConnectedThread 실행되어 장치가 보내는 데이터 수신 가능.

6. 참고 사이트


안드로이드 블루투스 개요
bugwhale.tistory
코드는 여기서 확인 가능

This post is licensed under CC BY 4.0 by the author.

Android Git 연동

-