You need to enable JavaScript to run this app. Android BLE广播设备端蓝牙接收器无法接收GATT连接广播问题
优惠活动
大模型
产品
解决方案
定价
更多

Android BLE广播设备端蓝牙接收器无法接收GATT连接广播问题

Android BLE广播端无法接收连接状态广播问题

这是我开发的首个Android蓝牙相关应用,目前遇到了一个较为特殊的问题:对外广播BLE服务的设备上,蓝牙广播接收器无法正常工作。

我同时使用两台手机测试该应用,为便于说明分别命名为手机A和B。首先我在手机A上启动BLE广播,随后在手机B上启动设备扫描,最后点击手机B上的发送数据按钮。该按钮按下后会首先发起GATT连接,连接成功后应该发送一条广播确认连接状态。我在BroadcastReceiver中添加了Log来监听该广播,最终仅能在手机B的logcat中看到对应日志输出,手机A的logcat中无相关内容。

我查阅了大量示例代码和StackOverflow上的相关帖子,仍未找到该问题的解决方案。

我目前尚未定位到问题根因,可能是我对蓝牙相关类的使用存在错误,或是相关知识储备不足。下面附上该简易项目唯一的类MainActivity的完整代码。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mText;
private Button mAdvertiseButton;
private Button mDiscoverButton;
private Button mSendButton;
private String TAG = "INFOBLERESULTS";
private BluetoothLeScanner mBluetoothLeScanner;
private BluetoothDevice bluetoothDevice;
private Handler mHandler = new Handler();
private ScanCallback mScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        Log.d(TAG, result.getDevice().getAddress());
        super.onScanResult(callbackType, result);
        if( result == null
                || result.getDevice() == null
                || TextUtils.isEmpty(result.getDevice().getAddress()) )
            return;

        StringBuilder builder = new StringBuilder( result.getDevice().getAddress() );
        builder.append("\n").append(result.getDevice().getName());

        //builder.append("\n").append(new String(result.getScanRecord().getServiceData(result.getScanRecord().getServiceUuids().get(0)), Charset.forName("UTF-8")));

        mText.setText(builder.toString());
        bluetoothDevice = result.getDevice();
        bluetoothLeService = new BluetoothLeService();
        bluetoothLeService.setAddress(result.getDevice().getAddress());
    }

    @Override
    public void onBatchScanResults(List<ScanResult> results) {
        super.onBatchScanResults(results);
    }

    @Override
    public void onScanFailed(int errorCode) {
        Log.e( TAG, "Discovery onScanFailed: " + errorCode );
        super.onScanFailed(errorCode);
    }
};
private BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
private boolean connected = false;

//Inner classes
class BluetoothLeService extends Service {
    public final static String ACTION_GATT_CONNECTED =
            "com.example.bluetooth.le.ACTION_GATT_CONNECTED";
    public final static String ACTION_GATT_DISCONNECTED =
            "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
    public final static String ACTION_GATT_SERVICES_DISCOVERED =
            "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
    public final static String ACTION_DATA_AVAILABLE =
            "com.example.bluetooth.le.ACTION_DATA_AVAILABLE";

    private static final int STATE_DISCONNECTED = 0;
    private static final int STATE_CONNECTED = 2;

    private int connectionState;
    public Context ctx;

    protected BluetoothGatt bluetoothGatt;

    protected final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            Log.i(TAG, "GATT status = "+ status + " newState = " + newState);
            if(status == BluetoothGatt.GATT_SUCCESS){
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    // successfully connected to the GATT Server
                    connectionState = STATE_CONNECTED;
                    broadcastUpdate(ACTION_GATT_CONNECTED);
                    bluetoothGatt = gatt;
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    // disconnected from the GATT Server
                    connectionState = STATE_DISCONNECTED;
                    broadcastUpdate(ACTION_GATT_DISCONNECTED);
                    gatt.close();
                }
            }else{
                gatt.close();
            }

        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            } else {
                Log.w(TAG, "onServicesDiscovered received: " + status);
            }
        }

        @Override
        public void onCharacteristicRead(
                BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic,
                int status
        ) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            }
        }

        @Override
        public void onCharacteristicChanged(
                BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic
        ) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }


    };

    private Binder binder = new LocalBinder();
    private String address = "";

    public void setAddress(String address) {
        this.address = address;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        close();
        return super.onUnbind(intent);
    }

    private void close() {
        if (bluetoothGatt == null) {
            return;
        }
        bluetoothGatt.close();
        bluetoothGatt = null;
    }

    public boolean connect() {
        if (bluetoothAdapter == null || this.address == null || this.address.equals("")) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        try {
            final BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
            bluetoothGatt = device.connectGatt(MainActivity.this.getApplicationContext(), false, gattCallback);
            Log.d(TAG,"GATT "+ bluetoothGatt);
            return true;

        } catch (IllegalArgumentException exception) {
            Log.w(TAG, "Device not found with provided address.");
            return false;
        }
    }

    private void broadcastUpdate(final String action) {
        final Intent intent = new Intent(action);
        Log.i(TAG, intent + "");
        MainActivity.this.getApplicationContext().sendBroadcast(intent);
    }

    private void broadcastUpdate(final String action, BluetoothGattCharacteristic characteristic) {
        final Intent intent = new Intent(action);
        
        sendBroadcast(intent);

    }

    public List<BluetoothGattService> getSupportedGattServices() {
        if (bluetoothGatt == null) return null;
        return bluetoothGatt.getServices();
    }

    public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (bluetoothGatt == null) {
            Log.w(TAG, "BluetoothGatt not initialized");
            return;
        }
        bluetoothGatt.readCharacteristic(characteristic);
    }

    public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,boolean enabled) {
        if (bluetoothGatt == null) {
            Log.w(TAG, "BluetoothGatt not initialized");
            return;
        }
        bluetoothGatt.setCharacteristicNotification(characteristic, enabled);
    }



    class LocalBinder extends Binder {
        public BluetoothLeService getService() {
            return BluetoothLeService.this;
        }
    }
}
private BluetoothLeService bluetoothLeService = new BluetoothLeService();

private final ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        bluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
        if (bluetoothLeService != null) {
            if (!bluetoothAdapter.isEnabled()) {
                Log.e(TAG, "Unable to initialize Bluetooth");
            }
            else{
                bluetoothLeService.connect();
                Log.i(TAG, "Service connected");
            }
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        bluetoothLeService = null;
    }
};

private final BroadcastReceiver gattUpdateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        Log.d(TAG, "RECEIVED " + action);
        if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
            connected = true;
            //Log.d(TAG, "CONNECTED");
        } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
            connected = false;
            //Log.d(TAG, "DISCONNECTED");
        }
    }

};



private final ActivityResultLauncher<Intent> someActivityResultLauncher = registerForActivityResult(
        new ActivityResultContracts.StartActivityForResult(),
        new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult result) {
                Log.i("RESULT", result.getResultCode() + "");
                setup();
            }
        });

private void setup() {
    bluetoothLeService.ctx = this.getApplicationContext();
    Log.d("APPLICATIONCONTEXT", bluetoothLeService.ctx + "");
    mDiscoverButton.setOnClickListener(this);
    mAdvertiseButton.setOnClickListener(this);
    mSendButton.setOnClickListener(this);

    mBluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();

    if (!BluetoothAdapter.getDefaultAdapter().isMultipleAdvertisementSupported()) {
        Toast.makeText(this, "Multiple advertisement not supported", Toast.LENGTH_SHORT).show();
        mAdvertiseButton.setEnabled(false);
        mDiscoverButton.setEnabled(false);
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull @org.jetbrains.annotations.NotNull String[] permissions, @NonNull @org.jetbrains.annotations.NotNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 2) {
        final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
        if(!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            Intent enableLocationIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            someActivityResultLauncher.launch(enableLocationIntent);
        }
        else{
            setup();
        }


    }

}

@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mText = (TextView) findViewById( R.id.text );
    mDiscoverButton = (Button) findViewById( R.id.discover_btn );
    mAdvertiseButton = (Button) findViewById( R.id.advertise_btn );
    mSendButton = (Button) findViewById( R.id.send_btn );

    this.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 2);

}

@Override
protected void onResume() {
    super.onResume();
    MainActivity.this.getApplicationContext().registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter());
}
@Override
protected void onPause() {
    super.onPause();
    MainActivity.this.getApplicationContext().unregisterReceiver(gattUpdateReceiver);
}




@Override
public void onClick(View v) {
    Log.d(TAG, getString( R.string.ble_uuid ));
    if( v.getId() == R.id.discover_btn ) {
        discover();
    } else if( v.getId() == R.id.advertise_btn ) {
        advertise();
        //MainActivity.this.getApplicationContext().registerReceiver(gattUpdateReceiver, makeGattUpdateIntentFilter());
    } else if (v.getId() == R.id.send_btn){
        //MainActivity.this.getApplicationContext().unregisterReceiver(gattUpdateReceiver);
        send();

    }
}

public void advertise(){
    BluetoothLeAdvertiser advertiser = BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();

    AdvertiseSettings settings = new AdvertiseSettings.Builder().setTimeout(0)
            .setAdvertiseMode( AdvertiseSettings.ADVERTISE_MODE_BALANCED )
            .setTxPowerLevel( AdvertiseSettings.ADVERTISE_TX_POWER_HIGH )
            .setConnectable( true )
            .build();
    ParcelUuid pUuid = ParcelUuid.fromString( getString( R.string.ble_uuid ) ) ;

    AdvertiseData data = new AdvertiseData.Builder()
            .addServiceUuid( pUuid ).setIncludeDeviceName(false)
            .build();
    AdvertiseCallback advertisingCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            Log.d(TAG, "START ADVERTISING");
            super.onStartSuccess(settingsInEffect);
        }

        @Override
        public void onStartFailure(int errorCode) {
            Log.e( TAG, "Advertising onStartFailure: " + errorCode );
            super.onStartFailure(errorCode);
        }
    };

    advertiser.startAdvertising( settings, data, advertisingCallback );


}

public void discover(){
    ScanFilter filter = new ScanFilter.Builder()
            .setServiceUuid( ParcelUuid.fromString( getString(R.string.ble_uuid ) ) )
            .build();
    List<ScanFilter> filters = new ArrayList<>();
    filters.add( filter );
    ScanSettings settings = new ScanSettings.Builder()
            .setScanMode( ScanSettings.SCAN_MODE_BALANCED )
            .build();
    mBluetoothLeScanner.startScan(filters, settings, mScanCallback);
    Log.d(TAG, "Discovery started");
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            Log.d(TAG, "Discovery stopped");
            mBluetoothLeScanner.stopScan(mScanCallback);
        }
    }, 10000);
}

public void send(){
    Log.d(TAG, "START CONNECTIONG GATT");
    mBluetoothLeScanner.stopScan(mScanCallback);
    //boundGatt();
    connectGatt();
}

public void boundGatt(){
    Intent gattServiceIntent = new Intent(MainActivity.this.getApplicationContext(), BluetoothLeService.class);
    bindService(gattServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}

public void connectGatt(){
    bluetoothLeService.connect();
}

private static IntentFilter makeGattUpdateIntentFilter() {
    final IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
    intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
    intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
    return intentFilter;
}
}

内容的提问来源于stack exchange,提问作者Andrea Pantieri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 21:39:02