当前位置: 首页 > article >正文

android10 蓝牙(一)开关与扫描源码解析

蓝牙开关源码分析

xref: /packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothEnabler.java

@Override
public boolean onSwitchToggled(boolean isChecked) {
    if (maybeEnforceRestrictions()) {
        triggerParentPreferenceCallback(isChecked);
        return true;
    }

    // Show toast message if Bluetooth is not allowed in airplane mode
    if (isChecked &&
            !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_BLUETOOTH)) {
        Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
        // Reset switch to off
        mSwitchController.setChecked(false);
        triggerParentPreferenceCallback(false);
        return false;
    }

    mMetricsFeatureProvider.action(mContext, mMetricsEvent, isChecked);

    if (mBluetoothAdapter != null) {
        boolean status = setBluetoothEnabled(isChecked);
        // If we cannot toggle it ON then reset the UI assets:
        // a) The switch should be OFF but it should still be togglable (enabled = True)
        // b) The switch bar should have OFF text.
        if (isChecked && !status) {
            mSwitchController.setChecked(false);
            mSwitchController.setEnabled(true);
            mSwitchController.updateTitle(false);
            triggerParentPreferenceCallback(false);
            return false;
        }
    }
    mSwitchController.setEnabled(false);
    triggerParentPreferenceCallback(isChecked);
    return true;
}


.........................................................................................


private boolean setBluetoothEnabled(boolean isEnabled) {
    return isEnabled ? mBluetoothAdapter.enable() : mBluetoothAdapter.disable();
}

        蓝牙开关封装在BluetoothEnabler.java中,实现了SwitchWidgetController.OnSwitchChangeListener监听,重写onSwitchToggled方法。在onSwitchToggled方法中调用setBluetoothEnabled方法,根据传入的boolean值打开蓝牙开关或者关闭蓝牙开关。

蓝牙扫描源码分析

xref: /frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java

private LocalBluetoothManager(LocalBluetoothAdapter adapter, Context context, Handler handler,
        UserHandle userHandle) {
    mContext = context.getApplicationContext();
    mLocalAdapter = adapter;
    mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, this);
    mEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext,
            handler, userHandle);
    mProfileManager = new LocalBluetoothProfileManager(mContext,
            mLocalAdapter, mCachedDeviceManager, mEventManager);

    mProfileManager.updateLocalProfiles();
    mEventManager.readPairedDevices();
}

        打开蓝牙开关后开启蓝牙扫描,调用LocalBluetoothManager方法,在构造方法中会创建BluetoothEventManager对象。

xref: /frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java

BluetoothEventManager(LocalBluetoothAdapter adapter,
        CachedBluetoothDeviceManager deviceManager, Context context,
        android.os.Handler handler, @Nullable UserHandle userHandle) {
    mLocalAdapter = adapter;
    mDeviceManager = deviceManager;
    mAdapterIntentFilter = new IntentFilter();
    mProfileIntentFilter = new IntentFilter();
    mHandlerMap = new HashMap<>();
    mContext = context;
    mUserHandle = userHandle;
    mReceiverHandler = handler;

    // Bluetooth on/off broadcasts
    addHandler(BluetoothAdapter.ACTION_STATE_CHANGED, new AdapterStateChangedHandler());
    // Generic connected/not broadcast
    addHandler(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED,
            new ConnectionStateChangedHandler());

    // Discovery broadcasts
    addHandler(BluetoothAdapter.ACTION_DISCOVERY_STARTED, new ScanningStateChangedHandler(true));
    addHandler(BluetoothAdapter.ACTION_DISCOVERY_FINISHED, new ScanningStateChangedHandler(false));
    addHandler(BluetoothDevice.ACTION_FOUND, new DeviceFoundHandler());
    addHandler(BluetoothDevice.ACTION_NAME_CHANGED, new NameChangedHandler());
     addHandler(BluetoothDevice.ACTION_ALIAS_CHANGED, new NameChangedHandler());

     // Pairing broadcasts
     addHandler(BluetoothDevice.ACTION_BOND_STATE_CHANGED, new BondStateChangedHandler());

     // Fine-grained state broadcasts
     addHandler(BluetoothDevice.ACTION_CLASS_CHANGED, new ClassChangedHandler());
     addHandler(BluetoothDevice.ACTION_UUID, new UuidChangedHandler());
     addHandler(BluetoothDevice.ACTION_BATTERY_LEVEL_CHANGED, new BatteryLevelChangedHandler());

     // Active device broadcasts
     addHandler(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
     addHandler(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED, new ActiveDeviceChangedHandler());
     addHandler(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED,
             new ActiveDeviceChangedHandler());

     // Headset state changed broadcasts
     addHandler(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED,
             new AudioModeChangedHandler());
     addHandler(TelephonyManager.ACTION_PHONE_STATE_CHANGED,
             new AudioModeChangedHandler());

     // ACL connection changed broadcasts
     addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
     addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());

     registerAdapterIntentReceiver();
}


......................................................................................


void addHandler(String action, Handler handler) {
    mHandlerMap.put(action, handler);
    mAdapterIntentFilter.addAction(action);
}


........................................................................................


private class DeviceFoundHandler implements Handler {
    public void onReceive(Context context, Intent intent,
            BluetoothDevice device) {
        short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
        String name = intent.getStringExtra(BluetoothDevice.EXTRA_NAME);
        // 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(device);
            Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice: "
                    + cachedDevice);
        } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
                &&!cachedDevice.getDevice().isConnected()) {
            // Dispatch device add callback to show bonded but
            // not connected devices in discovery mode
            dispatchDeviceAdded(cachedDevice);
            Log.d(TAG, "DeviceFoundHandler found bonded and not connected device:"
                    + cachedDevice);
        } else {
            Log.d(TAG, "DeviceFoundHandler found existing CachedBluetoothDevice:"
                    + cachedDevice);
        }
        cachedDevice.setRssi(rssi);
        cachedDevice.setJustDiscovered(true);
    }
}


........................................................................................


void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) {
    synchronized (mCallbacks) {
        for (BluetoothCallback callback : mCallbacks) {
            callback.onDeviceAdded(cachedDevice);
        }
    }
}

将DeviceFoundHandler添加到addHandler中,DeviceFoundHandler方法中调用了dispatchDeviceAdded方法。在dispatchDeviceAdded会遍历所有的BluetoothCallback,回调onDeviceAdded方法。

xref: /packages/apps/Settings/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java

@Override
public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
    if (mDevicePreferenceMap.get(cachedDevice) != null) {
        return;
    }

    // Prevent updates while the list shows one of the state messages
    if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) return;

    if (mFilter.matches(cachedDevice.getDevice())) {
        createDevicePreference(cachedDevice);
    }
}


.........................................................................................



void createDevicePreference(CachedBluetoothDevice cachedDevice) {
    if (mDeviceListGroup == null) {
        Log.w(TAG, "Trying to create a device preference before the list group/category "
                + "exists!");
        return;
    }

    String key = cachedDevice.getDevice().getAddress();
    BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key);

    if (preference == null) {
        preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice,
                mShowDevicesWithoutNames);
        preference.setKey(key);
        //Set hideSecondTarget is true if it's bonded device.
        preference.hideSecondTarget(true);
        mDeviceListGroup.addPreference(preference);
    }

    initDevicePreference(preference);
    mDevicePreferenceMap.put(cachedDevice, preference);
}

        在DeviceListPreferenceFragment.java的onDeviceAdded回调方法中会收到回调事件。调用createDevicePreference方法。在createDevicePreference方法中会将扫描到的蓝牙添加到mDeviceListGroup中,从而显示在界面上。

xref: /packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDevicePreference.java

public BluetoothDevicePreference(Context context, CachedBluetoothDevice cachedDevice,
        boolean showDeviceWithoutNames) {
    super(context, null);
    mResources = getContext().getResources();
    mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
    mShowDevicesWithoutNames = showDeviceWithoutNames;

    if (sDimAlpha == Integer.MIN_VALUE) {
        TypedValue outValue = new TypedValue();
        context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
        sDimAlpha = (int) (outValue.getFloat() * 255);
    }

    mCachedDevice = cachedDevice;
    mCachedDevice.registerCallback(this);

    onDeviceAttributesChanged();
}


..............................................................................................................



public void onDeviceAttributesChanged() {
    /*
     * The preference framework takes care of making sure the value has
     * changed before proceeding. It will also call notifyChanged() if
     * any preference info has changed from the previous value.
     */
    setTitle(mCachedDevice.getName());
    // Null check is done at the framework
    setSummary(mCachedDevice.getConnectionSummary());

    final Pair<Drawable, String> pair =
            BluetoothUtils.getBtRainbowDrawableWithDescription(getContext(), mCachedDevice);
    if (pair.first != null) {
        setIcon(pair.first);
        contentDescription = pair.second;
    }

    // Used to gray out the item
    setEnabled(!mCachedDevice.isBusy());

    // Device is only visible in the UI if it has a valid name besides MAC address or when user
    // allows showing devices without user-friendly name in developer settings
    setVisible(mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName());

    // This could affect ordering, so notify that
    if (mNeedNotifyHierarchyChanged) {
        notifyHierarchyChanged();
    }
}

        在BluetoothDevicePreference类的onDeviceAttributesChanged方法中会设置标题、概述以及图标等。


http://www.kler.cn/a/383706.html

相关文章:

  • Maven(20) 如何使用Maven进行版本管理?
  • 【LeetCode】【算法】206. 反转链表
  • ASP页面改为UTF-8编码后,刷新页面不定时中文输出乱码终极解决方案
  • rabbitMQ RabbitTemplate 发送消息
  • 【前端】JSX 中的 Fragments 详解
  • Python解力扣算法题(六)(详解+注释)
  • STM32Cube高效开发教程<高级篇><FreeRTOS>(十二)-----互斥量使用例程
  • Java学习Day58:相声二人组!(项目统计数据Excel图表导出)
  • 前端八股文(一)HTML 持续更新中。。。
  • 如何用PPT画箭头?用这2个ppt软件快速完成绘图!
  • 文件操作:Xml转Excel
  • Git代码托管(三)可视化工具操作(1)
  • 最全的Flutter中pubspec.yaml及其yaml 语法的使用说明
  • uniapp组件实现省市区三级联动选择
  • 【Unity基础】粒子系统与VFX Graph的区别
  • 【LeetCode】【算法】226. 翻转二叉树
  • echarts图表的使用(常用属性)
  • 数据特征工程:如何计算Teager能量算子(TEO)? | 基于SQL实现
  • 使用LoRA 对千问70B模型进行微调
  • Jupyter Notebook添加kernel的解决方案
  • 汇聚全球前沿科技产品,北京智能科技产业展览会·世亚智博会
  • 人工智能驱动金融市场:民锋智能分析引领精准投资
  • Java:多态的调用
  • 使用 Spring Security 和 JWT 实现安全认证机制
  • MySQL记录锁、间隙锁、临键锁(Next-Key Locks)详解
  • PostgreSQL (八) 创建分区