android 蓝牙自动连接,蓝牙自动连接实现
实现的主要功能(蓝牙配对成功如何与远程设备一直连接)
1.当蓝牙配对成功连接时,断开远程端设备会自动连接
2.当设备长时间锁屏会导致CachedBluetoothDevice自动清空,如果蓝牙断开就不会自动连接的处理
实现步骤
监控蓝牙断开连接状态时发生哪些改变媒体音频与通话音频(a2dp与hfp)
1.在com.android.bluetooth.btservice.AdapterProperties这个类中蓝牙连接状态
void sendConnectionStateChange(BluetoothDevice device, int profile, int state, int prevState) {
if (!validateProfileConnectionState(state) ||
!validateProfileConnectionState(prevState)) {
// Previously, an invalid state was broadcast anyway,
// with the invalid state converted to -1 in the intent.
// Better to log an error and not send an intent with
// invalid contents or set mAdapterConnectionState to -1.
errorLog("Error in sendConnectionStateChange: "
+ "prevState " + prevState + " state " + state);
return;
}
synchronized (mObject) {
updateProfileConnectionState(profile, state, prevState);
if (updateCountersAndCheckForConnectionStateChange(state, prevState)) {
setConnectionState(state);
//留意BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED
Intent intent = new Intent(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
convertToAdapterState(state));
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
convertToAdapterState(prevState));
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mService.sendBroadcastAsUser(intent, UserHandle.ALL,
mService.BLUETOOTH_PERM);
Log.d(TAG, "CONNECTION_STATE_CHANGE: " + device + ": "
+ prevState + " -> " + state);
}
}
}
2.在com.android.bluetooth.a2dpsink.A2dpSinkStateMachine这个类中蓝牙连接状态
/** Handles A2DP connection state change intent broadcasts. */
private class IntentBroadcastHandler extends Handler {
private void onConnectionStateChanged(BluetoothDevice device, int prevState, int state) {
Intent intent = new Intent(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
//FIXME intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
//留意android.bluetooth.a2dp.sink... 及保存参数
intent = new Intent("android.bluetooth.a2dp.sink.profile.action.CONNECTION_STATE_CHANGED");
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothProfile.EXTRA_STATE, state);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
log("Connection state " + device + ": " + prevState + "->" + state);
mService.notifyProfileConnectionStateChanged(device, BluetoothProfile.A2DP_SINK,
state, prevState);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_CONNECTION_STATE_CHANGED:
onConnectionStateChanged((BluetoothDevice) msg.obj, msg.arg1, msg.arg2);
break;
}
}
}
3.在com.android.bluetooth.hfpclient.HeadsetClientStateMachine这个类中蓝牙连接状态
// This method does not check for error condition (newState == prevState)
private void broadcastConnectionState(BluetoothDevice device, int newState, int prevState) {
Log.d(TAG, "Connection state " + device + ": " + prevState + "->" + newState);
/*
* Notifying the connection state change of the profile before sending
* the intent for connection state change, as it was causing a race
* condition, with the UI not being updated with the correct connection
* state.
*/
mService.notifyProfileConnectionStateChanged(device, BluetoothProfile.HEADSET_CLIENT,
newState, prevState);
//留意
Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
...
mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
}
广播监听com.android.settings.bluetooth.DockEventReceiver
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null)
return;
...
} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
Log.d(TAG,"szjjyh ACTION_STATE_CHANGED btState = "+btState);
//蓝牙关闭时停止服务
if (btState == BluetoothAdapter.STATE_OFF){
Intent intent2 = new Intent(context, BluetoothConnectService.class);
context.stopService(intent2);
}
if (btState != BluetoothAdapter.STATE_TURNING_ON) {
Intent i = new Intent(intent);
i.setClass(context, DockService.class);
beginStartingService(context, i);
}
//这下面就是上面留意的几个action及相应的参数
}else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
int newState = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 0);
int oldState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE, 0);
changeDeviceStatus(device,newState,oldState,intent,context);
}else if ("android.bluetooth.a2dp.sink.profile.action.CONNECTION_STATE_CHANGED".equals(intent.getAction())) {
int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
changeDeviceStatus(device,newState,oldState,intent,context);
}else if (BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED.equals(intent.getAction())) {
int newState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, 0);
int oldState = intent.getIntExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, 0);
changeDeviceStatus(device,newState,oldState,intent,context);
}
}
public static void changeDeviceStatus(BluetoothDevice device,int newState, int oldState ,Intent intent,Context context) {
if (!Utils.isAutoConnectBluetooth()) {
return;
}
Log.d(TAG,"szjjyh changeDeviceStatus newState = "+newState+" oldState = "+oldState+
"device = "+device.getAddress());
synchronized (sStartingServiceSync) {
if (BluetoothAdapter.getDefaultAdapter().isEnabled()) {
if (oldState==BluetoothProfile.STATE_CONNECTING&&newState == BluetoothProfile.STATE_CONNECTED) {
//留意saveConnectDevice
LocalBluetoothPreferences.saveConnectDevice(context,device.getAddress());
Intent intent2 = new Intent(context, BluetoothConnectService.class);
context.stopService(intent2);
}else if ((oldState==BluetoothProfile.STATE_CONNECTED||oldState==BluetoothProfile.STATE_CONNECTING)
&&newState == BluetoothProfile.STATE_DISCONNECTED){
if (LocalBluetoothPreferences.getConnectDevice(context,"").equals(device.getAddress())) {
Intent i = new Intent(intent);
i.setClass(context, BluetoothConnectService.class);
beginStartingService(context, i);
}
}else if (oldState==BluetoothProfile.STATE_DISCONNECTING&&newState == BluetoothProfile.STATE_DISCONNECTED){
Intent intent2 = new Intent(context, BluetoothConnectService.class);
context.stopService(intent2);
}else if (oldState==BluetoothProfile.STATE_CONNECTED&&newState == BluetoothProfile.STATE_DISCONNECTING){
LocalBluetoothPreferences.saveConnectDevice(context,"");
}
}
}
}
com.android.settings.bluetooth.LocalBluetoothPreferences存储值
static void saveConnectDevice(Context context, String addr) {
SharedPreferences.Editor editor = getSharedPreferences(context).edit();
editor.putString(KEY_CONNECT_DEVICE , addr);
editor.apply();
}
com.android.settings.bluetooth.DeviceProfilesSettings点击断开连接时取消保存
public final class DeviceProfilesSettings extends DialogFragment implements
CachedBluetoothDevice.Callback, DialogInterface.OnClickListener, OnClickListener {
...
Button cancle = (Button) mRootView.findViewById(R.id.cancle);
cancle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCachedDevice.unpair();
//留意
LocalBluetoothPreferences.saveConnectDevice(getContext(), "");
com.android.settings.bluetooth.Utils.updateSearchIndex(getContext(),
BluetoothSettings.class.getName(), mCachedDevice.getName(),
getString(R.string.bluetooth_settings),
R.drawable.ic_settings_bluetooth, false);
dismiss();
}
});
...
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
EditText deviceName = (EditText) mRootView.findViewById(R.id.name);
mCachedDevice.setName(deviceName.getText().toString());
break;
case DialogInterface.BUTTON_NEUTRAL:
mCachedDevice.unpair();
//留意
LocalBluetoothPreferences.saveConnectDevice(getContext(), "");
com.android.settings.bluetooth.Utils.updateSearchIndex(getContext(),
BluetoothSettings.class.getName(), mCachedDevice.getName(),
getString(R.string.bluetooth_settings),
R.drawable.ic_settings_bluetooth, false);
break;
}
}
}
创建服务com.android.settings.bluetooth.BluetoothConnectService
public class BluetoothConnectService extends Service {
private static final String TAG = "BluetoothConnectService";
private Timer timer;
private LocalBluetoothAdapter mLocalAdapter;
private CachedBluetoothDeviceManager mDeviceManager;
private LocalBluetoothProfileManager mProfileManager;
@Override
public void onCreate() {
super.onCreate();
// isOpenTimer(true);
LocalBluetoothManager manager = Utils.getLocalBtManager(this);
if (manager == null) {
Log.e(TAG, "szjjyh Can't get LocalBluetoothManager: exiting");
return;
}
mLocalAdapter = manager.getBluetoothAdapter();
mDeviceManager = manager.getCachedDeviceManager();
mProfileManager =manager.getProfileManager();
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "szjjyh onDestroy");
if (timer != null) {
timer.cancel();
timer = null;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "szjjyh onStartCommand");
isOpenTimer(true);
return START_STICKY;
}
private void isOpenTimer(boolean isOpenWindow) {
if (isOpenWindow) {
if (timer == null) {
timer = new Timer();
timer.scheduleAtFixedRate(new RefreshTask(), 0, 1000 * 60 * 1);
}
} else {
if (timer != null) {
timer.cancel();
timer = null;
}
}
}
private class RefreshTask extends TimerTask {
@Override
public void run() {
autoConnectDevice();
}
}
private void autoConnectDevice() {
Set bondedDevices = mLocalAdapter.getBondedDevices();
if (bondedDevices == null) {
stopSelf();
return;
}
Log.d(TAG, "szjjyh RefreshTask bondedDevices ="+bondedDevices.size());
for (BluetoothDevice device : bondedDevices) {
CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
if (LocalBluetoothPreferences.getConnectDevice(this, "").equals(device.getAddress())) {
if (cachedDevice == null) {
cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
}
int bondState = cachedDevice.getBondState();
if (bondState == BluetoothDevice.BOND_BONDED&&!cachedDevice.isConnected()) {
cachedDevice.connect(false);
} else {
stopSelf();
}
}
}
}
}
蓝牙自动连接完毕经测试长时间灭屏重启远距离断开等场景再次检测到之前连接设备时会自动连接
android 蓝牙自动连接,蓝牙自动连接实现相关推荐
- android蓝牙开启后会尝试自动连接,Android 自动连接蓝牙
蓝牙是手机和智能硬件通信常用的方式,蓝牙通信可分为传统蓝牙和低功耗蓝牙(BLE).其中BLE的连接断开等操作可以通过Android SDK中提供的API进行操作,而传统蓝牙部分SDK并没有提供相关的A ...
- Android手机靠近蓝牙模块自动连接蓝牙模块,断后自动重连。也可以手机靠近手机自动连接。连接成功率百分之百,可后台运行
BluetoothChat手机与串口模块通信靠近自动连接2.0apk示例:链接: https://pan.baidu.com/s/1YoMNNBfLTAuXm2XukG5s9g 提取码: sm3h 全 ...
- Android实现蓝牙的搜索,配对(不需要输入PIN,自动匹配),连接,通信
目录 目录 一.蓝牙设置权限 二.蓝牙搜索 1.首先需要获得蓝牙适配器. 2.判断蓝牙是否打开,然后请求打开蓝牙 3.搜索蓝牙 三.蓝牙配对 1.动态注册广播接收器 2.判断蓝牙设备是否为目标设备,并 ...
- Android BLE低功耗蓝牙重启手机后自动连接失败问题
最近在做安卓开发,用到蓝牙模块相关功能.主要功能是使用手机连上低功耗蓝牙设备,比如蓝牙手环.关于如何蓝牙连接在这里就不讲述了,网上搜索一大堆相关教程.想要来这里看蓝牙连接方式的朋友可能要大失所望了. ...
- 解决Mac电脑开机无法自动连接蓝牙音箱问题!
苹果系统的电脑无法自动连接外置的蓝牙音箱,每次都要手动选择点选蓝牙连接,然后选择声音输出为蓝牙音箱,有点小烦,具体解决方法放在下面,一分钟搞定! 1.安装蓝牙连接工具"blueutil&qu ...
- 微信小程序自动连接蓝牙电子秤
不同品牌的称,只需要打印下方函数返回值,根据自己需要做处理就可以了. wx.onBLECharacteristicValueChange(function (res) {let receiverTex ...
- flutter实现自动连接蓝牙
flutter蓝牙功能实现 不会flutter可以做蓝牙吗 使用方式 蓝牙权限 蓝牙自动连接读取数据 不会flutter可以做蓝牙吗 我的回答是可以的,0基础flutter半天时间搞定蓝牙功能,首先介 ...
- Android连接蓝牙打印机
前言 在之前写过一篇Android操作蓝牙打印机(上),当时也是因为自己在工作中确实走了许多弯路,所以当时计划着用两篇文章详细阐述蓝牙打印的整个流程,也是对工作的一种总结,其次也可以给蓝牙打印方面感觉 ...
- 【Android】蓝牙开发——经典蓝牙:配对与解除配对 实现配对或连接时不弹出配对框
目录 一.配对方法 二.解除配对方法 三.配对/解除配对结果 四.justwork配对模式下,不弹出配对框 五.pincode配对模式下,不弹出配对框 六.小结 在之前的文章[Android]蓝牙开发 ...
- 蓝牙快速连接 android,Android智能设备快速连接蓝牙的方法与流程
技术特征: 1.Android智能设备快速连接蓝牙的方法,其特征在于,在Android系统根目录下的init.rc中注册native蓝牙服务,native蓝牙服务进程在开机时启动,完成对本机蓝牙模块和 ...
最新文章
- pyqt4+chatterbot实现简单聊天机器人程序
- 流行的14个机器学习编程语言框架和工具
- 放大器和比较器的区别
- TortoiseSVN客户端重新设置用户名和密码
- android实现计时器
- adonis.js mysql_Adonis.js——数据库基本操作
- 解决SublimeCodeIntel回车换行误打代码
- 【LeetCode笔记】剑指Offer 19. 正则表达式匹配(Java、动态规划)
- mysql 时间 between查询 索引吗_Mysql: mysql between 日期索引 索引问题-日期索引使用...
- Halcon 轮廓合并算子
- 操作系统|操作系统概述
- GitOps:Weaveworks通过开发者工具实现CI/CD
- JZOJ.5264【NOIP2017模拟8.12】化学
- iptables 之 REJECT 与 DROP 对比
- bp神经网络数字识别matlab_pytorch神经网络实践(1): 安装与初次使用pytorch搭建神经网络实践手写数字识别教程
- 登陆界面HTML验证码生成
- 什么是Web应用程序防火墙?
- 思维导图怎么画简单又漂亮?思维导图制作方法分享
- t-SNE数据降维可视化
- OFFPIPE 海底管道铺设计算分析软件