Android 향상 의 Android 핸드폰 과 BLE 단말기 통신

15915 단어 Android
최근 웨 어 러 블 기기 가 크게 발전 해 관련 기술 도 활 기 를 띠 고 있 는데 그 중 하 나 는 BLE(Bluetooth Low Energy)다.BLE 는 블 루 투 스 4.0 의 핵심 Profile 로,주요 기능 은 빠 른 검색,빠 른 연결,초 저 전력 소모 로 연결 과 전송 데 이 터 를 유지 하 는 것 이 며,약점 은 데이터 전송 속도 가 낮 고 BLE 의 저 전력 소모 특성 때문에 웨 어 러 블 기기 에 보편적으로 사용 된다 는 것 이다.Android 4.3 은 BLE API 를 지원 하기 시 작 했 습 니 다.따라서 고객 님 들 은 본 코드 를 블 루 투 스 4.0 과 Android 4.3 이상 의 시스템 에서 실행 하 십시오.또한 본 고 에서 사용 하 는 BLE 단말 기 는 블 루 투 스 4.0 의 직렬 블 루 투 스 모듈 입 니 다.
주:필자 의 i9100 이 4.4 시스템 을 닦 은 후에 도 BLE 블 루 투 스 모듈 과 통신 할 수 있 습 니 다.
BLE 은 세 부분 Service,Characteristic,Descriptor 로 나 뉘 는데 이 세 부분 은 모두 UUID 가 유일한 표시 부호 로 한다.블 루 투 스 4.0 의 터미널 은 여러 개의 서 비 스 를 포함 할 수 있 습 니 다.하나의 Service 는 여러 개의 Characteristic 을 포함 할 수 있 습 니 다.하나의 Characteristic 은 하나의 Value 와 여러 개의 Descriptor 를 포함 하고 하나의 Descriptor 는 하나의 Value 를 포함 합 니 다.일반적으로 Characteristic 은 핸드폰 과 BLE 단말기 가 데 이 터 를 교환 하 는 관건 이다.Characteristic 은 권한 과 관련 된 필드 가 많다.예 를 들 어 PERMISSION 과 PROPERTY 이다.그 중에서 가장 자주 사용 하 는 것 은 PROPERTY 이다.본 고 에서 사용 하 는 BLE 블 루 투 스 모듈 은 표준 적 인 Characteristic 의 PERMISSION 이 없다.Characteristic 의 PROPERTY 는 비트 연산 자 조합 을 통 해 읽 기와 쓰기 속성 을 설정 할 수 있 습 니 다.예 를 들 어 READ|WRITE,READ|WRITENO_RESPONSE|NOTIfy.따라서 PROPERTY 를 읽 은 후 사용 하 는 조합 으로 분해 해 야 합 니 다(본 코드 는 이 분해 방법 을 포함 하고 있 습 니 다).
본 고 는 Android 4.3 Sample 의 BluetoothLeGatt 에서 코드 를 바 꾸 고 불필요 한 코드 를 제거 하 며 얻 은 BLE 장치 정 보 는 모두 Log 를 통 해 얻 을 수 있 습 니 다.그리고 필요 한 읽 기와 쓰기 블 루 투 스 방법 도 있 습 니 다.여러분 이 한 번 보면 알 수 있 을 정도 로 간소화 한 셈 입 니 다.본 논문 의 전체 코드 는 여 기 를 클릭 할 수 있 습 니 다본 사이트 다운로드
그 다음 에 본 논문 이 실 행 된 결 과 를 붙 입 니 다.먼저 BLE 장 치 를 연결 한 후에 모든 Service,Characteristic,Descriptor 를 들 고 핸드폰 은 Characteristic uid=0000ffe1-0000-1000-0805 f9b34fb 에'send data->'문자열 을 기록 합 니 다.BLE 단말 기 는 데 이 터 를 받 아 직렬 포트 를 통 해 PC 직렬 포트 조수 에 게 전 달 됩 니 다.
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service uuid:00001800-0000-1000-8000-00805f9b34fb
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a00-0000-1000-8000-00805f9b34fb
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a01-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a02-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ|WRITE|
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a03-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ|WRITE|
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char uuid:00002a04-0000-1000-8000-00805f9b34fb
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service uuid:00001801-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:00002a05-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:INDICATE
04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service uuid:0000ffe0-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:0000ffe1-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:READ|WRITE_NO_RESPONSE|NOTIFY|
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002901-0000-1000-8000-00805f9b34fb
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:26.025: E/DeviceScanActivity(12254): onCharRead BLE DEVICE read 0000ffe1-0000-1000-8000-00805f9b34fb -> 00
여기 빨 간 글 자 는 BluetoothGattCallback 의 onCharacteristicRead()리 셋 으로 Log 를 칩 니 다.

아래 Log 는 PC 의 직렬 도구 로 BLE 모듈 을 통 해 보 내 집 니 다.BluetoothGattCallback 의 onCharacteristicChanged()에서 Log 를 칩 니 다.
04-21 18:30:18.260: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:18.745: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.085: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.350: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.605: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.835: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.055: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.320: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.510: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.735: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:21.000: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
다음은 본문의 핵심 코드 를 붙인다.

public class DeviceScanActivity extends ListActivity {
 private final static String TAG = DeviceScanActivity.class.getSimpleName();
 private final static String UUID_KEY_DATA = "0000ffe1-0000-1000-8000-00805f9b34fb";

  private LeDeviceListAdapter mLeDeviceListAdapter;
  /**  BLE  */
  private BluetoothAdapter mBluetoothAdapter;
  /**  BLE  */
  private BluetoothLeClass mBLE;
  private boolean mScanning;
  private Handler mHandler;

  // Stops scanning after 10 seconds.
  private static final long SCAN_PERIOD = 10000;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getActionBar().setTitle(R.string.title_devices);
    mHandler = new Handler();
    // Use this check to determine whether BLE is supported on the device. Then you can
    // selectively disable BLE-related features.
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
      Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
      finish();
    }
    // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
    // BluetoothAdapter through BluetoothManager.
    final BluetoothManager bluetoothManager =
        (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();
    // Checks if Bluetooth is supported on the device.
    if (mBluetoothAdapter == null) {
      Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
      finish();
      return;
    }
    //    
    mBluetoothAdapter.enable();
    mBLE = new BluetoothLeClass(this);
    if (!mBLE.initialize()) {
      Log.e(TAG, "Unable to initialize Bluetooth");
      finish();
    }
    //  BLE   Service   
    mBLE.setOnServiceDiscoverListener(mOnServiceDiscover);
    //  BLE         
    mBLE.setOnDataAvailableListener(mOnDataAvailable);
  }
  @Override
  protected void onResume() {
    super.onResume();

    // Initializes list view adapter.
    mLeDeviceListAdapter = new LeDeviceListAdapter(this);
    setListAdapter(mLeDeviceListAdapter);
    scanLeDevice(true);
  }
  @Override
  protected void onPause() {
    super.onPause();
    scanLeDevice(false);
    mLeDeviceListAdapter.clear();
    mBLE.disconnect();
  }
  @Override
  protected void onStop() {
    super.onStop();
    mBLE.close();
  }
  @Override
  protected void onListItemClick(ListView l, View v, int position, long id) {
    final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
    if (device == null) return;
    if (mScanning) {
      mBluetoothAdapter.stopLeScan(mLeScanCallback);
      mScanning = false;
    }
    mBLE.connect(device.getAddress());
  }
  private void scanLeDevice(final boolean enable) {
    if (enable) {
      // Stops scanning after a pre-defined scan period.
      mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
          mScanning = false;
          mBluetoothAdapter.stopLeScan(mLeScanCallback);
          invalidateOptionsMenu();
        }
      }, SCAN_PERIOD);
      mScanning = true;
      mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
      mScanning = false;
      mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
    invalidateOptionsMenu();
  }
  /**
   *    BLE       
   */
  private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener(){

 @Override
 public void onServiceDiscover(BluetoothGatt gatt) {
  displayGattServices(mBLE.getSupportedGattServices());
 }
  };
  /**
   *   BLE         
   */
  private BluetoothLeClass.OnDataAvailableListener mOnDataAvailable = new OnDataAvailableListener(){
   /**
   * BLE         
   */
 @Override
 public void onCharacteristicRead(BluetoothGatt gatt,
  BluetoothGattCharacteristic characteristic, int status) {
  if (status == BluetoothGatt.GATT_SUCCESS) 
  Log.e(TAG,"onCharRead "+gatt.getDevice().getName()
   +" read "
   +characteristic.getUuid().toString()
   +" -> "
   +Utils.bytesToHexString(characteristic.getValue()));
 }
   /**
   *   BLE        
   */
 @Override
 public void onCharacteristicWrite(BluetoothGatt gatt,
  BluetoothGattCharacteristic characteristic) {
  Log.e(TAG,"onCharWrite "+gatt.getDevice().getName()
   +" write "
   +characteristic.getUuid().toString()
   +" -> "
   +new String(characteristic.getValue()));
 }
  };
  // Device scan callback.
  private BluetoothAdapter.LeScanCallback mLeScanCallback =
      new BluetoothAdapter.LeScanCallback() {
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          mLeDeviceListAdapter.addDevice(device);
          mLeDeviceListAdapter.notifyDataSetChanged();
        }
      });
    }
  };
  private void displayGattServices(List<BluetoothGattService> gattServices) {
    if (gattServices == null) return;
    for (BluetoothGattService gattService : gattServices) {
     //-----Service     -----//
     int type = gattService.getType();
      Log.e(TAG,"-->service type:"+Utils.getServiceType(type));
      Log.e(TAG,"-->includedServices size:"+gattService.getIncludedServices().size());
      Log.e(TAG,"-->service uuid:"+gattService.getUuid());
      
      //-----Characteristics     -----//
      List<BluetoothGattCharacteristic> gattCharacteristics =gattService.getCharacteristics();
      for (final BluetoothGattCharacteristic gattCharacteristic: gattCharacteristics) {
        Log.e(TAG,"---->char uuid:"+gattCharacteristic.getUuid());
        int permission = gattCharacteristic.getPermissions();
        Log.e(TAG,"---->char permission:"+Utils.getCharPermission(permission));
        int property = gattCharacteristic.getProperties();
        Log.e(TAG,"---->char property:"+Utils.getCharPropertie(property));
        byte[] data = gattCharacteristic.getValue();
     if (data != null && data.length > 0) {
      Log.e(TAG,"---->char value:"+new String(data));
     }
     //UUID_KEY_DATA             Characteristic
     if(gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA)){      
      //      Characteristic  ,   mOnDataAvailable.onCharacteristicRead()
      mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
             mBLE.readCharacteristic(gattCharacteristic);
            }
          }, 500);
      //  Characteristic     ,             mOnDataAvailable.onCharacteristicWrite()
      mBLE.setCharacteristicNotification(gattCharacteristic, true);
      //      
      gattCharacteristic.setValue("send data->");
      //         
      mBLE.writeCharacteristic(gattCharacteristic);
     }
     //-----Descriptors     -----//
  List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();
  for (BluetoothGattDescriptor gattDescriptor : gattDescriptors) {
   Log.e(TAG, "-------->desc uuid:" + gattDescriptor.getUuid());
   int descPermission = gattDescriptor.getPermissions();
   Log.e(TAG,"-------->desc permission:"+ Utils.getDescPermission(descPermission));
   byte[] desData = gattDescriptor.getValue();
   if (desData != null && desData.length > 0) {
   Log.e(TAG, "-------->desc value:"+ new String(desData));
   }
      }
      }
    }//
  }
}

관심 있 는 독자 들 은 코드 의 운행 상황 을 직접 테스트 하여 여러분 의 안 드 로 이 드 프로젝트 개발 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기