BLE设备自动配对

由于公司需求,需要实现蓝牙遥控器在开机时实现自动配对,很早就写过,现做一下总结,
所谓自动配对就是长按遥控器组合键开启被扫描状态,Android设备运行BLE Scan 扫描到遥控器,主动进行连接。
分以下几个步骤
- 1.静态广播:蓝牙开启时(或开机广播),启动配对服务
- 2.配对服务:后台扫描以及配对遥控器
- 3.配对界面:配对状态:正在配对、配对成功、配对失败、配对超时、信号弱。


AutoPairBroadcast

package com.dtv.rc;import android.annotation.SuppressLint;import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;import android.content.Context;
import android.content.Intent;
import android.util.Log;@SuppressLint("NewApi")
public class AutoPairBroadcast extends BroadcastReceiver {private final String TAG = "AutoPairBroadcast";private BluetoothAdapter bluetoothAdapter;@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (action == null) return;bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (bluetoothAdapter == null) return;//在Android TV 版本上无法开机接收到蓝牙开启广播,只能监听开机广播启动配对服务if (action.equals("android.intent.action.BOOT_COMPLETED")) {enablePairService(context, true);}  if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {Log.d(TAG, " =================== >> ACTION:  " + action);int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);switch (state) {case BluetoothAdapter.STATE_TURNING_OFF://如果蓝牙被关闭,配对服务就没存在意义了,关闭服务enablePairService(context, false);break;case BluetoothAdapter.STATE_ON://一般开机时,蓝牙会随着开机一起打开,也代表蓝牙装备就绪,那么就开启配对服务//如果没随机开启,那就需要监听开机广播,然后再启动蓝牙enablePairService(context, true);break;default:break;}}
//设备挂载广播,当遥控器断开连接后,还是需要自动开启扫描。(同一遥控器多次配对就是这样)
//加上AutoPairService.RUNNING 判断是因为配对服务如果在运行,就不要在这里进行逻辑处理,在配对服务中也有对此ACTION的处理else if (action.equals("android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED") && !AutoPairService.RUNNING) {BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);int connectState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);//判断一下断开的设备是不是之前连接的遥控器,通过MAC或NAME判断if (device.getAddress().equals(AutoPairGlobalConfig.getRcMac()) || device.getName() != null&& (device.getName().startsWith((AutoPairGlobalConfig.getRcName())) || device.getName().startsWith(AutoPairGlobalConfig.DEF_NAME))) {if (connectState == BluetoothProfile.STATE_DISCONNECTED && bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {//断开连接,开启配对服务enablePairService(context, true);} else if (connectState == BluetoothProfile.STATE_CONNECTED) {//断开连接,停止配对服务enablePairService(context, false);}}}// TODO am broadcast -a android.action.hitv.STOP_LESCANelse if (action.equals("android.action.hitv.START_LESCAN")) {enablePairService(context, true);} else if (action.equals("android.action.hitv.STOP_LESCAN")) {enablePairService(context, false);}}public void enablePairService(Context context, boolean pair) {Log.d(TAG, " =================== >> enablePairService:  " + pair);Intent autoPairService = new Intent(context, AutoPairService.class);if(pair){context.startService(autoPairService);} else {context.stopService(autoPairService);}}}

AutoPairService


package com.dtv.rc;import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;import android.content.IntentFilter;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.view.WindowManager;import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;@SuppressLint("NewApi")
public class AutoPairService extends Service {// 蓝牙连接状态改变广播public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";// 蓝牙配对状态改变广播public static final String ACTION_BOND_STATE_CHANGED = BluetoothDevice.ACTION_BOND_STATE_CHANGED;// 蓝牙配对状态改变广播public static final String ACTION_UUID = BluetoothDevice.ACTION_UUID;private final static String TAG = AutoPairService.class.getSimpleName();private BluetoothManager mBluetoothManager;private BluetoothAdapter mBluetoothAdapter;private BluetoothDevice mPairingDevice;private BluetoothProfile mBluetoothProfile;private InputDeviceServiceListener mInputDeviceServiceListener;private BluetoothLeScanner mBLEScanner;private ScanSettings mScanSettings;private List<ScanFilter> mScanFilterList;private BleDeviceScanCallback mScanCallback;public static final int INPUT_DEVICE = 4;public static final int PRIORITY_AUTO_CONNECT = 1000;//开启扫描时间,一直开启BT会影响WIFI速率,也没必要一直开启,在15分后关闭扫描private static final long SCAN_PERIOD = 15 * 1000 * 60;public boolean mScanning = false;private PairHandler mHandler;public static boolean RUNNING = false;public static boolean KEEP_SCAN = false;@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> onCreate");RUNNING = true;mScanning = false;boolean init = initBluetooth();if (!init) return;initUI();// 广播接收器IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(ACTION_UUID);intentFilter.addAction(ACTION_BOND_STATE_CHANGED);intentFilter.addAction(ACTION_CONNECTION_STATE_CHANGED);registerReceiver(mBluetoothReceiver, intentFilter);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> onStartCommand");//第一次启动mBluetoothProfile可能还没回调初始化,在2.step会去扫描//第二次启动mBluetoothProfile已经初始化完毕,代表需要直接扫描,那么此时直接开启扫描if(mBluetoothProfile ==null){//TODO 1.step 获取输出设备的操作对象BluetoothProfilemInputDeviceServiceListener = new InputDeviceServiceListener();mBluetoothAdapter.getProfileProxy(this, mInputDeviceServiceListener, INPUT_DEVICE);} else {KEEP_SCAN = true;scanLeDevice(true);}return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> onDestroy");unregisterReceiver(mBluetoothReceiver);scanLeDevice(false);closeProfileProxy();RUNNING = false;super.onDestroy();}public boolean initBluetooth() {if (mBluetoothManager == null) {mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);if (mBluetoothManager == null) {Log.e(TAG, "Unable to initialize BluetoothManager.");return false;}}mBluetoothAdapter = mBluetoothManager.getAdapter();if (mBluetoothAdapter == null) {Log.e(TAG, "Unable to obtain a BluetoothAdapter.");return false;}mBLEScanner = mBluetoothAdapter.getBluetoothLeScanner();if (mBLEScanner == null) {Log.e(TAG, "Unable to obtain a BluetoothLeScanner.");return false;}mScanFilterList = new ArrayList<ScanFilter>();mScanSettings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();mScanCallback = new BleDeviceScanCallback();return true;}void closeProfileProxy() {if (mBluetoothProfile != null) {try {mBluetoothAdapter.closeProfileProxy(INPUT_DEVICE, mBluetoothProfile);mBluetoothProfile = null;} catch (Throwable t) {Log.e(TAG, "Error cleaning up HID proxy", t);}}}private final class InputDeviceServiceListener implements BluetoothProfile.ServiceListener {@Overridepublic void onServiceConnected(int profile, BluetoothProfile proxy) {try {if (profile == INPUT_DEVICE) {mBluetoothProfile = proxy;Log.i(TAG, "InputDeviceServiceListener onServiceConnected");// TODO 2.stepif (hasDeviceIsConnected() == null) {scanLeDevice(true);} else {scanLeDevice(false);}}} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(int profile) {Log.i(TAG, "InputDeviceServiceListener onServiceDisconnected");}}Runnable stopLeScanRunnable = new Runnable() {@Overridepublic void run() {if (mScanning) {mScanning = false;stopLeScan();}}}; public void scanLeDevice(final boolean enable) {if (enable) {// Stops scanning after a pre-defined scan period.mHandler.removeCallbacks(stopLeScanRunnable);mHandler.postDelayed(stopLeScanRunnable, SCAN_PERIOD);if (!mScanning) {mScanning = true;startLeScan();}} else {if (mScanning) {mScanning = false;stopLeScan();}}}void startLeScan() {Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> startLeScan" );if (mBLEScanner != null)mBLEScanner.startScan(mScanFilterList, mScanSettings, mScanCallback);}void stopLeScan() {Log.d(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> stopLeScan" );if (mBLEScanner != null) mBLEScanner.stopScan(mScanCallback);}private final class BleDeviceScanCallback extends ScanCallback {@Overridepublic void onScanResult(int callbackType, ScanResult result) {Log.d(TAG, " onScanResult <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");BluetoothDevice device = result.getDevice();int rssi = result.getRssi();byte[] scanRecord = result.getScanRecord().getBytes();if (device.getBondState() != BluetoothDevice.BOND_NONE) {return;}// TODO 3.step 验证扫描结果if (mPairingDevice != null) {return;}mPairingDevice = device;scanLeDevice(false);Log.d(TAG, "onScanResult  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Name:"+mPairingDevice.getName());Log.d(TAG, "onScanResult  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<MAC:"+mPairingDevice.getAddress());Log.d(TAG, "onScanResult  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<RSSI:" +(0 - rssi));//条件是否匹配if (isGoodMatchRc(mPairingDevice, rssi, scanRecord)) {Log.d(TAG, "onScanResult  GoodGoodGoodGoodGoodGoodGoodGood isGoodMatchRc: "+mPairingDevice.getAddress());//找到可配对的设备,停止LE扫描if (createBond(device)) {// TODO 4.step 等待广播mBluetoothReceiver更新结果showDialog(); //Dialog和广播同步} else {removeBond(mPairingDevice);// 若连接失败,移除它mPairingDevice = null;}} else {mPairingDevice = null;}//无法配对设备,开启LE扫描,重新寻找if (mPairingDevice == null) {scanLeDevice(true);} }@Overridepublic void onScanFailed(int errorCode) {}}// createBond 匹配状态 已经接受ACTION_UUID后进行连接private final BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);if (device == null) return;if(mPairingDevice == null) {if (isHmdDevice(device)) {if (action.equals(ACTION_CONNECTION_STATE_CHANGED)) {int connectState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);if (connectState == BluetoothProfile.STATE_CONNECTED) {// 遥控器连接后是否关闭扫描scanLeDevice(false);} else if (connectState == BluetoothProfile.STATE_DISCONNECTED) {// 遥控器断开后断是否开启扫描if (hasDeviceIsConnected() != null) {AutoPairGlobalConfig.setRcMac(device.getAddress());// 设置MAC地址if(!KEEP_SCAN) //可能是替换设备,此时不能关闭扫描scanLeDevice(false);} else {scanLeDevice(true);}}}}} else {// 配对时发生的状态改变if (mPairingDevice.getAddress().equals(device.getAddress())) {// 接收到了UUID直接尝试连接if (action.equals(ACTION_UUID)) {connect(device);} else  if (action.equals(ACTION_BOND_STATE_CHANGED)) { // 是否是正在连接设备的状态的改变int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);if (bondState == BluetoothDevice.BOND_NONE) { // 绑定失败mHandler.sendEmptyMessageDelayed(PairHandler.MSG_PAIR_FAIL, 20000);} else if (bondState == BluetoothDevice.BOND_BONDING) { // 正在绑定...mHandler.removeMessages(PairHandler.MSG_PAIR_FAIL);} else if (bondState == BluetoothDevice.BOND_BONDED) { // 绑定成功mHandler.removeMessages(PairHandler.MSG_PAIR_FAIL);} else if (bondState == BluetoothDevice.ERROR) {mHandler.sendEmptyMessage(PairHandler.MSG_PAIR_FAIL);}} else if (action.equals(ACTION_CONNECTION_STATE_CHANGED)) {int connectState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, BluetoothProfile.STATE_CONNECTED);if (connectState == BluetoothProfile.STATE_DISCONNECTED) { // 连接失败mHandler.removeMessages(PairHandler.MSG_PAIR_TIMEOUT);mHandler.sendEmptyMessage(PairHandler.MSG_PAIR_FAIL);} else if (connectState == BluetoothProfile.STATE_CONNECTING) { // 连接中...mHandler.removeMessages(PairHandler.MSG_PAIR_FAIL);} else if (connectState == BluetoothProfile.STATE_CONNECTED) { // 连接成功mHandler.removeMessages(PairHandler.MSG_PAIR_TIMEOUT);mHandler.removeMessages(PairHandler.MSG_PAIR_FAIL);mHandler.sendEmptyMessage(PairHandler.MSG_PAIR_SUCESS);AutoPairGlobalConfig.setRcMac(mPairingDevice.getAddress());// 设置MAC地址}}}}}};private void removeBond(BluetoothDevice device) {if (device != null) {int state = device.getBondState();if (state == BluetoothDevice.BOND_BONDING) {try {Method method = BluetoothDevice.class.getMethod("cancelBondProcess");method.invoke(device);} catch (Exception e) {e.printStackTrace();}}state = device.getBondState();if (state != BluetoothDevice.BOND_NONE) {try {Method method = BluetoothDevice.class.getMethod("removeBond");method.invoke(device);} catch (Exception e) {e.printStackTrace();}}}}public boolean createBond(BluetoothDevice device) {if (device != null) {if (device.getBondState() == BluetoothDevice.BOND_NONE) {return device.createBond();}}return false;}public void connect(BluetoothDevice device) {if (mBluetoothProfile != null && device != null) {try {Method method = mBluetoothProfile.getClass().getMethod("connect", new Class[]{BluetoothDevice.class});method.invoke(mBluetoothProfile, device);} catch (Exception e) {e.printStackTrace();}try {Method method = mBluetoothProfile.getClass().getMethod("setPriority", new Class[]{BluetoothDevice.class, int.class});method.invoke(mBluetoothProfile, device, PRIORITY_AUTO_CONNECT);} catch (Exception e) {e.printStackTrace();}}}void disconnect(final BluetoothDevice device) {try {Method method = mBluetoothProfile.getClass().getMethod("disconnect", new Class[]{BluetoothDevice.class});method.invoke(mBluetoothProfile, device);} catch (Exception e) {e.printStackTrace();}}public int getConnectionStatus(BluetoothDevice device) {if (mBluetoothProfile == null) {return BluetoothProfile.STATE_DISCONNECTED;}return mBluetoothProfile.getConnectionState(device);}// ########################################  配对过滤条件  ###########################################private static final int BLE_RSSI = 100;private static final int COMPLETE_NAME_FLAG = 0x09;private static final int UUID16_SERVICE_FLAG_MORE = 0x02;private static final int UUID16_SERVICE_FLAG_COMPLETE = 0x03;private static final int UUID32_SERVICE_FLAG_MORE = 0x04;private static final int UUID128_SERVICE_FLAG_COMPLETE = 0x07;private static final int HOGP_UUID16 = 0x1812;private long matchTime = 0;private boolean isGoodMatchRc(BluetoothDevice device, final int rssi, byte[] scanRecord) {boolean isHIMEDIARc;if (isHmdDevice(device)) {isHIMEDIARc = true;} else {isHIMEDIARc = isNameMatchExName(AutoPairGlobalConfig.getRcName(), scanRecord);}boolean isHOGPDevice = containHogpUUID(scanRecord);if (isHIMEDIARc && isHOGPDevice) {if ((0 - rssi) <= BLE_RSSI) {return true;} else if( System.currentTimeMillis() - matchTime > 10*1000) {mHandler.sendEmptyMessage(PairHandler.MSG_RSSI_LOW);matchTime = System.currentTimeMillis();}}return false;}public  boolean isHmdDevice(BluetoothDevice device) {if (device != null) {if (device.getAddress().equals(AutoPairGlobalConfig.getRcMac())) {return true;}if (device.getName() != null) {if (device.getName().startsWith(AutoPairGlobalConfig.DEF_NAME)) return true;if (device.getName().startsWith(AutoPairGlobalConfig.getRcName())) return true;}}return false;}// 是否有连接的遥控器private  BluetoothDevice hasDeviceIsConnected() {if (mBluetoothProfile != null) {List<BluetoothDevice> deviceList = mBluetoothProfile.getConnectedDevices();for (BluetoothDevice device : deviceList) {if (isHmdDevice(device)) {return device;}}}return null;}// 是否有已绑定的遥控器private BluetoothDevice hasDeviceIsBonded() {if (mBluetoothAdapter != null) {Set<BluetoothDevice> deviceList = mBluetoothAdapter.getBondedDevices();for (BluetoothDevice device : deviceList) {if (isHmdDevice(device)) {return device;}}}return null;}/* we only care 16bit UUID now */public static synchronized boolean containHogpUUID(byte[] scanRecord) {int i, j, length = scanRecord.length;i = 0;int uuid = 0;while (i < length - 2) {int element_len = scanRecord[i];byte element_type = scanRecord[i + 1];if (element_type == UUID16_SERVICE_FLAG_MORE || element_type == UUID16_SERVICE_FLAG_COMPLETE) {for (j = 0; j < element_len - 1; j++, j++) {uuid = scanRecord[i + j + 2] + (scanRecord[i + j + 3] << 8);if (uuid == HOGP_UUID16) {return true;}}} else if (element_type >= UUID32_SERVICE_FLAG_MORE && element_type >= UUID128_SERVICE_FLAG_COMPLETE) {}i += element_len + 1;}return false;}public static synchronized boolean isNameMatchExName(String name, byte[] scanRecord) {int i = 0;int length = scanRecord.length;byte[] byteName = new byte[50];String decodedName = null;while (i < length - 2) {int element_len = scanRecord[i];byte element_type = scanRecord[i + 1];if (element_type == COMPLETE_NAME_FLAG) {System.arraycopy(scanRecord, i + 2, byteName, 0, element_len - 1);try {decodedName = new String(byteName, "UTF-8");} catch (UnsupportedEncodingException e) {}if (decodedName != null) {if (decodedName.startsWith(name)) {return true;}}}i += element_len + 1;}return false;}// ########################################  UI  ###########################################private class PairHandler extends Handler {private static final int MSG_SHOW_DIALOG = 0x1;private static final int MSG_DIS_DIALOG = 0x2;private static final int MSG_PAIR_TIMEOUT = 0x3;private static final int MSG_PAIR_SUCESS = 0x4;private static final int MSG_PAIR_FAIL = 0x5;private static final int MSG_RSSI_LOW = 0x6;private static final int MSG_TIMEOUIT_REBT = 0x7;private static final int MSG_REBT = 0x7;private final WeakReference<Context> mContext;public PairHandler(Context context) {mContext = new WeakReference<Context>(context);}@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_SHOW_DIALOG:if (mPairDialog != null) {mPairDialog.show();showDialogProgress(true);setDialogText(R.string.auto_pairng);}break;case MSG_DIS_DIALOG:mHandler.removeMessages(MSG_PAIR_TIMEOUT);mHandler.removeMessages(MSG_PAIR_FAIL);mPairDialog.dismiss();disDialogPair();break;case MSG_PAIR_TIMEOUT:mHandler.removeCallbacksAndMessages(null);showDialogProgress(false);setDialogText(R.string.auto_pair_timeout);disDialog(3);// 配对超时,可能是蓝牙服务出问题了,可以重新启动蓝牙// mHandler.sendEmptyMessageDelayed(MSG_TIMEOUIT_REBT,3000);break;case MSG_PAIR_SUCESS:showDialogProgress(false);setDialogText(R.string.auto_pair_sucess);disDialog(3);break;case MSG_PAIR_FAIL:mHandler.removeMessages(MSG_PAIR_FAIL);mHandler.removeMessages(MSG_PAIR_TIMEOUT);mHandler.removeMessages(MSG_RSSI_LOW);//mBluetoothAdapter.disable();//关闭蓝牙//mHandler.sendEmptyMessageDelayed(MSG_TIMEOUIT_REBT,3000);showDialogProgress(false);setDialogText(R.string.auto_pair_fail);disDialog(3);break;case MSG_RSSI_LOW:mHandler.removeMessages(MSG_RSSI_LOW);showDialogProgress(false);setDialogText(R.string.auto_pair_rssi_low);disDialog(3);break;case MSG_TIMEOUIT_REBT:mBluetoothAdapter.enable();//重新开启蓝牙break;default:super.handleMessage(msg);break;}}}public AutoPairDialog mPairDialog;public void initUI() {if (mPairDialog == null) {mPairDialog = new AutoPairDialog(this, R.style.DialogStyle);mPairDialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));mHandler = new PairHandler(this.getBaseContext());}}public void showDialog() {mHandler.removeCallbacksAndMessages(null);mHandler.sendEmptyMessage(PairHandler.MSG_SHOW_DIALOG);mHandler.sendEmptyMessageDelayed(PairHandler.MSG_PAIR_TIMEOUT, 15 * 1000);// 15s超时}public void disDialog(int time) {mHandler.removeCallbacksAndMessages(null);mHandler.sendEmptyMessageDelayed(PairHandler.MSG_DIS_DIALOG, time * 1000);}public void setDialogText(int resid) {if (mPairDialog != null)mPairDialog.setDialogText(mPairDialog.getContext().getResources().getString(resid));}public void showDialogProgress(boolean show) {if (mPairDialog != null) mPairDialog.setDialogProgress(show);}public void disDialogPair() {if (mPairingDevice != null) {// 没连接成功if (getConnectionStatus(mPairingDevice) == BluetoothProfile.STATE_CONNECTED) {disOtherDeviceIsConnected();rmOtherDeviceIsBonded();} else {removeBond(mPairingDevice);}}mPairingDevice = null;if (hasDeviceIsConnected() != null) {scanLeDevice(false);} else {scanLeDevice(true);}}// 断开有连接的遥控器private void disOtherDeviceIsConnected() {if (mBluetoothProfile != null) {List<BluetoothDevice> deviceList = mBluetoothProfile.getConnectedDevices();for (BluetoothDevice device : deviceList) {if (isHmdDevice(device)) {if (mPairingDevice != null && mPairingDevice.getAddress().equals(device.getAddress())) {continue;}disconnect(device);}}}}private void rmOtherDeviceIsBonded() {Set<BluetoothDevice> deviceList = mBluetoothAdapter.getBondedDevices();for (BluetoothDevice device : deviceList) {if (isHmdDevice(device)) {if (mPairingDevice != null && mPairingDevice.getAddress().equals(device.getAddress())) {continue;}removeBond(device);}}}// #################################################################################################// AIDL 可以调用private final IBinder mBinder = new LocalBinder();@Overridepublic IBinder onBind(Intent intent) {return mBinder;}@Overridepublic boolean onUnbind(Intent intent) {return super.onUnbind(intent);}public class LocalBinder extends Binder {AutoPairService getService() {return AutoPairService.this;}}
}

核心就是这两个类,仅提参考。

  • BLE设备自动配对

    • AutoPairBroadcast
    • AutoPairService

本人从事Android TV 开发,若需要定制TV Setttings、TV Launcher、TV FileExplore,TV Mediaplay等相关TV软件请联系:QQ:1045612812

Android 智能机顶盒之蓝牙遥控器开机自动配对相关推荐

  1. android智能机顶盒的ota设计,智能机顶盒APP方案开发,让生活更有趣!

    原标题:智能机顶盒APP方案开发,让生活更有趣! 目前的有线存量机顶盒配置低.支撑业务比较少.用户体验也非常差,只能满足基本的看电视需求,并不支持新业务形态,也很难进行新业务拓展,面临用之无味.弃之可 ...

  2. 竖屏电视 安卓智能电视 广告机应用 开机自动播放 横屏竖屏 循环自动播放,

    基于安卓机顶盒的开发与应用(2)竖屏播放视频-图片-旋转-自动播放 通过基于安卓机顶盒的程序设计,开发出一套可以竖屏播放视频,图片功能. 1.优盘内有图片,开机后可以自动发现并显示,竖屏,横屏均可设置 ...

  3. android智能机顶盒测试,跑分过万 智能android机顶盒MINIX X5测试

    2013-8-1 16:12 [天极网家电频道]智能手机的风靡,让android系统风光无限,而开源和良好的兼容性,使得各种各样的设备都可以用上android系统啦. 导航仪可以用,相机可以用,电视盒 ...

  4. 安卓 蓝牙遥控器键值配对 kl文件

    场景:厂商送过来的蓝牙遥控器有可能linux上不对应,例如蓝牙的source 被识别为F1键,这时需要重新配置kl kl知识参考 https://www.jianshu.com/p/1b0ae800b ...

  5. android蓝牙配对 自动联接,Android系统下蓝牙自动配对连接方法

    Android系统下蓝牙自动配对连接方法 [专利摘要]本发明涉及一种Android系统下蓝牙自动配对连接方法,其包括如下步骤:步骤1.在Android设备端内存储上次进行蓝牙连接蓝牙外设的蓝牙地址,并 ...

  6. Android支持蓝牙midi键盘,CME推出无线MIDI蓝牙适配器WIDI Master,可以进行傻瓜式自动配对...

    12月19日消息,CME是中国的本土企业,也是国际上知名的MIDI设备制造商.CME日前宣布推出无线MIDI蓝牙适配器WIDI Master.该产品可以进行傻瓜式自动配对,无需复杂的连接和设置. 主要 ...

  7. 蓝牙遥控器与小米盒子增强版配对指南

    蓝牙遥控器和小米盒子增强版配对步骤: 1.打开蓝牙遥控器电池盖,将绝缘膜去掉后装好电池(正极朝上)和电池盖. 2.通过红外遥控器进入盒子[设置]->[系统设置]->[网络]->[蓝牙 ...

  8. Android 蓝牙遥控器的连接

    项目是TV端的,产品要求不经过设置界面,开机进入引导页,自动搜索蓝牙遥控器并且建立连接. 刚开始接手的时候以为会很快完成,无非就是调用API吗?可是事实不是这样,前后花了一些时间,才解决. 好了,当时 ...

  9. android 蓝牙 遥控器,Android 蓝牙遥控器的连接

    项目是TV端的,产品要求不经过设置界面,开机进入引导页,自动搜索蓝牙遥控器并且建立连接. 刚开始接手的时候以为会很快完成,无非就是调用API吗?可是事实不是这样,前后花了一些时间,才解决. 好了,当时 ...

  10. android+蓝牙遥控器,一种通过蓝牙遥控安卓设备的方法与流程

    本发明涉及安卓系统遥控领域,具体公开了一种通过蓝牙遥控安卓设备的方法. 背景技术: 随着数字技术的发展,人们使用的数字设备日新月异.现在最为常见的个人设备操作系统是安卓系统.对安卓设备控制的方式,最常 ...

最新文章

  1. 用bde连接 连接sql server2005
  2. C#基础-应用程序域
  3. 湖北大学数学与计算机科学学院,2017年湖北大学数学与计算机科学学院811数据结构考研题库...
  4. “单口相声”回归!罗永浩要开发布会了:黑科技!不售票!
  5. ionic4 组件的使用(一)
  6. 如何使用Mac预览程序将png转换为jpg格式的技巧分享
  7. C中遇到错误error: jump to label [-fpermissive]的解决办法
  8. plsql 存储过程 测试
  9. C#技术分享【PDF转换成图片——10种方案】(2013-07-25重新整理)
  10. 不支持S/W HEVC(H265)解码的有效解决方案
  11. Vienna大学5G链路级仿真平台简介
  12. 利用OpenCV实现一个简单的实时人脸检测项目并显示FPS
  13. 手把手学习和理解遗传算法的最佳例子
  14. amlogic logo amlogic rk tvbox 电视盒 定制化开发(一) 开机logo 定制
  15. WordPress必装插件推荐
  16. vue 如何下载文件(包含txt jpg pdf word)
  17. 基于51单片机的电子血压温度计(单片机健康检测系统设计)proteus仿真设计(仿真+程序+演示视频)
  18. Windows Server2012安装.NET Framework 3.5失败解决方案
  19. 关于逻辑学家的经典问题
  20. 树莓派学习笔记——更换国内源

热门文章

  1. 盘点:在造自行车的团队里,你最看好哪个?
  2. 【Hadoop实训】统计文件中所有单词的平均长度
  3. 有利网2022最新兑付消息,开展部分债务资金清退
  4. 前后端分离是什么意思?
  5. git master手动合并到develop
  6. workbench与SolidWorks联合划分六面体网格
  7. eclipse php集成包,php-eclipse集成配置(Ecli
  8. 整理苹果官网上iOS的各种辅助功能
  9. 更新来袭!新增语音添加待办、邮箱通知等功能
  10. Win7+U盘安装Ubuntu 双系统超级详细教程