2014-11-05 11 views
1

맞춤 장치에 대한 알림을 받고 싶습니다. Lightblue 앱을 사용하는 iOS에서 알림을받을 수 있기 때문에 기기가 작동하고 있음을 안다. 나는 넥서스 5와 samsung s4 (둘 다 kitkats)로 시도했다. 아무것도 작동하는 것 같습니다. 내 "onCharacteristicChanged"가 호출되지 않습니다.안드로이드에서 BLE 알림을받는 방법?

MainActivity.java

package com.foo.ble; 

import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothManager; 
import android.content.Context; 
import android.os.Bundle; 
import android.os.Handler; 
import android.util.Log; 


public class MainActivity extends Activity implements BluetoothAdapter.LeScanCallback { 
    private BluetoothAdapter adapter; 

    final private static char[] hexArray = "ABCDEF".toCharArray(); 
    private Callback callback; 

    /** 
    * Converts 0xfe to "FE" 
    * @return hex representation of the adScanned 
    */ 
    public static String getPayload(final byte[] adScanned) { 
     if (adScanned == null) return "N/A"; 

     final char[] hexChars = new char[adScanned.length * 2]; 
     for (int j = 0; j < adScanned.length; j++) { 
      final int v = adScanned[j] & 0xFF; 
      hexChars[j * 2] = hexArray[v >>> 4]; 
      hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
     } 
     return new String(hexChars); 
    } 

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

     BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 
     adapter = manager.getAdapter(); 
     callback = new Callback(); 

     Handler handler = new Handler(); 
     handler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       adapter.stopLeScan(MainActivity.this); 
      } 
     }, 3*10000); 

     runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 
       adapter.startLeScan(MainActivity.this); 
      } 
     }); 
    } 

    @Override 
    public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) { 
     if (device.getAddress().equals("CE:AD:09:F2:BB:DC")) { 
      Log.d("foo", "onLeScan payload:" + getPayload(scanRecord)); 
      adapter.stopLeScan(this); 
      runOnUiThread(new Runnable() { 
       @Override 
       public void run() { 
        device.connectGatt(MainActivity.this, true, callback); 
       } 
      }); 
     } 
    } 

    @Override 
    protected void onDestroy() { 
     callback.close(); 
    } 
} 

Callback.java

package com.foo.ble; 

import android.bluetooth.BluetoothGatt; 
import android.bluetooth.BluetoothGattCallback; 
import android.bluetooth.BluetoothGattCharacteristic; 
import android.bluetooth.BluetoothGattDescriptor; 
import android.bluetooth.BluetoothProfile; 
import android.util.Log; 

import java.util.UUID; 

public class Callback extends BluetoothGattCallback { 
    final static UUID SERVICE = UUID.fromString("something1"); 
    final static UUID ADV_CHAR = UUID.fromString("something2"); 
    final static UUID ADV_DESCRIPTOR = UUID.fromString("something3"); 

    BluetoothGatt gatt; 

    public void close() { 
     if (gatt == null) return; 
     Log.d("foo", "close with gatt"); 

     gatt.disconnect(); 
     gatt.close(); 
     gatt = null; 
    } 

    @Override 
    public void onConnectionStateChange(final BluetoothGatt gatt, final int status, 
             final int newState) { 
     Log.d("foo", "onConnectionStateChange"); 
     if (newState == BluetoothProfile.STATE_CONNECTED) { 
      Log.d("foo", "status connected"); 
      this.gatt = gatt; 
      gatt.discoverServices(); 
     } 
    } 

    @Override 
    public void onServicesDiscovered(final BluetoothGatt gatt, final int status) { 
     Log.d("foo", "onServicesDiscovered"); 
     if (status == BluetoothGatt.GATT_SUCCESS) { 
      final BluetoothGattCharacteristic characteristic = 
        gatt.getService(SERVICE).getCharacteristic(ADV_CHAR); 
      final BluetoothGattDescriptor descriptor = 
        characteristic.getDescriptor(ADV_DESCRIPTOR); 
      descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); 
      gatt.setCharacteristicNotification(characteristic, true); 
      gatt.writeDescriptor(descriptor); 
     } 
    } 

    @Override 
    public void onCharacteristicRead(final BluetoothGatt gatt, 
            final BluetoothGattCharacteristic characteristic, 
            final int status) { 
     Log.d("foo", "onCharacteristicRead status:" + status + " payload: " + 
       MainActivity.getPayload(characteristic.getValue())); 
    } 

    @Override 
    public void onCharacteristicWrite(final BluetoothGatt gatt, 
             final BluetoothGattCharacteristic characteristic, 
             final int status) { 
     Log.d("foo", "onCharacteristicWrite"); 
    } 

    @Override 
    public void onCharacteristicChanged(final BluetoothGatt gatt, 
             final BluetoothGattCharacteristic characteristic) { 
     Log.d("foo", "onCharacteristicChanged payload:" + 
       MainActivity.getPayload(characteristic.getValue())); 
    } 

    @Override 
    public void onDescriptorWrite(final BluetoothGatt gatt, 
            final BluetoothGattDescriptor descriptor, 
            final int status) { 
     Log.d("foo", "onDescriptorWrite status: " + status); 
     final BluetoothGattCharacteristic characteristic = 
       gatt.getService(SERVICE).getCharacteristic(ADV_CHAR); 
     if (characteristic.getValue() != null) { 
      Log.d("foo", "value: " + MainActivity.getPayload(characteristic.getValue())); 
     } else { 
      gatt.readCharacteristic(characteristic); 
     } 
    } 

} 

내 AndroidManifest.xml에가 있습니다

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

을 로그는 다음과 같습니다

11-05 12:17:13.314 3683-3683/com.foo.ble D/BluetoothAdapter﹕ startLeScan(): null 
11-05 12:17:13.364 3683-3695/com.foo.ble D/BluetoothAdapter﹕ onClientRegistered() - status=0 clientIf=5 
11-05 12:17:13.394 3683-3683/com.foo.ble I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:320>: EGL 1.4 QUALCOMM Build: I0404c4692afb8623f95c43aeb6d5e13ed4b30ddbDate: 11/06/13 
11-05 12:17:13.414 3683-3683/com.foo.ble D/OpenGLRenderer﹕ Enabling debug mode 0 
11-05 12:17:13.454 3683-3683/com.foo.ble D/dalvikvm﹕ GC_FOR_ALLOC freed 238K, 2% free 16971K/17240K, paused 14ms, total 14ms 
11-05 12:17:15.174 3683-3694/com.foo.ble D/foo﹕ onLeScan payload:02010517FF0000000000000005000000000000000000395401001207086C6976656C7911072E9AB04DB9790F857A4CF0634C7AB94A000000000000000000 
11-05 12:17:15.174 3683-3694/com.foo.ble D/BluetoothAdapter﹕ stopLeScan() 
11-05 12:17:15.184 3683-3683/com.foo.ble D/BluetoothGatt﹕ connect() - device: CE:AD:09:F2:BB:DC, auto: true 
11-05 12:17:15.184 3683-3683/com.foo.ble D/BluetoothGatt﹕ registerApp() 
11-05 12:17:15.184 3683-3683/com.foo.ble D/BluetoothGatt﹕ registerApp() - UUID=605cbd6f-6080-4fd8-97ff-1f97b406258e 
11-05 12:17:15.194 3683-3695/com.foo.ble D/BluetoothGatt﹕ onClientRegistered() - status=0 clientIf=5 
11-05 12:17:43.344 3683-3683/com.foo.ble D/BluetoothAdapter﹕ stopLeScan() 
11-05 12:23:59.194 3683-3694/com.foo.ble D/BluetoothGatt﹕ onClientConnectionState() - status=0 clientIf=5 device=CE:AD:09:F2:BB:DC 
11-05 12:23:59.194 3683-3694/com.foo.ble D/foo﹕ onConnectionStateChange 
11-05 12:23:59.204 3683-3694/com.foo.ble D/foo﹕ status connected 
11-05 12:23:59.204 3683-3694/com.foo.ble D/BluetoothGatt﹕ discoverServices() - device: CE:AD:09:F2:BB:DC 
11-05 12:24:00.754 3683-3695/com.foo.ble D/BluetoothGatt﹕ onGetService() - Device=CE:AD:09:F2:BB:DC UUID=randomService1 
11-05 12:24:00.764 3683-3694/com.foo.ble D/BluetoothGatt﹕ onGetService() - Device=CE:AD:09:F2:BB:DC UUID=randomService2 
11-05 12:24:00.784 3683-3695/com.foo.ble D/BluetoothGatt﹕ onGetService() - Device=CE:AD:09:F2:BB:DC UUID=something1 
11-05 12:24:00.794 3683-3694/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=randomUUID1 
11-05 12:24:00.804 3683-3695/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=randomUUID2 
11-05 12:24:00.804 3683-3694/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=randomUUID3 
11-05 12:24:00.814 3683-3695/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=randomUUID4 
11-05 12:24:00.814 3683-3694/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=randomUUID5 
11-05 12:24:00.814 3683-3695/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=randomUUID6 
11-05 12:24:00.814 3683-3694/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=randomUUID7 
11-05 12:24:00.814 3683-3695/com.foo.ble D/BluetoothGatt﹕ onGetCharacteristic() - Device=CE:AD:09:F2:BB:DC UUID=something2 
11-05 12:24:00.824 3683-3694/com.foo.ble D/BluetoothGatt﹕ onGetDescriptor() - Device=CE:AD:09:F2:BB:DC UUID=something3 
11-05 12:24:00.824 3683-3695/com.foo.ble D/BluetoothGatt﹕ onSearchComplete() = Device=CE:AD:09:F2:BB:DC Status=0 
11-05 12:24:00.824 3683-3695/com.foo.ble D/foo﹕ onServicesDiscovered 
11-05 12:24:00.824 3683-3695/com.foo.ble D/BluetoothGatt﹕ setCharacteristicNotification() - uuid: something2 enable: true 
11-05 12:24:00.834 3683-3695/com.foo.ble D/BluetoothGatt﹕ writeDescriptor() - uuid: something3 
11-05 12:24:00.894 3683-3694/com.foo.ble D/BluetoothGatt﹕ onDescriptorWrite() - Device=CE:AD:09:F2:BB:DC UUID=something3 
11-05 12:24:00.894 3683-3694/com.foo.ble D/foo﹕ onDescriptorWrite status: 0 
11-05 12:24:00.894 3683-3694/com.foo.ble D/BluetoothGatt﹕ readCharacteristic() - uuid: something2 
11-05 12:24:00.994 3683-3695/com.foo.ble D/BluetoothGatt﹕ onCharacteristicRead() - Device=CE:AD:09:F2:BB:DC UUID=something2 Status=0 
11-05 12:24:00.994 3683-3695/com.foo.ble D/foo﹕ onCharacteristicRead status:0 payload: 0000000000050000000000000000005154010012 

도움이 될 것입니다!

+0

정확히 작동하지 않는 항목은 무엇입니까? 로그에 성공 상태가 표시됩니다. –

+0

알림이 표시되지 않습니다. "onCharacteristicChanged"가 없습니다. – eipipuz

+0

OnCharacteristicChanged 메서드의 다른 위치에 중단 점을 설정하면 디버깅하는 동안 실제로 원격 장치에서 알림을 받고 있습니다. –

답변

2

특정 전화/주변기기/환경 조합에서 작동하지 않는 알림을 보았거나 동일한 연결 세션에서 작업 한 후 명백한 이유없이 알림을 보았습니다. 모든 전화는 성공을 반환하지만 알림은 전달되지 않습니다. 현재 당면한 문제를 해결할 수 있는지 여부와 관계없이 백업 솔루션으로 특성 값에 대한 읽기 설문 조사를 고려해야합니다.

onServicesDiscovered() 메서드의 다양한 호출은 호출중인 다양한 gatt 메서드의 반환 값에 대한 조건부 검사를 통해 게이트되어야합니다.

어쨌든, 당신이 시도 할 수있는 몇 가지 :

  • 블루투스를 재설정 해보십시오 휴대 전화 설정을 통해 스택, 또는 전체 전화를 다시 시작.
  • 다른 장치를 테스트하십시오. iPhone이 주변기기로 작동하도록 허용하는 iOS 용 앱이 있습니다. 이러한 "sim 장치"에 연결하여이 경우 알림이 작동하는지 확인하십시오.
  • 다른 Android 휴대 전화를 사용해보십시오. Nexus 4가 사용중인 경우 Nexus 4에서 알림과 관련하여 가장 많은 문제가 있음을 확인했습니다.

마지막으로, 컴퓨터가 연결되어 있는지 묻는 기술 지원처럼 행동 할 것입니다. 주변 장치의 특성 값이 실제로 변경되고 있는지 확인하십시오.

+0

Doug에게 답변 해 주셔서 감사합니다. . 진행 방법을 모르겠습니다. 당신이 말했듯이, 일단 내가 다른 전화로 시도, 동일한 코드가 작동했습니다. 넥서스에서 나는 그것이 최대 7 분을 기다리는 문제라는 것을 알게되었습니다 .O.O S4에서 나는 그것을 전혀 할 수 없었습니다 (예, UI 스레드에서 실행 중입니다). 이 질문을 끝내는 가장 좋은 방법은 무엇인지 모르겠습니다. – eipipuz

+0

7 분 대기는'device.connectGatt (MainActivity.this, true, callback);를'device.connectGatt (MainActivity.this, false, callback);로 변경하여 "고정"되었습니다. 나는 두 번째 매개 변수가 큰 차이를 만든다는 것을 알지 못했습니다. – eipipuz

+0

예 autoConnect는 매우 까다 롭습니다.일부 전화 및 표식 장치 조합의 경우이 부울은 참이어야하며 그렇지 않은 경우 false입니다. 다른 사람들은 더 일관성있게 성공하지만 연결 속도는 더 느립니다. 강력한 연결 흐름을 얻으려면 기본적으로 런타임에 즉석에서 실험을 해보고 성공적인 연결을 얻을 때까지 다양한 조합을 시도한 다음 후속 연결 시도에 대한 설정을 기억해야합니다. 그리고 "autoConnect"를 true로 설정하면 네이티브 스택은 매우 적극적으로 영원히 연결을 시도 할 수 있기 때문에주의해야합니다. –

관련 문제