androidQ(10.0) 读取蓝牙设备当前电量并显示

效果图

华为手机顶部状态栏

UCMBHf.png

我们客制化后最终效果

UCMJ4e.png

实现步骤

1、获取蓝牙设备连接成功后的电量值

2、跟踪蓝牙图标显示流程

3、制作蓝牙带电量图标

4、获取电量后显示对应电量值图标

文件修改清单

 vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/ic_bluetooth_connected_super.xml                   
 vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/stat_sys_data_bluetooth_connected_battery_0.xml  
 vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/stat_sys_data_bluetooth_connected_battery_1.xml   
 vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/stat_sys_data_bluetooth_connected_battery_2.xml   
 vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/stat_sys_data_bluetooth_connected_battery_3.xml  
 vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/stat_sys_data_bluetooth_connected_battery_4.xml   
 vendor/mediatek/proprietary/packages/apps/SystemUI/res/drawable/stat_sys_data_bluetooth_connected_battery_5.xml   
 vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java     

除了 PhoneStatusBarPolicy.java 之外其余都是新增蓝牙图标相关资源文件,资源文件不再贴出,可以去这里下载

资源文件选用 xml path 绘制,好处就是能跟随系统状态栏切换背景色,如果采用 png 图片将需要处理监听状态栏底色改变

读取已连接蓝牙设备电量值,在网上搜索后找到了一个工具类,简单试了下发现可用,通过反射调用 BluetoothDevice 的

getBatteryLevel 方法获取电量值

private  int getBluetoothDeviceBattery(){
        int battery = -1;
        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
        Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;
        try {
            Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
            method.setAccessible(true);
            int state = (int) method.invoke(btAdapter, (Object[]) null);

            if (state == BluetoothAdapter.STATE_CONNECTED) {
                Set<BluetoothDevice> devices = btAdapter.getBondedDevices();
                for (BluetoothDevice device : devices) {
                    Method batteryMethod = BluetoothDevice.class.getDeclaredMethod("getBatteryLevel", (Class[]) null);
                    batteryMethod.setAccessible(true);
                    Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
                    isConnectedMethod.setAccessible(true);
                    boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                    int level = (int) batteryMethod.invoke(device, (Object[]) null);
                    if (device != null && level > 0 && isConnected) {
                        String deviceName = device .getName();
                        battery = level;
                        android.util.Log.i(TAG, "Connected Bluetooth="+deviceName + "  battery="+level);
                    }
                }
            } else {
                android.util.Log.e(TAG, "No Connected Bluetooth Devices Found");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            return battery;
        }
    }

电量值为 -1 说明蓝牙设备不支持读取电量

其实后来通过跟踪系统蓝牙连接界面显示电量值逻辑,最终找到的也是调用此方法获取电量

frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth\CachedBluetoothDevice.java

 /**
     * Return summary that describes connection state of this device. Summary depends on:
     * 1. Whether device has battery info
     * 2. Whether device is in active usage(or in phone call)
     *
     * @param shortSummary {@code true} if need to return short version summary
     */
    public String getConnectionSummary(boolean shortSummary) {
        boolean profileConnected = false;    // Updated as long as BluetoothProfile is connected
        boolean a2dpConnected = true;        // A2DP is connected
        boolean hfpConnected = true;         // HFP is connected
        boolean hearingAidConnected = true;  // Hearing Aid is connected
        int leftBattery = -1;
        int rightBattery = -1;

		.....

		 String batteryLevelPercentageString = null;
        // Android framework should only set mBatteryLevel to valid range [0-100] or
        // BluetoothDevice.BATTERY_LEVEL_UNKNOWN, any other value should be a framework bug.
        // Thus assume here that if value is not BluetoothDevice.BATTERY_LEVEL_UNKNOWN, it must
        // be valid
        final int batteryLevel = getBatteryLevel();
        if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
            // TODO: name com.android.settingslib.bluetooth.Utils something different
            batteryLevelPercentageString =
                    com.android.settingslib.Utils.formatPercentage(batteryLevel);
        }

        int stringRes = R.string.bluetooth_pairing;
        //when profile is connected, information would be available
        if (profileConnected) {
            // Update Meta data for connected device
            if (BluetoothUtils.getBooleanMetaData(
                    mDevice, BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)) {
                leftBattery = BluetoothUtils.getIntMetaData(mDevice,
                        BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY);
                rightBattery = BluetoothUtils.getIntMetaData(mDevice,
                        BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY);
            }
		......
}


 /**
     * Get battery level from remote device
     * @return battery level in percentage [0-100], or {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN}
     */
    public int getBatteryLevel() {
	//android.bluetooth.BluetoothDevice  mDevice;
        return mDevice.getBatteryLevel();
    }

通过跟踪发现控制蓝牙图标显示代码在 PhoneStatusBarPolicy.java 中,只有当蓝牙设备连接成功后蓝牙图标才会显示,

默认用的资源文件为 stat_sys_data_bluetooth_connected.xml,我们就可以在这块做调整,当蓝牙设备连接成功后读取电量值,

根据电量值获取对应电池格数资源文件就ok了。

vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java

 @Override
    public void onBluetoothStateChange(boolean enabled) {
        updateBluetooth();
    }

    private final void updateBluetooth() {
        //int iconId = R.drawable.stat_sys_data_bluetooth_connected;
        int iconId = R.drawable.ic_bluetooth_connected_super;//cczheng change
        String contentDescription =
                mContext.getString(R.string.accessibility_quick_settings_bluetooth_on);
        boolean bluetoothVisible = false;
        if (mBluetooth != null) {
            if (mBluetooth.isBluetoothConnected()) {
                contentDescription = mContext.getString(R.string.accessibility_bluetooth_connected);
                bluetoothVisible = mBluetooth.isBluetoothEnabled();
            }
        }
        //20200602 cczheng add
        if (bluetoothVisible) {
            int battery = getBluetoothDeviceBattery();
            if (battery > 0) {
                iconId = getBatteryLevelIconId(battery);
            }
        }//E

        mIconController.setIcon(mSlotBluetooth, iconId, contentDescription);
        mIconController.setIconVisibility(mSlotBluetooth, bluetoothVisible);
    }

    //20200602 cczheng add for show bt headset battery S
    private int getBatteryLevelIconId(int battery){
        int iconId = 0;
        if (battery <= 10) {
            iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_0;
        }else if (battery <= 20) {
            iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_1;
        }else if (battery <= 40) {
            iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_2;
        }else if (battery <= 60) {
            iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_3;
        }else if (battery <= 80) {
            iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_4;
        }else if (battery <= 100) {
            iconId = R.drawable.stat_sys_data_bluetooth_connected_battery_5;
        }
        Log.e(TAG, "iconId="+iconId);
        return iconId;
    }

    private  int getBluetoothDeviceBattery(){
        int battery = -1;
        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
        Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;
        try {
            Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
            method.setAccessible(true);
            int state = (int) method.invoke(btAdapter, (Object[]) null);

            if (state == BluetoothAdapter.STATE_CONNECTED) {
                Set<BluetoothDevice> devices = btAdapter.getBondedDevices();
                for (BluetoothDevice device : devices) {
                    Method batteryMethod = BluetoothDevice.class.getDeclaredMethod("getBatteryLevel", (Class[]) null);
                    batteryMethod.setAccessible(true);
                    Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
                    isConnectedMethod.setAccessible(true);
                    boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
                    int level = (int) batteryMethod.invoke(device, (Object[]) null);
                    if (device != null && level > 0 && isConnected) {
                        String deviceName = device .getName();
                        battery = level;
                        android.util.Log.i(TAG, "Connected Bluetooth="+deviceName + "  battery="+level);
                    }
                }
            } else {
                android.util.Log.e(TAG, "No Connected Bluetooth Devices Found");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            return battery;
        }
    }
    //20200602 cczheng add for show bt headset battery E

    private final void updateTTY() {
        TelecomManager telecomManager =
                (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
        if (telecomManager == null) {
            updateTTY(TelecomManager.TTY_MODE_OFF);
        } else {
            updateTTY(telecomManager.getCurrentTtyMode());
        }
    }

参考文章

Android 10 获取已连接的蓝牙设备的当前电量

Android7.0 获取蓝牙设备电量

猜你喜欢

转载自blog.csdn.net/u012932409/article/details/107156645
今日推荐