意图在Android外围设备上接收有关BLE连接事件的通知

时间:2015-04-30 00:17:30

标签: android android-intent bluetooth bluetooth-lowenergy android-bluetooth

我正在开发一个在Android上运行的外设模式BLE应用程序。有几个很好的功能示例描述了如何开发外设模式应用程序herehere

示例应用程序与我需要开发的系统之间存在一个细微差别。在示例应用程序中,GATT服务器在外围模式设备上运行。外围设备通告,集中扫描并查找设备并向GATT服务器发送请求。

在我的系统中,GATT服务器将位于中央模式设备上。外围设备将收到连接请求,需要找到请求设备的地址并启动与中央模式设备上的GATT服务器的连接。

命名和详细操作

MyApp(BLE外围设备;广告商,GATT客户端)

TgtDev(BLE中心;扫描仪,运行GATT服务器)

  1. TgtDev不断扫描并查找具有特定UUID的广告。
  2. MyApp已推出并开始宣传其存在。
  3. TgtDev检测到MyApp并发送连接请求。
  4. 收到连接请求后,MyApp将请求用户接受或拒绝连接请求。此时,它需要读取请求连接的设备的地址。
  5. 如果用户接受,MyApp将请求连接TgtDev上的GATT服务器。
  6. 如果用户拒绝请求,MyApp将停止投放广告。
  7. 我的申请代码如下所示。我希望在收到连接请求时收到MyApp的意图。看起来这应该可以使用registerReceiver()的适当的intent过滤器。但是,我没有看到在发出连接请求时调用BroadcastReceiver。

    提供了GattCallback()函数的实现,但未使用。要注册回调,我需要连接设备的地址。

    有关我在这里缺少什么的建议吗?

    编辑:添加有关系统和Android日志消息的信息。 外围设备Nexus 6运行5.1。 MyApp targetSdkVersion 21.跟踪TgtDev上的代码路径我可以看到MyApp接受了连接事件。我能用BLE嗅探器证实这一点。

    记录消息。

    I/ActivityManager(  802): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.example.user.advertiser/.PeripheralActivity (has extras)} from uid 10034 on display 0
    V/WindowManager(  802): addAppToken: AppWindowToken{2ff62ab token=Token{225f8cfa ActivityRecord{f3dc325 u0 com.example.user.advertiser/.PeripheralActivity t89}}} to stack=1 task=89 at 0
    V/WindowManager(  802): Adding window Window{2d18b520 u0 Starting com.example.user.advertiser} at 3 of 9 (after Window{14f690b7 u0 com.google.android.googlequicksearchbox/com.google.android.launcher.GEL})
    D/BluetoothManagerService(  802): checkIfCallerIsForegroundUser: valid=true callingUser=0 parentUser=-10000 foregroundUser=0
    D/BluetoothManagerService(  802): checkIfCallerIsForegroundUser: valid=true callingUser=0 parentUser=-10000 foregroundUser=0
    D/BluetoothLeAdvertiser( 4018): onClientRegistered() - status=0 clientIf=5
    V/WindowManager(  802): Adding window Window{16d3a650 u0 com.example.user.advertiser/com.example.user.advertiser.PeripheralActivity} at 3 of 10 (before Window{2d18b520 u0 Starting com.example.user.advertiser})
    I/ActivityManager(  802): Displayed com.example.user.advertiser/.PeripheralActivity: +129ms
    E/bt-att  ( 3236): MTU request PDU with MTU size 517
    W/bt-att  ( 3236): Call back not found for application conn_id=3
    W/bt-att  ( 3236): Call back not found for application conn_id=4
    W/bt-att  ( 3236): Call back not found for application conn_id=5
    W/bt-btif ( 3236): info:x0
    E/BluetoothRemoteDevices( 3236): aclStateChangeCallback: Device is NULL
    W/bt-btif ( 3236): bta_gattc_conn_cback() - cif=3 connected=0 conn_id=3 reason=0x0016
    W/bt-btif ( 3236): bta_gattc_conn_cback() - cif=4 connected=0 conn_id=4 reason=0x0016
    W/bt-btif ( 3236): bta_gattc_conn_cback() - cif=5 connected=0 conn_id=5 reason=0x0016
    E/bt-btm  ( 3236): btm_sec_disconnected - Clearing Pending flag
    E/BluetoothRemoteDevices( 3236): aclStateChangeCallback: Device is NULL
    W/PackageManager( 1045): Failure retrieving resources for com.example.user.advertiser: Resource ID #0x0
    

    申请代码

        public class PeripheralActivity extends Activity {
        private static final String TAG = "PeripheralActivity";
    
        private BluetoothManager mBluetoothManager;
        private BluetoothAdapter mBluetoothAdapter;
        private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
    
        private ArrayList<BluetoothDevice> mConnectedDevices;
        private ArrayAdapter<BluetoothDevice> mConnectedDevicesAdapter;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ListView list = new ListView(this);
            setContentView(list);
    
        mConnectedDevices = new ArrayList<BluetoothDevice>();
        mConnectedDevicesAdapter = new ArrayAdapter<BluetoothDevice>(this,
                android.R.layout.simple_list_item_1, mConnectedDevices);
        list.setAdapter(mConnectedDevicesAdapter);
    
        /*
         * Bluetooth in Android 4.3+ is accessed via the BluetoothManager, rather than
         * the old static BluetoothAdapter.getInstance()
         */
        mBluetoothManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        mBluetoothAdapter = mBluetoothManager.getAdapter();
        }
    
        @Override
        protected void onResume() {
        super.onResume();
    
        // extraneous code; check if bluetooth is on, advertising is supported etc.
    
        registerReceiver(intentReceiver, makeGattUpdateIntentFilter());
        mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
        startAdvertising();
        }
    
        @Override
        protected void onPause() {
        super.onPause();
        stopAdvertising();
        if (intentReceiver != null)
        {
            unregisterReceiver(intentReceiver);
        }
        }
    
         /*
         * Callback handles all incoming requests from GATT clients.
         * From connections to read/write requests.
         */
        private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            Log.i(TAG, "onConnectionStateChange "
                    +DeviceProfile.getStatusDescription(status)+" "
                    +DeviceProfile.getStateDescription(newState));
    
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                Log.i(TAG, "connected");
    
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.i(TAG, "disconnected");
    
            } else if (newState == BluetoothProfile.STATE_CONNECTING) {
                Log.i(TAG, "attempting to connect");
    
            }
        }      
    
        private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent receivedIntent) {
            Log.v(TAG, "Entered intent receiver");
            if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(receivedIntent.getAction()))
            {
                Log.v(TAG, "Received Pairing request");
            }
            if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(receivedIntent.getAction()))
            {
                Log.v(TAG, "connected");
            }
            if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(receivedIntent.getAction()))
            {
                Log.v(TAG, "disconnected");
            }
            if (BluetoothDevice.ACTION_FOUND.equals(receivedIntent.getAction()))
            {
                Log.v(TAG, "action found");
                BluetoothDevice foundDevice = receivedIntent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                Log.v(TAG, foundDevice.getName()+" "+foundDevice.getAddress()+" was found");
                BluetoothDevice foundDeviceClass = receivedIntent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
                Log.v(TAG, "BT class: "+foundDeviceClass.toString());
            }
            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(receivedIntent.getAction()))
            {
                Log.v(TAG, "bond state changed");
            }
        }
        };
    
        /*
         * Initialize the advertiser
         */
         private void startAdvertising() {
        if (mBluetoothLeAdvertiser == null) return;
    
        AdvertiseSettings settings = new AdvertiseSettings.Builder()
                .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
                .setConnectable(true)
                .setTimeout(0)
                .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
                .build();
    
        AdvertiseData data = new AdvertiseData.Builder()
                .setIncludeDeviceName(true)
                .addServiceUuid(new ParcelUuid(DeviceProfile.SERVICE_UUID))
                .build();
    
        mBluetoothLeAdvertiser.startAdvertising(settings, data, mAdvertiseCallback);
        }
    
        /*
         * Terminate the advertiser
         */
         private void stopAdvertising() {
         if (mBluetoothLeAdvertiser == null) return;
    
         mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
        }
    
        /*
         * Callback handles events from the framework describing
         * if we were successful in starting the advertisement requests.
         */
        private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            Log.i(TAG, "Peripheral Advertise Started.");        
        }
    
        @Override
        public void onStartFailure(int errorCode) {
            Log.w(TAG, "Peripheral Advertise Failed: ");
        }
        };      
    
    
        private static IntentFilter makeGattUpdateIntentFilter() {
    
        final IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    
        return intentFilter;
        }
        }
    

0 个答案:

没有答案