基于源码开机蓝牙一直扫描并自动连接指定的蓝牙设备

注:"fd_501_car".equals(android.os.Build.CUSTOM_FEATURE):这个是我自己添加的一个变量,可用宏控实现
packages/apps/Settings/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
这个类用是设置里面扫描到的蓝牙设备列表,可以在 public void onDeviceAdded(CachedBluetoothDevice cachedDevice)方法中过滤,使指定的蓝牙添加到列表中,可通过mac地址和蓝牙名,建议使用mac地址,蓝牙名称可变化,不具有唯一性,如:
    public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
        Xlog.d(TAG, "onDeviceAdded, Device name is " + cachedDevice.getName());
//zhy cachedDevice.getAddress() || cachedDevice.getName()
        if (mDevicePreferenceMap.get(cachedDevice) != null) {
            Xlog.d(TAG, "Device name " + cachedDevice.getName() + " already have preference");
            return;
        }
//add by zhy start
         if("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE)){
             if(!("11:22:33:44:55:66".equals(cachedDevice.getDevice().getAddress()) || "11:22:33:44:55:77".equals(cachedDevice.getDevice().getAddress())))
                return;
         }
//add by zhy end


packages/apps/Settings/src/com/android/settings/bluetooth/Utils.java
在static void showError(Context context, String name, int messageResId)方法中添加retrun退出,如:
    static void showError(Context context, String name, int messageResId) {
        String message = context.getString(messageResId, name);
        LocalBluetoothManager manager = LocalBluetoothManager.getInstance(context);
        if(manager == null) {
            return;
        }
//add by zhy start
        if ("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE)) {
            return;
        }
//add by zhy end

防止配对失败弹出对话框,对于没有显示屏开发是很有必要的,下面会讲下取消配对弹出对话框的实现方法

packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothEventManager.java
这个类是对BluetoothDevice.ACTION_FOUND广播监听的
    private class DeviceFoundHandler implements Handler {
        public void onReceive(Context context, Intent intent,
                BluetoothDevice device) {
            short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
            BluetoothClass btClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS);
            String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
            Xlog.d(TAG, "Device " + name + " ,Class: " + (btClass != null ? btClass.getMajorDeviceClass() : null));
            // TODO Pick up UUID. They should be available for 2.1 devices.
            // Skip for now, there's a bluez problem and we are not getting uuids even for 2.1.
            CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
            if (cachedDevice == null) {
                cachedDevice = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, device);
                Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
                        + cachedDevice);
            }
            // callback to UI to create Preference for new device
            /// M: no matter the found device is in the device list,
            /// call onDeviceAdded(), if the device preference has been 
            /// added to the screen, it will not add again
            dispatchDeviceAdded(cachedDevice);
            
            cachedDevice.setRssi(rssi);
            cachedDevice.setBtClass(btClass);
            cachedDevice.setName(name);
            cachedDevice.setVisible(true);
//add by zhy start
            if("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE)){
                 if("11:22:33:44:55:66".equals(device.getAddress()) || "11:22:33:44:55:77".equals(device.getAddress())){
                     bluetoothAutoConnect(cachedDevice,context);//扫描到指定mac地址自动发起连接
                 }
            }
//add by zhy end

        }
    }
//add by zhy start
    public void bluetoothAutoConnect(CachedBluetoothDevice cachedDevice,Context context) {
        int bondState = cachedDevice.getBondState();
        Xlog.d(TAG, "zhy address " + cachedDevice.getDevice().getAddress());
        if (bondState == BluetoothDevice.BOND_BONDED) {
            cachedDevice.connect(true);
        } else if (bondState == BluetoothDevice.BOND_NONE) {
            pair(cachedDevice,context);
        }
    }

    private void pair(CachedBluetoothDevice cachedDevice,Context context) {
        if (!cachedDevice.startPairing()) {
            Utils.showError(context, cachedDevice.getName(),
                    R.string.bluetooth_pairing_error_message);
        }
    }
//add by zhy end


packages/apps/Bluetooth/src/com/android/bluetooth/btservice/BondStateMachine.java
这个用于只有指定的设备mac才能进行配对成功,其他的不能配对成功
    private class StableState extends State {
              ........
                  removeBond(dev, true);
                  break;
              case BONDING_STATE_CHANGE:
                int newState = msg.arg1;
                /* if incoming pairing, transition to pending state */
//modify bluetooth mac addres dev.getAddress() 请求配对
                if (newState == BluetoothDevice.BOND_BONDING)
                {
                    if("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE)){
                        if("11:22:33:44:55:66".equals(dev.getAddress()) || "11:22:33:44:55:77".equals(dev.getAddress())){
                            sendIntent(dev, newState, 0);//BluetoothDevice.ACTION_BOND_STATE_CHANGED发送蓝牙绑定状态改变的广播
                            transitionTo(mPendingCommandState);
                        }
                     }
else{
                        sendIntent(dev, newState, 0);
                        transitionTo(mPendingCommandState);
                    }

                }
packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
private int getConnectionSummary(){
......
        if (profileConnected) {
            if (a2dpNotConnected && headsetNotConnected) {
                return R.string.bluetooth_connected_no_headset_no_a2dp;
            } else if (a2dpNotConnected) {
                return R.string.bluetooth_connected_no_a2dp;
            } else if (headsetNotConnected) {
                return R.string.bluetooth_connected_no_headset;
            } else {
//add by zhy start
                android.provider.Settings.System.putInt(getContext().getContentResolver(), "blue_connected", 1);
//add by zhy end

                return R.string.bluetooth_connected;
            }
        }

        switch (cachedDevice.getBondState()) {
            case BluetoothDevice.BOND_BONDING:
                return R.string.bluetooth_pairing;

            case BluetoothDevice.BOND_BONDED:
            case BluetoothDevice.BOND_NONE:
            default:
//add by zhy start
                android.provider.Settings.System.putInt(getContext().getContentResolver(), "blue_connected", 0);
//add by zhy end

                return 0;
        }
用于写系统数据库,功能是用于判断蓝牙设备是否已连接状态,如不是已连接状态,则一直扫描
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
用于开机后启动扫描功能,通过log分析,发现这里比较适合
//add by zhy start
   public BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   public void startDiscovery(Context context){
        int blue_connect = android.provider.Settings.System.getInt(context.getContentResolver(), "blue_connected", 0);;
        if (adapter.getState() == BluetoothAdapter.STATE_OFF) {// 如果蓝牙还没开启  
            adapter.enable();   
        }   
                
        Object[] lstDevice = adapter.getBondedDevices().toArray();  
        for (int i = 0; i < lstDevice.length; i++) {  
           BluetoothDevice device = (BluetoothDevice) lstDevice
           Log.d("zhy","zhy----"+device.getName()); 
        }  
        Log.d("zhy","zhy----blue_connect="+blue_connect); 
        if(blue_connect == 1){
            Log.d("zhy","zhy----stop"); 
            if (adapter.isDiscovering())  
                adapter.cancelDiscovery();  
        }else{
            Log.d("zhy","zhy----start"); 
            adapter.startDiscovery();  
        }
    }
//add by zhy end

    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            if (Intent.ACTION_TIME_TICK.equals(action)
                    || Intent.ACTION_TIME_CHANGED.equals(action)
                    || Intent.ACTION_TIMEZONE_CHANGED.equals(action)
                    || Intent.ACTION_LOCALE_CHANGED.equals(action)) {
                if (Intent.ACTION_LOCALE_CHANGED.equals(action)
                        || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
                    // need to get a fresh date format
                    mDateFormat = null;
                }
                updateClock();
//add by zhy start
                if ("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE)) {
                     startDiscovery(context);
                }
//add by zhy end
           }
        }
    };

packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
用于取消配对对话框功能
//add zhy start
    String temp = null;
    private void onPair(String value,int type,BluetoothDevice device) {
        switch (type) {
            case BluetoothDevice.PAIRING_VARIANT_PIN:
                byte[] pinBytes = BluetoothDevice.convertPinToBytes(value);
                if (pinBytes == null) {
                    return;
                }
                device.setPin(pinBytes);
                break;

            case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
                int passkey = Integer.parseInt(value);
                device.setPasskey(passkey);
                break;

            case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
            case BluetoothDevice.PAIRING_VARIANT_CONSENT:
                device.setPairingConfirmation(true);
                break;

            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY:
            case BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN:
                // Do nothing.
                break;

            case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
                device.setRemoteOutOfBandData();
                break;

            default:
        }
    }
//add zhy end

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
            // convert broadcast intent into activity intent (same action string)
            BluetoothDevice device =
                    intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
                    BluetoothDevice.ERROR);
            Intent pairingIntent = new Intent();
            pairingIntent.setClass(context, BluetoothPairingDialog.class);
            pairingIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
            pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, type);
            if (type == BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION ||
                    type == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY ||
                    type == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN) {
                int pairingKey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY,
                        BluetoothDevice.ERROR);
                pairingIntent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pairingKey);

            //add zhy start
                temp = pairingKey+"";
                if ("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE) && type == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN) {
                     byte[] pinBytes = BluetoothDevice.convertPinToBytes(String.format(java.util.Locale.US,"%04d", temp));
                     device.setPin(pinBytes);
                }
             //add zhy end

            }
            pairingIntent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
            pairingIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            PowerManager powerManager =
                    (PowerManager)context.getSystemService(Context.POWER_SERVICE);
            String deviceAddress = device != null ? device.getAddress() : null;

            //zhy
            // Since its only a notification, send an OK to the framework,
            // indicating that the dialog has been displayed.
            if ("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE) && type == BluetoothDevice.PAIRING_VARIANT_DISPLAY_PASSKEY) {
                device.setPairingConfirmation(true);
            }

            if ("fd_501_car".equals(android.os.Build.CUSTOM_FEATURE) || powerManager.isScreenOn() &&
                    LocalBluetoothPreferences.shouldShowDialogInForeground(context, deviceAddress)
) {
                // Since the screen is on and the BT-related activity is in the foreground,
                // just open the dialog
                //zhy
                if (!"fd_501_car".equals(android.os.Build.CUSTOM_FEATURE)) {
                    context.startActivity(pairingIntent);//这个是对话框dialogactivity
                } else {
                    onPair(temp,type,device);
                }

            }
这个是发送接收配对的广播


以上就是这几天修改问题总结的经验,里面还有很多是可以优化的,做的不是很好,请大家谅解
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值