Android蓝牙配对

article/2025/10/8 10:36:23

上一篇博客介绍了Android ble的一些情况。

http://blog.csdn.net/guijiaoba/article/details/41172403


蓝牙如果链接好,能够读写,基本上完成了。蓝牙还有个比较烦人的东西,就是蓝牙配对。

Android ble4.0使用的配对方式和原先版本的配对方式不一样。


看了网上很多地方都是hellogv大神的方法,这个真心不错。

http://blog.csdn.net/hellogv/article/details/6042091


本着认真的态度,我把Android系统中Settings的源码给研究了下,发现了配对的流程,Settings的源码大小大概有300m,考虑的攻击

Ble4.0的配对界面有2个部分,首先的是一个请求的配对的通知,点击了是一个确认对话框,再点击,然后又有个通知,点击通知后,有个输入密码的的对话框,输入密码后,点确定,稍后就会有配对的结果。


下面是Settings中的源码

Settings的目录是/package/app/Settings,下面是Setting的源码url,感兴趣的同学可以去研究下

http://git.omapzoom.org/   所有的源码网址

http://git.omapzoom.org/?p=platform/packages/apps/Settings.git;a=summary  Settings的网址

git://git.omapzoom.org/platform/packages/apps/Settings.git Settings的git地址

 

Settings中的蓝牙代码都在/Settings/src/com/android/settings/bluetooth目录中

主要流程看下面的文件

/Settings/src/com/android/settings/bluetooth/BluetoothPairingDialog.java

代码中很多的类,在实际的Android应该开发中是没有的,我这边准备了三个jar文件,分别是framework.jar,core.jar,ext.jar,这些事Android系统编译的时候,生产的jar。

导入到elcipse中,关联此jar就可以。关联的jar时放在libs中,但是有个必须注意的地方,点击项目的属性,在Java BuildPath类别,Order and Export标签,Android Dependenceis必须要比Android 5.0的在上面,这样在引用的时候,就会优先引用Android Dependceis中的jar。






下面是Setting中的BluetoothPairingDialog.java,简单分析下,中文部分是我添加的注释。

package com.android.settings.bluetooth;import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.Editable;
import android.text.Html;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.InputFilter.LengthFilter;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.settings.R;
import android.view.KeyEvent;import java.util.Locale;/*** BluetoothPairingDialog asks the user to enter a PIN / Passkey / simple* confirmation for pairing with a remote Bluetooth device. It is an activity* that appears as a dialog.*/// BluetoothPairingDialog 说明这个节目是一个对话框
public final class BluetoothPairingDialog extends AlertActivity implements CompoundButton.OnCheckedChangeListener, DialogInterface.OnClickListener, TextWatcher {private static final String TAG = "BluetoothPairingDialog";private static final int BLUETOOTH_PIN_MAX_LENGTH = 16;private static final int BLUETOOTH_PASSKEY_MAX_LENGTH = 6;private BluetoothDevice mDevice;private int mType;private String mPairingKey;private EditText mPairingView;private Button mOkButton;/*** Dismiss the dialog if the bond state changes to bonded or none, or if* pairing was canceled for {@link #mDevice}.*/private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {// 当设备的配对状态改变的时候,就把对话框去掉int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);if (bondState == BluetoothDevice.BOND_BONDED || bondState == BluetoothDevice.BOND_NONE) {dismiss();}} else if (BluetoothDevice.ACTION_PAIRING_CANCEL.equals(action)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device == null || device.equals(mDevice)) {dismiss();}}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 必须是ACTION_PAIRING_REQUEST,否则不运行,ACTION_PAIRING_REQUEST是一个请求的配对的广播Intent intent = getIntent();if (!intent.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST是一个请求的配对的广播)) {Log.e(TAG, "Error: this activity may be started only with intent " + BluetoothDevice.ACTION_PAIRING_REQUEST);finish();return;}LocalBluetoothManager manager = LocalBluetoothManager.getInstance(this);if (manager == null) {Log.e(TAG, "Error: BluetoothAdapter not supported by system");finish();return;}CachedBluetoothDeviceManager deviceManager = manager.getCachedDeviceManager();// 获取配对的设备和配对类型,我的项目中配对类型是BluetoothDevice.PAIRING_VARIANT_PINmDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);mType = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);// 根据配对的类型,进行分发,我们重点关注PAIRING_VARIANT_PINswitch (mType) {case BluetoothDevice.PAIRING_VARIANT_PIN:case BluetoothDevice.PAIRING_VARIANT_PASSKEY:// 创建用户输入配对密码的对话框createUserEntryDialog(deviceManager);break;case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:int passkey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);if (passkey == BluetoothDevice.ERROR) {Log.e(TAG, "Invalid Confirmation Passkey received, not showing any dialog");return;}mPairingKey = String.format(Locale.US, "%06d", passkey);createConfirmationDialog(deviceManager);break;case BluetoothDevice.PAIRING_VARIANT_CONSENT:case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:createConsentDialog(deviceManager);break;case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:int pairingKey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);if (pairingKey == BluetoothDevice.ERROR) {Log.e(TAG, "Invalid Confirmation Passkey or PIN received, not showing any dialog");return;}if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {mPairingKey = String.format("%06d", pairingKey);} else {mPairingKey = String.format("%04d", pairingKey);}createDisplayPasskeyOrPinDialog(deviceManager);break;default:Log.e(TAG, "Incorrect pairing type received, not showing any dialog");}/** Leave this registered through pause/resume since we still want to* finish the activity in the background if pairing is canceled.*/registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_CANCEL));registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));}// 创建用户输入配对密码的对话框private void createUserEntryDialog(CachedBluetoothDeviceManager deviceManager) {// 创建对话框的界面,// 在看看对话框的确定的回调函数,由于本类是实现DialogInterface.OnClickListener的方法的,我们可以去看下// public void onClick(DialogInterface dialog, int which)final AlertController.AlertParams p = mAlertParams;p.mIconId = android.R.drawable.ic_dialog_info;p.mTitle = getString(R.string.bluetooth_pairing_request);p.mView = createPinEntryView(deviceManager.getName(mDevice));p.mPositiveButtonText = getString(android.R.string.ok);p.mPositiveButtonListener = this;p.mNegativeButtonText = getString(android.R.string.cancel);p.mNegativeButtonListener = this;setupAlert();mOkButton = mAlert.getButton(BUTTON_POSITIVE);mOkButton.setEnabled(false);}private View createPinEntryView(String deviceName) {View view = getLayoutInflater().inflate(R.layout.bluetooth_pin_entry, null);TextView messageView = (TextView) view.findViewById(R.id.message);TextView messageView2 = (TextView) view.findViewById(R.id.message_below_pin);CheckBox alphanumericPin = (CheckBox) view.findViewById(R.id.alphanumeric_pin);mPairingView = (EditText) view.findViewById(R.id.text);mPairingView.addTextChangedListener(this);alphanumericPin.setOnCheckedChangeListener(this);int messageId1;int messageId2;int maxLength;switch (mType) {case BluetoothDevice.PAIRING_VARIANT_PIN:messageId1 = R.string.bluetooth_enter_pin_msg;messageId2 = R.string.bluetooth_enter_pin_other_device;// Maximum of 16 characters in a PINmaxLength = BLUETOOTH_PIN_MAX_LENGTH;break;case BluetoothDevice.PAIRING_VARIANT_PASSKEY:messageId1 = R.string.bluetooth_enter_passkey_msg;messageId2 = R.string.bluetooth_enter_passkey_other_device;// Maximum of 6 digits for passkeymaxLength = BLUETOOTH_PASSKEY_MAX_LENGTH;alphanumericPin.setVisibility(View.GONE);break;default:Log.e(TAG, "Incorrect pairing type for createPinEntryView: " + mType);return null;}// HTML escape deviceName, Format the message string, then parse HTML style tagsString messageText = getString(messageId1, Html.escapeHtml(deviceName));messageView.setText(Html.fromHtml(messageText));messageView2.setText(messageId2);mPairingView.setInputType(InputType.TYPE_CLASS_NUMBER);mPairingView.setFilters(new InputFilter[] { new LengthFilter(maxLength) });return view;}private View createView(CachedBluetoothDeviceManager deviceManager) {View view = getLayoutInflater().inflate(R.layout.bluetooth_pin_confirm, null);// Escape device name to avoid HTML injection.String name = Html.escapeHtml(deviceManager.getName(mDevice));TextView messageView = (TextView) view.findViewById(R.id.message);String messageText; // formatted string containing HTML style tagsswitch (mType) {case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:messageText = getString(R.string.bluetooth_confirm_passkey_msg, name, mPairingKey);break;case BluetoothDevice.PAIRING_VARIANT_CONSENT:case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:messageText = getString(R.string.bluetooth_incoming_pairing_msg, name);break;case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:messageText = getString(R.string.bluetooth_display_passkey_pin_msg, name, mPairingKey);break;default:Log.e(TAG, "Incorrect pairing type received, not creating view");return null;}messageView.setText(Html.fromHtml(messageText));return view;}private void createConfirmationDialog(CachedBluetoothDeviceManager deviceManager) {final AlertController.AlertParams p = mAlertParams;p.mIconId = android.R.drawable.ic_dialog_info;p.mTitle = getString(R.string.bluetooth_pairing_request);p.mView = createView(deviceManager);p.mPositiveButtonText = getString(R.string.bluetooth_pairing_accept);p.mPositiveButtonListener = this;p.mNegativeButtonText = getString(R.string.bluetooth_pairing_decline);p.mNegativeButtonListener = this;setupAlert();}private void createConsentDialog(CachedBluetoothDeviceManager deviceManager) {final AlertController.AlertParams p = mAlertParams;p.mIconId = android.R.drawable.ic_dialog_info;p.mTitle = getString(R.string.bluetooth_pairing_request);p.mView = createView(deviceManager);p.mPositiveButtonText = getString(R.string.bluetooth_pairing_accept);p.mPositiveButtonListener = this;p.mNegativeButtonText = getString(R.string.bluetooth_pairing_decline);p.mNegativeButtonListener = this;setupAlert();}private void createDisplayPasskeyOrPinDialog(CachedBluetoothDeviceManager deviceManager) {final AlertController.AlertParams p = mAlertParams;p.mIconId = android.R.drawable.ic_dialog_info;p.mTitle = getString(R.string.bluetooth_pairing_request);p.mView = createView(deviceManager);p.mNegativeButtonText = getString(android.R.string.cancel);p.mNegativeButtonListener = this;setupAlert();// Since its only a notification, send an OK to the framework,// indicating that the dialog has been displayed.if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {mDevice.setPairingConfirmation(true);} else if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN) {byte[] pinBytes = BluetoothDevice.convertPinToBytes(mPairingKey);mDevice.setPin(pinBytes);}}@Overrideprotected void onDestroy() {super.onDestroy();unregisterReceiver(mReceiver);}public void afterTextChanged(Editable s) {if (mOkButton != null) {mOkButton.setEnabled(s.length() > 0);}}// 进行配对private void onPair(String value) {// 根据类型进行分发switch (mType) {case BluetoothDevice.PAIRING_VARIANT_PIN:// 注意这里是用了转换的方法,不是直接调用value.getBytes();方法byte[] pinBytes = BluetoothDevice.convertPinToBytes(value);if (pinBytes == null) {return;}// 直接调用setPin方法,然后就没有了,等到收到状态改变的广播后就进行dismiss,请看54行的mReceivermDevice.setPin(pinBytes);break;case BluetoothDevice.PAIRING_VARIANT_PASSKEY:int passkey = Integer.parseInt(value);mDevice.setPasskey(passkey);break;case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:case BluetoothDevice.PAIRING_VARIANT_CONSENT:mDevice.setPairingConfirmation(true);break;case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:// Do nothing.break;case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:mDevice.setRemoteOutOfBandData();break;default:Log.e(TAG, "Incorrect pairing type received");}}private void onCancel() {mDevice.cancelPairingUserInput();}public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {onCancel();}return super.onKeyDown(keyCode, event);}// 对话框的确定的回调public void onClick(DialogInterface dialog, int which) {switch (which) {case BUTTON_POSITIVE:// 进行配对if (mPairingView != null) {onPair(mPairingView.getText().toString());} else {onPair(null);}break;case BUTTON_NEGATIVE:default:onCancel();break;}}/* Not used */public void beforeTextChanged(CharSequence s, int start, int count, int after) {}/* Not used */public void onTextChanged(CharSequence s, int start, int before, int count) {}public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {// change input type for soft keyboard to numeric or alphanumericif (isChecked) {mPairingView.setInputType(InputType.TYPE_CLASS_TEXT);} else {mPairingView.setInputType(InputType.TYPE_CLASS_NUMBER);}}
}

1、对话框的创建

当收到请求配对的广播后,此对话框会显示。

	protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 必须是ACTION_PAIRING_REQUEST,否则不运行,ACTION_PAIRING_REQUEST是一个请求的配对的广播Intent intent = getIntent();if (!intent.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST是一个请求的配对的广播)) {Log.e(TAG, "Error: this activity may be started only with intent " + BluetoothDevice.ACTION_PAIRING_REQUEST);finish();return;}LocalBluetoothManager manager = LocalBluetoothManager.getInstance(this);if (manager == null) {Log.e(TAG, "Error: BluetoothAdapter not supported by system");finish();return;}CachedBluetoothDeviceManager deviceManager = manager.getCachedDeviceManager();// 获取配对的设备和配对类型,我的项目中配对类型是BluetoothDevice.PAIRING_VARIANT_PINmDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);mType = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);// 根据配对的类型,进行分发,我们重点关注PAIRING_VARIANT_PINswitch (mType) {case BluetoothDevice.PAIRING_VARIANT_PIN:case BluetoothDevice.PAIRING_VARIANT_PASSKEY:// 创建用户输入配对密码的对话框createUserEntryDialog(deviceManager);break;case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:int passkey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);if (passkey == BluetoothDevice.ERROR) {Log.e(TAG, "Invalid Confirmation Passkey received, not showing any dialog");return;}mPairingKey = String.format(Locale.US, "%06d", passkey);createConfirmationDialog(deviceManager);break;case BluetoothDevice.PAIRING_VARIANT_CONSENT:case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:createConsentDialog(deviceManager);break;case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:int pairingKey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);if (pairingKey == BluetoothDevice.ERROR) {Log.e(TAG, "Invalid Confirmation Passkey or PIN received, not showing any dialog");return;}if (mType == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {mPairingKey = String.format("%06d", pairingKey);} else {mPairingKey = String.format("%04d", pairingKey);}createDisplayPasskeyOrPinDialog(deviceManager);break;default:Log.e(TAG, "Incorrect pairing type received, not showing any dialog");}/** Leave this registered through pause/resume since we still want to* finish the activity in the background if pairing is canceled.*/// 注册广播registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_PAIRING_CANCEL));registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));}


2、创建有输入框的界面

	// 创建用户输入配对密码的对话框private void createUserEntryDialog(CachedBluetoothDeviceManager deviceManager) {// 创建对话框的界面,// 在看看对话框的确定的回调函数,由于本类是实现DialogInterface.OnClickListener的方法的,我们可以去看下// public void onClick(DialogInterface dialog, int which)final AlertController.AlertParams p = mAlertParams;p.mIconId = android.R.drawable.ic_dialog_info;p.mTitle = getString(R.string.bluetooth_pairing_request);p.mView = createPinEntryView(deviceManager.getName(mDevice));p.mPositiveButtonText = getString(android.R.string.ok);p.mPositiveButtonListener = this;p.mNegativeButtonText = getString(android.R.string.cancel);p.mNegativeButtonListener = this;setupAlert();mOkButton = mAlert.getButton(BUTTON_POSITIVE);mOkButton.setEnabled(false);}


3、查看输入框的确定回调函数

	// 对话框的确定的回调public void onClick(DialogInterface dialog, int which) {switch (which) {case BUTTON_POSITIVE:// 进行配对if (mPairingView != null) {onPair(mPairingView.getText().toString());} else {onPair(null);}break;case BUTTON_NEGATIVE:default:onCancel();break;}}

4、配对

	// 进行配对private void onPair(String value) {// 根据类型进行分发switch (mType) {case BluetoothDevice.PAIRING_VARIANT_PIN:// 注意这里是用了转换的方法,不是直接调用value.getBytes();方法byte[] pinBytes = BluetoothDevice.convertPinToBytes(value);if (pinBytes == null) {return;}// 直接调用setPin方法,然后就没有了,等到收到状态改变的广播后就进行dismiss,请看54行的mReceivermDevice.setPin(pinBytes);break;case BluetoothDevice.PAIRING_VARIANT_PASSKEY:int passkey = Integer.parseInt(value);mDevice.setPasskey(passkey);break;case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:case BluetoothDevice.PAIRING_VARIANT_CONSENT:mDevice.setPairingConfirmation(true);break;case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:// Do nothing.break;case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:mDevice.setRemoteOutOfBandData();break;default:Log.e(TAG, "Incorrect pairing type received");}}

// 注意这里是用了转换的方法,不是直接调用value.getBytes();方法
byte[] pinBytes = BluetoothDevice.convertPinToBytes(value);

下面是系统的中的配对密码转换

    /*** Check that a pin is valid and convert to byte array.** Bluetooth pin's are 1 to 16 bytes of UTF-8 characters.* @param pin pin as java String* @return the pin code as a UTF-8 byte array, or null if it is an invalid*         Bluetooth pin.* @hide*/public static byte[] convertPinToBytes(String pin) {if (pin == null) {return null;}byte[] pinBytes;try {pinBytes = pin.getBytes("UTF-8");} catch (UnsupportedEncodingException uee) {Log.e(TAG, "UTF-8 not supported?!?");  // this should not happenreturn null;}if (pinBytes.length <= 0 || pinBytes.length > 16) {return null;}return pinBytes;}



5、根据配对的结果,进行配对

	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {// 当设备的配对状态改变的时候,就把对话框去掉int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);if (bondState == BluetoothDevice.BOND_BONDED || bondState == BluetoothDevice.BOND_NONE) {dismiss();}} else if (BluetoothDevice.ACTION_PAIRING_CANCEL.equals(action)) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device == null || device.equals(mDevice)) {dismiss();}}}};

以上就是系统的设置的配对流程。




下面是自己的项目中的业务代码

	BroadcastReceiver bleReceiver = new BroadcastReceiver() {public void onReceive(Context context, Intent intent) {McLog.mByStackTrace();String action = intent.getAction();McLog.i("action = " + action);if (BluetoothDevice.ACTION_FOUND.equals(action)) {// 搜索设备doDeviceSearch(intent);} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //搜索结束doDeviceSearchFinished(intent);} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { // 设备状态改变doStateChange(intent);} else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {// 请求匹配doRequestPari(intent);}}void doStateChange(Intent intent) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);switch (device.getBondState()) {case BluetoothDevice.BOND_NONE:McLog.i("取消配对");break;case BluetoothDevice.BOND_BONDING:McLog.i("正在配对......");break;case BluetoothDevice.BOND_BONDED:McLog.i("完成配对");break;}}void doDeviceSearch(Intent intent) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);McLog.i("device = " + device);if (device.getBondState() == BluetoothDevice.BOND_BONDED) {// 已经配对的则跳过} else {if (!searchDevices.contains(searchDevices)) {searchDevices.add(device);}}}void doDeviceSearchFinished(Intent intent) {McLog.i("search finished, searchDevices's size = " + searchDevices.size());boolean isFindRightDevice = false;for (BluetoothDevice device : searchDevices) {if (isRightDevice(device)) { //  如果是我想要的设备,那么我就进行配对doNormalPair(device);isFindRightDevice = true;break;}}if (!isFindRightDevice) {McLog.i("sorry,do't search user's device[" + bleDeviceMac + "]");}}void doNormalPair(BluetoothDevice device) {McLog.mByStackTrace();currentPairDevice = device;try {// 调用配对的方法,此方法是异步的,系统会触发BluetoothDevice.ACTION_PAIRING_REQUEST的广播// 收到此广播后,设置配对的密码ClsUtils.createBond(BluetoothDevice.class, currentPairDevice);} catch (Exception e) {e.printStackTrace();}}void doRequestPari(Intent intent) {BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (btDevice.getBondState() == BluetoothDevice.BOND_BONDED) {McLog.e("已经绑定");} else {McLog.e("没有绑定");if (currentPairDevice != null && btDevice.getAddress().equalsIgnoreCase(currentPairDevice.getAddress())) {try {McLog.i("invoke setpin :" + bleDeviceMac);// 设置配对的密码 <span style="font-family: Arial, Helvetica, sans-serif;">bleDevicePasswd 设备的配对密码</span>ClsUtils.setPin2(BluetoothDevice.class, currentPairDevice, bleDevicePasswd);} catch (Exception e) {McLog.i("e = " + e);}currentPairDevice = null;uiHandler.postDelayed(new Runnable() {public void run() {loadBleData();// 注销监听unregisterReceiver(bleReceiver);}}, 1000);}}}};




以上就能完成ble4.0的密码自动配对,当然中间的对话框会显示1s左右时间,然后会再次消失。




http://chatgpt.dhexx.cn/article/gpjdiaRL.shtml

相关文章

Android蓝牙开发(二)之蓝牙配对和蓝牙连接

上篇文章&#xff1a;https://blog.csdn.net/huangliniqng/article/details/82185983 讲解了打开蓝牙设备和搜索蓝牙设备&#xff0c;这篇文章来讲解蓝牙配对和蓝牙连接 1.蓝牙配对 搜索到蓝牙设备后&#xff0c;将设备信息填充到listview中&#xff0c;点击listiew则请求配对…

BLE蓝牙的连接和配对过程

一 连接 同一款手机&#xff0c;为什么跟某些设备可以连接成功&#xff0c;而跟另外一些设备又连接不成功&#xff1f;同一个设备&#xff0c;为什么跟某些手机可以建立连接&#xff0c;而跟另外一些手机又无法建立连接&#xff1f;同一个手机&#xff0c;同一个设备&#xff…

BLE蓝牙的配对过程浅析

BLE蓝牙配对过程 在了解到Bluetooth协议的大概后&#xff0c;本篇文章简单的梳理一下BLE蓝牙的配对过程和配对过程的数据格式&#xff0c;对于后面理解蓝牙的集中配对模式及相关漏洞浅浅奠定一下基础。 和经典蓝牙一样&#xff0c;协议为处于连接状态的BLE设备&#xff0c;定…

蓝牙设备的连接与配对

蓝牙是一种短距离无线通信技术&#xff0c;它由爱立信公司于1994年创制&#xff0c;原本想替代连接电信设备的数据线&#xff0c;但是后来发现它也能用于移动设备之间的数据传输&#xff0c;所以蓝牙技术在手机上获得了长足发展。 因为手机内部的通讯芯片一般同时集成了2G/3G/4…

Android 蓝牙连接,蓝牙配对,自动连接蓝牙

趁热打铁&#xff0c;这篇文章写于刚写完蓝牙配对Demo&#xff0c;主要介绍配对蓝牙的具体编码步骤&#xff0c;开整! 首先上效果图&#xff0c;看一下是否符合读者现在的需求 主要核心代码没有想象中那么复杂&#xff0c;首先要去申请一下权限&#xff0c;不仅需要蓝牙权限…

蓝牙配对方式

4种蓝牙配对方式&#xff0c;通俗地说&#xff1a; 1.Numeric Comparison&#xff1a;配对双方都显示一个6位的数字&#xff0c;由用户来核对数字是否一致&#xff0c;一致即可配对。例如手机之间的配对。 2.Just Works&#xff1a;用于配对没有显示没有输入的设备&#xff0c;…

蓝牙的配对和连接的建立过程

蓝牙的建立过程是一个复杂的过程&#xff0c;即使有过相当一段工作和使用经验的人&#xff0c;如果不仔细去了解还是理解不全。 平时我们用蓝牙耳机听音乐&#xff0c;和不同的设备共享文件&#xff0c;打电话等&#xff0c;都有一个配对--连接--传输数据的过程。 配对&#…

蓝牙|标准蓝牙配对方式

蓝牙:BlueTooth,是一种无线技术标准&#xff0c;可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换&#xff0c;蓝牙又分为传统/标准蓝牙和BLE蓝牙。 在了解配对方式前&#xff0c;先了解设备的IOCapacity,IOCapcaity是由设备InputCapacity和OutputCapacity组合而成…

蓝牙学习八(配对与绑定)

1.简介 Paring&#xff08;配对&#xff09;和Bonding&#xff08;绑定&#xff09;是实现蓝牙射频通信安全的一种机制&#xff0c;有两点需要注意&#xff1a; Paring/bonding实现的是蓝牙链路层的安全&#xff0c;对应用层来说是完全透明的。也就是说&#xff0c;不管有没有…

蓝牙 - 配对和连接

什么是蓝牙配对&#xff1f; 蓝牙配对是为了连接设备的一种信息注册方法。通过在设备之间注册设备信息&#xff08;配对&#xff09;&#xff0c;它们可以连接。要使用一个蓝牙设备&#xff0c;你必须首先将其与另一个蓝牙设备配对。配对有点像交换电话号码。类似于你必须与你…

Java 接口回调机制

日常开发中接口回调机制无处不在&#xff0c;刚开始用时却总是晕晕乎乎&#xff0c;网上也有很多相关的文章介绍&#xff0c;但总是没有看得太明白&#xff0c;今天端午假期正好花时间来总结一下&#xff0c;我们按如下顺序介绍 一、什么是接口回调 在应用开发中&#xff0c;接…

Android 接口回调

Android接口回调讲解 回调定义回调机制回调意义接口回调的实现步骤参考 网上看了一堆&#xff0c;感觉有点零散&#xff0c;我自己总结一下。 回调定义 正式定义 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另一…

理解Java接口回调

初步认识&#xff1a; 实现步骤&#xff1a; 1、创建一个回调接口。 2、创建一个回调对象实现回调接口。 3、创建一个控制器对象&#xff0c;将回调对象作为参数传给控制器对象&#xff0c;控制器对象负责检查某个场景是否出现或某个条件是否满足&#xff0c;当满足时&#…

Android 自定义接口回调

1.定义一个简单的接口回调 下面是定义一个简单的接口&#xff0c;实现的功能是&#xff0c;设置名字爱好&#xff0c;并且返回给主 Activity。 1.1 自定义一个接口 定义一个名字为 setNameListener() 的接口类&#xff1a; /*** author: wu* date: on 2018/10/23.* describ…

接口回调(笔记

接口回调讲解 回调定义回调机制回调意义接口回调的实现步骤参考 网上看了一堆&#xff0c;感觉有点零散&#xff0c;我自己总结一下。看评论区说存在很多问题&#xff0c;我读了一下&#xff0c;雀氏存在一些&#xff0c;非常感谢批评指正&#xff0c;我重新写一写。&#xff0…

接口回调与方法回调

1.1 接口回调 简介&#xff1a; 笔者查阅了大量资料&#xff0c;接口回调没有定义&#xff0c;可以理解为是一种设计思想。 其本质是将实现接口的类通过向上转型至接口类型&#xff0c;通过传入不同的子类&#xff0c;实现调用相应的子类重写的父类接口方法。 详情见&#xff…

Java接口回调详解

一.产生接口回调的场景 在现实生活中,产生接口回调的场景很简单,比如我主动叫你帮我做一件事,然后你做完这件事之后会通知我,"通知我"这个动作就是接口回调的动作.接口回调重在理解思就好.再举个例子用于下面的代码演示,老师让学生做课堂练习,学生做完练习后并告诉老…

java 接口回调的例子_java接口回调

java的接口回调原理网上已经有很多生动形象的例子说明了,在此总结一下个人的理解:类A调用类B的方法b(),类B再回调类A的方法a(),其中方法a()是定义在接口中的,由类A来实现。这是一个双向调用的过程,用下面的类图来加以说明。 Callback.png 1. 创建一个接口: public inter…

巧妙理解接口回调

接口回调目的和用法解析 一、为什么会有接口回调&#xff1f;什么是接口回调&#xff1f; 其实这两个问题是一个问题&#xff0c;知道了接口回调的原理自然就知道了为什么会有这么个东西。我们知道java中接口是不可以直接创建实例的&#xff0c;那么问题来了&#xff0c;假如…

[Java]什么是接口回调?

什么是接口回调&#xff1f; 1&#xff0e;接口回调是什么[2]&#xff1f; 接口回调是指&#xff1a;可以把使用某一接口的类创建的对象的引用赋给该接口声明的接口变量&#xff0c;那么该接口变量就可以调用被类实现的接口的方法。实际上&#xff0c;当接口变量调用被类实现…