packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothPairingDetail.java
@Override
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
disableScanning();
super.onDevicePreferenceClick(btPreference);
} packages\apps\Settings\src\com\android\settings\bluetooth\DeviceListPreferenceFragment.java
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
btPreference.onClicked();
} packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothDevicePreference.java
void onClicked() {
Context context = getContext();
// 获取连接状态
int bondState = mCachedDevice.getBondState(); final MetricsFeatureProvider metricsFeatureProvider =
FeatureFactory.getFactory(context).getMetricsFeatureProvider();
// 已经连接
if (mCachedDevice.isConnected()) {
// 断开连接
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_DISCONNECT);
askDisconnect();
// 以前连接过,不需要再配对,直接进行连接
} else if (bondState == BluetoothDevice.BOND_BONDED) {
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_CONNECT);
mCachedDevice.connect(true);
// 没连接过,进行配对,需要连接的双方都同意之后才能连接
} else if (bondState == BluetoothDevice.BOND_NONE) {
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR);
if (!mCachedDevice.hasHumanReadableName()) {
metricsFeatureProvider.action(context,
MetricsEvent.ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES);
}
pair();
}
} 1. 已经连接过的设备,直接断开
// Show disconnect confirmation dialog for a device.
private void askDisconnect() {
Context context = getContext();
String name = mCachedDevice.getName();
if (TextUtils.isEmpty(name)) {
name = context.getString(R.string.bluetooth_device);
}
String message = context.getString(R.string.bluetooth_disconnect_all_profiles, name);
String title = context.getString(R.string.bluetooth_disconnect_title);
// 对话框的listener
DialogInterface.OnClickListener disconnectListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mCachedDevice.disconnect();
}
};
// 显示断开对话框
mDisconnectDialog = Utils.showDisconnectDialog(context,
mDisconnectDialog, disconnectListener, title, Html.fromHtml(message));
} 2. 匹配过的设别,进行连接
frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\CachedBluetoothDevice.java
public void connect(boolean connectAllProfiles) {
// 是否配对过
if (!ensurePaired()) {
return;
} mConnectAttempted = SystemClock.elapsedRealtime();
connectWithoutResettingTimer(connectAllProfiles);
} private void connectWithoutResettingTimer(boolean connectAllProfiles) {
// Try to initialize the profiles if they were not.
if (mProfiles.isEmpty()) {
// if mProfiles is empty, then do not invoke updateProfiles. This causes a race
// condition with carkits during pairing, wherein RemoteDevice.UUIDs have been updated
// from bluetooth stack but ACTION.uuid is not sent yet.
// Eventually ACTION.uuid will be received which shall trigger the connection of the
// various profiles
// If UUIDs are not available yet, connect will be happen
// upon arrival of the ACTION_UUID intent.
Log.d(TAG, "No profiles. Maybe we will connect later");
return;
} // Reset the only-show-one-error-dialog tracking variable
mIsConnectingErrorPossible = true; int preferredProfiles = 0;
for (LocalBluetoothProfile profile : mProfiles) {
// connectAllProfile传进来的是true
if (connectAllProfiles ? profile.isConnectable() : profile.isAutoConnectable()) {
if (profile.isPreferred(mDevice)) {
++preferredProfiles;
connectInt(profile); // 连接对应的profile
}
}
}
if (DEBUG) Log.d(TAG, "Preferred profiles = " + preferredProfiles); if (preferredProfiles == 0) {
connectAutoConnectableProfiles();
}
} private void connectAutoConnectableProfiles() {
if (!ensurePaired()) {
return;
}
// Reset the only-show-one-error-dialog tracking variable
mIsConnectingErrorPossible = true; for (LocalBluetoothProfile profile : mProfiles) {
if (profile.isAutoConnectable()) {
profile.setPreferred(mDevice, true);
connectInt(profile);
}
}
} 3. 没有配对的设备,先进行配对
private void pair() {
if (!mCachedDevice.startPairing()) {
Utils.showError(getContext(), mCachedDevice.getName(),
R.string.bluetooth_pairing_error_message);
}
} frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\CachedBluetoothDevice.java
public boolean startPairing() {
// Pairing is unreliable while scanning, so cancel discovery
// 配对的时候,关闭扫描
if (mLocalAdapter.isDiscovering()) {
mLocalAdapter.cancelDiscovery();
} if (!mDevice.createBond()) {
return false;
} return true;
} frameworks\base\core\java\android\bluetooth\BluetoothDevice.java
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean createBond() {
final IBluetooth service = sService;
if (service == null) {
Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
return false;
}
try {
Log.i(TAG, "createBond() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
return service.createBond(this, TRANSPORT_AUTO);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
return false;
} packages\apps\Bluetooth\src\com\android\bluetooth\btservice\AdapterService.java
private static class AdapterServiceBinder extends IBluetooth.Stub {
public boolean createBond(BluetoothDevice device, int transport) {
if (!Utils.checkCallerAllowManagedProfiles(mService)) {
Log.w(TAG, "createBond() - Not allowed for non-active user");
return false;
} AdapterService service = getService();
if (service == null) return false;
return service.createBond(device, transport, null); // bond
} // 建立bond
boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
return false;
}
// 在多播的时候不要进行bond,不明白这个multicast是什么意思
// Multicast: Do not allow bonding while multcast
A2dpService a2dpService = A2dpService.getA2dpService();
if (a2dpService != null &&
a2dpService.isMulticastFeatureEnabled() &&
a2dpService.isMulticastOngoing(null)) {
Log.i(TAG,"A2dp Multicast is ongoing, ignore bonding");
return false;
} mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); // Pairing is unreliable while scanning, so cancel discovery
// Note, remove this when native stack improves
if (!mAdapterProperties.isDiscovering()) {
Log.i(TAG,"discovery not active, no need to send cancelDiscovery");
} else {
cancelDiscoveryNative();
}
// 或去状态机的消息
Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
msg.obj = device;
msg.arg1 = transport; if (oobData != null) {
Bundle oobDataBundle = new Bundle();
oobDataBundle.putParcelable(BondStateMachine.OOBDATA, oobData);
msg.setData(oobDataBundle);
}
// 发送消息给状态机
mBondStateMachine.sendMessage(msg);
return true;
} packages\apps\Bluetooth\src\com\android\bluetooth\btservice\BondStateMachine.java
private class StableState extends State {
@Override
public void enter() {
infoLog("StableState(): Entering Off State");
} @Override
public synchronized boolean processMessage(Message msg) { BluetoothDevice dev = (BluetoothDevice)msg.obj; switch(msg.what) { case CREATE_BOND:
OobData oobData = null;
if (msg.getData() != null)
oobData = msg.getData().getParcelable(OOBDATA); createBond(dev, msg.arg1, oobData, true);
break;
case REMOVE_BOND:
removeBond(dev, true);
break;
case BONDING_STATE_CHANGE:
int newState = msg.arg1;
/* if incoming pairing, transition to pending state */
if (newState == BluetoothDevice.BOND_BONDING)
{
if(!mDevices.contains(dev)) {
mDevices.add(dev);
}
sendIntent(dev, newState, 0);
transitionTo(mPendingCommandState);
}
else if (newState == BluetoothDevice.BOND_NONE)
{
/* if the link key was deleted by the stack */
sendIntent(dev, newState, 0);
}
else
{
Log.e(TAG, "In stable state, received invalid newState: " + newState);
}
break; case CANCEL_BOND:
default:
Log.e(TAG, "Received unhandled state: " + msg.what);
return false;
}
return true;
}
} private boolean createBond(BluetoothDevice dev, int transport, OobData oobData,
boolean transition) {
if(mAdapterService == null) return false;
if (dev.getBondState() == BluetoothDevice.BOND_NONE) {
infoLog("Bond address is:" + dev);
byte[] addr = Utils.getBytesFromAddress(dev.getAddress());
boolean result;
// 调用JNI
if (oobData != null) {
result = mAdapterService.createBondOutOfBandNative(addr, transport, oobData);
} else {
result = mAdapterService.createBondNative(addr, transport);
} if (!result) {
sendIntent(dev, BluetoothDevice.BOND_NONE,
BluetoothDevice.UNBOND_REASON_REMOVED);
return false;
} else if (transition) {
transitionTo(mPendingCommandState);
}
return true;
}
return false;
}

Liu Tao

2019-3-27

Android 8 蓝牙 连接过程的更多相关文章

  1. Android使用蓝牙连接adb调试App

    使用WiFi连接Android设备调试APP的教程非常多,可是项目中须要使用蓝牙进行通信.所以牵扯使用蓝牙调用adb. 1.   将电脑蓝牙与手机进行配对(控制面板->设备和打印机->加入 ...

  2. Android 8 蓝牙打开过程

    packages\apps\Settings\src\com\android\settings\bluetooth\BluetoothEnabler.java @Override public boo ...

  3. Android实现蓝牙耳机连接

    代码地址如下:http://www.demodashi.com/demo/13259.html 前言 讲讲android对于蓝牙耳机连接技术的实现 今天涉及的内容有: 流程讲解 新建广播Bluetoo ...

  4. 基于swift语言iOS8的蓝牙连接(初步)

    看过一些蓝牙App的事例,大体上对蓝牙的连接过程进行了了解.但是开始真正自己写一个小的BLE程序的时候就举步维艰了.那些模棱两可的概念在头脑中瞬间就蒸发了,所以还是决定从最基本的蓝牙连接过程进行.这里 ...

  5. ZT Android 4.2 BT系统之蓝牙关闭过程全跟踪

    Android 4.2 BT系统之蓝牙关闭过程全跟踪 分类: android 2013-08-03 00:34 2252人阅读 评论(10) 收藏 举报 代码位置:       frameworks/ ...

  6. Android蓝牙连接自动测试工具

    蓝牙连接自动测试工具 1.需求产生 开发不按着需求走都是耍流氓且浪费时间.此工具的需求产生是研发人员在开发产品时涉及到蓝牙驱动和安卓蓝牙两个东西.但是呢,蓝牙不太稳定,那么工作来了.就需要研发人员一边 ...

  7. ubuntu16.04连接android手机蓝牙共享网络热点

    最近的想要用android手机蓝牙共享wifi网络给ubuntu16.04系统用,查了好多资料,发现网上很少有有用的.自己实践后分享如下. 第一步:手机与电脑配对:         该步骤比较简单,网 ...

  8. Android Multimedia框架总结(十九)Camera2框架C/S模型之CameraService启动及与Client连接过程

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53150322 Agenda: 一 ...

  9. Android一对多蓝牙连接示例APP

    一对多蓝牙连接示例,基于Google BluetoothChat修改,实现一对多聊天(一个服务端.多个客户端),类似聊天室. 主要功能: 客户端的发出的消息所有终端都能收到(由服务端转发) 客户端之间 ...

随机推荐

  1. POJ 水题(刷题)进阶

    转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6642573 部分解题报告添加新内容,除了原有的"大致题意&q ...

  2. python数据类型及基本运算符

    1.数据类型 (1)什么是数据类型? 变量值是我们存储的数据,所以数据类型就是变量值的不同种类 (2)为什么要分类型? 变量值是为了保存现实世界中的状态,针对于不同的状态应该用不同的类型去表示 (3) ...

  3. vb.net播放资源文件中的音乐

    1.在自己的工程里添加一个资源文件. 2.打开添加的资源文件,资源类型选择为音频,点击添加资源把准备好的wav格式音乐文件添加进入资源文件. 3.设置资源属性和文件属性为嵌入 4.代码以及调用方法 P ...

  4. ES6 迭代器和生成器

    设计为了更高效的数据处理,避免过多for循环嵌套(代码复杂度,跟踪多个循环变量) 1. 迭代器: 为迭代过程设计的接口 所有的迭代器对象都有next()方法,每次调用都返回一个结果对象,对象有两个属性 ...

  5. List集合的总结和应用场景的介绍

    1.List的整体介绍 List 是一个接口,它继承于Collection的接口,它代表着有序的队列.list的实现类对象中每一个元素都有一个索引值,能够按照索引值进行元素查找. AbstractLi ...

  6. Java基础知识--内存管理

    Java语言中 的垃圾收集器相对于以前的其他语言优势是什么? 过去的语言需要程序员显示的进行分配内存.释放内存.这种做法可能会引起“内存泄漏”,即由于某种原因是分配给程序的内存无法释放,如果该任务不断 ...

  7. 小甲鱼Python第十四课后习题

    字符串格式化符号含义    符   号    说     明      %c    格式化字符及其ASCII码[>>> '%c' %97        'a']      %s    ...

  8. SSH报错

    1.SSH 加入HQL查询时,报错 antlr.collections.AST.getLine()I 2.百度发现是 因为struts 和 hibernate红都有antlr-2.7.2.jar,但两 ...

  9. 透明Panel

    unit TransparentPanel; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Varia ...

  10. CSS魔法堂:Transition就这么好玩

    前言  以前说起前端动画必须使用JS,而CSS3为我们带来transition和@keyframes,让我们可以以更简单(声明式代替命令式)和更高效的方式实现UI状态间的补间动画.本文为近期对Tran ...