수색…


소개

이 문서는 원본 문서를 보완하기위한 것으로, Android 5.0 (API 21)에서 소개 된 최신 Bluetooth LE API에 중점을 둡니다. 중앙 및 주변 장치 역할뿐만 아니라 스캔 및 광고 작업을 시작하는 방법도 다룹니다.

BLE 장치 찾기

Bluetooth API를 사용하려면 다음 권한이 필요합니다.

android.permission.BLUETOOTH
android.permission.BLUETOOTH_ADMIN

Android 6.0 ( API 레벨 23 ) 이상의 기기를 타겟팅하고 스캔 / 광고 작업을 수행하려면 위치 권한이 필요합니다.

android.permission.ACCESS_FINE_LOCATION

또는

android.permission.ACCESS_COARSE_LOCATION

참고 - Android 6.0 (API 레벨 23) 이상인 기기에서도 위치 서비스를 사용하도록 설정해야합니다.

BluetoothAdapter 객체는 스캔 / 광고 작업을 시작하는 데 필요합니다.

BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
bluetoothAdapter = bluetoothManager.getAdapter();

BluetoothLeScanner 클래스의 startScan (ScanCallback callback) 메소드는 스캔 작업을 시작하는 가장 기본적인 방법입니다. 결과를 받으려면 ScanCallback 개체가 필요합니다.

bluetoothAdapter.getBluetoothLeScanner().startScan(new ScanCallback() {
     @Override
     public void onScanResult(int callbackType, ScanResult result) {
     super.onScanResult(callbackType, result);
     Log.i(TAG, "Remote device name: " + result.getDevice().getName());
       }
    });

GATT 서버에 연결

원하는 BluetoothDevice 객체를 connectGatt() Context 객체를 매개 변수로 사용하는 connectGatt() 메서드, BLE 장치에 자동으로 연결할지 여부를 나타내는 부울 값 및 연결 이벤트 및 클라이언트 작업이있는 BluetoothGattCallback 참조를 사용하여 연결할 수 있습니다 결과가 전달됩니다.

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        device.connectGatt(context, false, bluetoothGattCallback, BluetoothDevice.TRANSPORT_AUTO);
    } else {
        device.connectGatt(context, false, bluetoothGattCallback);
    }

연결을 수신하기 위해 BluetoothGattCallback의 onConnectionStateChange 를 재정의하십시오. 연결 해제 이벤트 :

    BluetoothGattCallback bluetoothGattCallback =
        new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
            int newState) {
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            Log.i(TAG, "Connected to GATT server.");

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            
            Log.i(TAG, "Disconnected from GATT server.");
        }
    }
   };

특성 작성 및 독해

Gatt Server에 연결되면 서버의 특성을 읽고 쓰면서 상호 작용할 것입니다. 이렇게하려면 먼저이 서버에서 사용할 수있는 서비스와 각 서비스에서 사용할 수있는 특성을 찾아야합니다.

 @Override
 public void onConnectionStateChange(BluetoothGatt gatt, int status,
        int newState) {
    if (newState == BluetoothProfile.STATE_CONNECTED) {
        Log.i(TAG, "Connected to GATT server.");
        gatt.discoverServices();

    }
. . .

 @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
             List<BluetoothGattService> services = gatt.getServices();
                for (BluetoothGattService service : services) {
                    List<BluetoothGattCharacteristic> characteristics = service.getCharacteristics();
                    for (BluetoothGattCharacteristic characteristic : characteristics) { 
                        ///Once you have a characteristic object, you can perform read/write
                        //operations with it         
                    }
                 }
              }
            }

기본 쓰기 작업은 다음과 같이 진행됩니다.

characteristic.setValue(newValue);
characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
gatt.writeCharacteristic(characteristic);

쓰기 프로세스가 완료되면 BluetoothGattCallbackonCharacteristicWrite 메서드가 호출됩니다.

    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
        Log.d(TAG, "Characteristic " + characteristic.getUuid() + " written);
    }

기본 쓰기 작업은 다음과 같이 진행됩니다.

gatt.readCharacteristic(characteristic);

쓰기 프로세스가 완료되면 BluetoothGattCallbackonCharacteristicRead 메소드가 호출됩니다.

@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
  super.onCharacteristicRead(gatt, characteristic, status);
  byte[] value = characteristic.getValue();
  }

Gatt Server에서 알림 구독

특성 값이 변경되면 Gatt Server에 통지하도록 요청할 수 있습니다.

gatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
    UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);

서버의 모든 알림은 BluetoothGattCallback의 onCharacteristicChanged 메소드에서 수신됩니다.

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicChanged(gatt, characteristic);
        byte[] newValue = characteristic.getValue();
}

BLE 장치 광고

Bluetooth LE Advertising을 사용하면 먼저 연결을 설정하지 않고도 주변의 모든 장치에 데이터 패키지를 브로드 캐스트 할 수 있습니다. 31 바이트의 광고 데이터에는 엄격한 제한이 있음을 명심하십시오. 기기를 광고하는 것은 다른 사용자가 나와 연결하도록하는 첫 걸음입니다.

모든 장치가 Bluetooth LE Advertising을 지원하는 것은 아니기 때문에, 첫 단계는 장치가이를 지원하는 데 필요한 모든 요구 사항을 갖추고 있는지 확인하는 것입니다. 그런 다음 BluetoothLeAdvertiser 객체를 초기화 할 수 있으며 광고 작업을 시작할 수 있습니다.

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && bluetoothAdapter.isMultipleAdvertisementSupported())
        {
            BluetoothLeAdvertiser advertiser = bluetoothAdapter.getBluetoothLeAdvertiser();

            AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
           //Define a service UUID according to your needs                
           dataBuilder.addServiceUuid(SERVICE_UUID);
            dataBuilder.setIncludeDeviceName(true);


             AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
             settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
             settingsBuilder.setTimeout(0);

             //Use the connectable flag if you intend on opening a Gatt Server
             //to allow remote connections to your device.
             settingsBuilder.setConnectable(true);

            AdvertiseCallback advertiseCallback=new AdvertiseCallback() {
            @Override
            public void onStartSuccess(AdvertiseSettings settingsInEffect) {
                super.onStartSuccess(settingsInEffect);
                Log.i(TAG, "onStartSuccess: ");
            }

            @Override
            public void onStartFailure(int errorCode) {
                super.onStartFailure(errorCode);
                Log.e(TAG, "onStartFailure: "+errorCode );
            }
          };
advertising.startAdvertising(settingsBuilder.build(),dataBuilder.build(),advertiseCallback);
        }

Gatt Server 사용

장치가 주변 장치로 작동하려면 먼저 BluetoothGattServer 를 열고 하나 이상의 BluetoothGattService 및 하나의 BluetoothGattCharacteristic 채워야합니다.

BluetoothGattServer server=bluetoothManager.openGattServer(context, bluetoothGattServerCallback);

BluetoothGattService service = new BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);

전체 쓰기, 읽기 및 알림 권한이있는 BluetoothGattCharacteristic의 예입니다. 필요에 따라이 특성을 부여하는 사용 권한을 세부적으로 조정할 수 있습니다.

BluetoothGattCharacteristic characteristic = new BluetoothGattCharacteristic(CHARACTERISTIC_UUID,
                    BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE |
                            BluetoothGattCharacteristic.PROPERTY_NOTIFY,
                    BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE);

characteristic.addDescriptor(new BluetoothGattDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"), BluetoothGattCharacteristic.PERMISSION_WRITE));

service.addCharacteristic(characteristic);

server.addService(service);

BluetoothGattServerCallback 당신의 관련된 모든 이벤트 수신을 담당 BluetoothGattServer :

BluetoothGattServerCallback bluetoothGattServerCallback= new BluetoothGattServerCallback() {
                @Override
                public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
                    super.onConnectionStateChange(device, status, newState);
                }

                @Override
                public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
                    super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
                }

                @Override
                public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
                    super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
                }

                @Override
                public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
                    super.onDescriptorReadRequest(device, requestId, offset, descriptor);
                }

                @Override
                public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
                    super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
                }

특성 또는 기술자에 대한 쓰기 / 읽기 요청을받을 때마다 요청을 성공적으로 완료 할 수 있도록 응답을 보내야합니다.

@Override
 public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
    super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
    server.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, YOUR_RESPONSE);
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow