Harmony Ble蓝牙App(三)特性和属性

news2024/9/25 7:25:35

Ble蓝牙App(三)特性使用

  • 前言
  • 正文
    • 一、获取属性列表
    • 二、属性提供者
    • 三、获取特性名称
    • 四、特性提供者
    • 五、加载特性
    • 六、源码

前言

  在上一篇中我们完成了连接和发现服务两个动作,那么再发现服务之后要做什么呢?发现服务只是让你知道设备有什么服务,可以做什么事情。

在这里插入图片描述

正文

  本篇要做的是显示服务下的特性,首先我们了解一下特性的基本知识。在蓝牙低功耗(BLE)中,特性(Characteristic)是蓝牙设备提供的一种数据单元,用于描述设备的某个属性或功能。特性包含了一系列的属性和值,可以用于读取、写入和通知数据。

BLE特性相关的关键概念和说明:

  1. UUID(Universally Unique Identifier):每个特性都会有一个唯一的UUID,用于标识该特性。
  2. 值(Value):特性包含一个值,可以是字节数组、字符串或其他数据类型。该值代表特性的当前状态或数据内容。
  3. 属性(Properties):特性具有一组属性,包括读、写、通知等。属性决定了可以对特性进行哪些操作。
  4. 读(Read):允许外部设备从特性中读取当前的值。
  5. 写(Write):允许外部设备向特性写入一个新的值。
  6. 通知(Notify):当特性的值发生变化时,可以通过通知方式将新的值发送给订阅该特性的外部设备。
  7. 描述符(Descriptor):特性可以附带一个或多个描述符,用于提供关于特性的额外信息或配置。

  使用BLE特性,可以实现各种功能和数据交互,例如传感器数据的读取、设备状态的监控、远程控制等。特性的读写和通知操作可以通过与蓝牙设备的交互来实现。需要注意的是,BLE特性的操作和功能是由设备的厂商定义的,并在设备的GATT(Generic Attribute Profile)配置文件中进行描述。

  首先理清一下思路,我们现在知道服务下面有特性,特性下面有一些属性值,其中属性(Properties)尤为重要,因为它决定了你的特性可以进行那些操作。用一个图来说明服务,特性,属性之间的关系。

在这里插入图片描述

一、获取属性列表

下面我们先获取最下面的属性,这是一个列表,属性值的处理有一些不同,首先我们在BleUtils中增加一个函数,代码如下所示:

	/**
     * 获取属性
     */
    public static List<String> getProperties(int property) {
        List<String> properties = new ArrayList<>();
        for (int i = 0; i < 8; i++) {
            switch (property & (1 << i)) {
                case 0x01:
                    properties.add("Broadcast");
                    break;
                case 0x02:
                    properties.add("Read");
                    break;
                case 0x04:
                    properties.add("Write No Response");
                    break;
                case 0x08:
                    properties.add("Write");
                    break;
                case 0x10:
                    properties.add("Notify");
                    break;
                case 0x20:
                    properties.add("Indicate");
                    break;
                case 0x40:
                    properties.add("Authenticated Signed Writes");
                    break;
                case 0x80:
                    properties.add("Extended Properties");
                    break;
            }
        }
        return properties;
    }

  这里是通过位运算进行计算属性的值,首先是循环遍历,先左移再按位与,得到最终的值,根据值得到属性描述,这些描述就是具体的功能操作。会返回一个属性列表,有了列表我们就可以写一个适配器了。

二、属性提供者

首先我们在layout下创建一个item_property.xml,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Text
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:id="$+id:tx_property"
    ohos:height="match_content"
    ohos:width="match_content"
    ohos:end_margin="8vp"
    ohos:text="property"
    ohos:text_color="$color:blue"
    ohos:text_size="14fp"/>

  因为是String类型,所以我们就直接用一个Text显示即可,下面我们写提供者,在provider包下新建一个PropertyProvider类,代码如下所示:

public class PropertyProvider extends BaseItemProvider {

    private final List<String> propertyList;
    private final AbilitySlice slice;

    public PropertyProvider(List<String> list, AbilitySlice slice) {
        this.propertyList = list;
        this.slice = slice;
    }

    @Override
    public int getCount() {
        return propertyList == null ? 0 : propertyList.size();
    }

    @Override
    public Object getItem(int position) {
        if (propertyList != null && position >= 0 && position < propertyList.size()) {
            return propertyList.get(position);
        }
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
        final Component cpt;
        ServiceHolder holder;

        if (component == null) {
            cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_item_property, null, false);
            holder = new ServiceHolder(cpt);
            //将获取到的子组件信息绑定到列表项的实例中
            cpt.setTag(holder);
        } else {
            cpt = component;
            // 从缓存中获取到列表项实例后,直接使用绑定的子组件信息进行数据填充。
            holder = (ServiceHolder) cpt.getTag();
        }

        holder.txProperty.setText(propertyList.get(position));
        return cpt;
    }

    /**
     * 用于保存列表项的子组件信息
     */
    public static class ServiceHolder {
        Text txProperty;
        public ServiceHolder(Component component) {
            txProperty = (Text) component.findComponentById(ResourceTable.Id_tx_property);
        }
    }
}

这里进行了属性的点击监听,我们可以回调到特性适配器中去处理,下面我们要处理的就是特性了。

三、获取特性名称

  首先是特性名称,同样是根据UUID,同样是那个PDF文档,在BleUtils中增加一个getCharacteristicsName()函数,代码有点多,如下所示:

    /**
     * 获取特性名称
     * @param uuid UUID
     */
    public static String getCharacteristicsName(UUID uuid) {
        String targetUuid = getShortUUID(uuid);
        switch (targetUuid) {
            case "0x2A00":
                return "Device Name";
            case "0x2A01":
                return "Appearance";
            case "0x2A02":
                return "Peripheral Privacy Flag";
            case "0x2A03":
                return "Reconnection Address";
            case "0x2A04":
                return "Peripheral Preferred Connection Parameters";
            case "0x2A05":
                return "Service Changed";
            case "0x2A06":
                return "Alert Level";
            case "0x2A07":
                return "Tx Power Level";
            case "0x2A08":
                return "Date Time";
            case "0x2A09":
                return "Day of Week";
            case "0x2A0A":
                return "Day Date Time";
            case "0x2A0C":
                return "Exact Time 256";
            case "0x2A0D":
                return "DST Offset";
            case "0x2A0E":
                return "Time Zone";
            case "0x2A0F":
                return "Local Time Information";
            case "0x2A11":
                return "Time with DST";
            case "0x2A12":
                return "Time Accuracy";
            case "0x2A13":
                return "Time Source";
            case "0x2A14":
                return "Reference Time Information";
            case "0x2A16":
                return "Time Update Control Point";
            case "0x2A17":
                return "Time Update State";
            case "0x2A18":
                return "Glucose Measurement";
            case "0x2A19":
                return "Battery Level";
            case "0x2A1C":
                return "Temperature Measurement";
            case "0x2A1D":
                return "Temperature Type";
            case "0x2A1E":
                return "Intermediate Temperature";
            case "0x2A21":
                return "Measurement Interval";
            case "0x2A22":
                return "Boot Keyboard Input Report";
            case "0x2A23":
                return "System ID";
            case "0x2A24":
                return "Model Number String";
            case "0x2A25":
                return "Serial Number String";
            case "0x2A26":
                return "Firmware Revision String";
            case "0x2A27":
                return "Hardware Revision String";
            case "0x2A28":
                return "Software Revision String";
            case "0x2A29":
                return "Manufacturer Name String";
            case "0x2A2A":
                return "IEEE 11073-20601 Regulatory Certification Data List";
            case "0x2A2B":
                return "Current Time";
            case "0x2A2C":
                return "Magnetic Declination";
            case "0x2A31":
                return "Scan Refresh";
            case "0x2A32":
                return "Boot Keyboard Output Report";
            case "0x2A33":
                return "Boot Mouse Input Report";
            case "0x2A34":
                return "Glucose Measurement Context";
            case "0x2A35":
                return "Blood Pressure Measurement";
            case "0x2A36":
                return "Intermediate Cuff Pressure";
            case "0x2A37":
                return "Heart Rate Measurement";
            case "0x2A38":
                return "Body Sensor Location";
            case "0x2A39":
                return "Heart Rate Control Point";
            case "0x2A3F":
                return "Alert Status";
            case "0x2A40":
                return "Ringer Control Point";
            case "0x2A41":
                return "Ringer Setting";
            case "0x2A42":
                return "Alert Category ID Bit Mask";
            case "0x2A43":
                return "Alert Category ID";
            case "0x2A44":
                return "Alert Notification Control Point";
            case "0x2A45":
                return "Unread Alert Status";
            case "0x2A46":
                return "New Alert";
            case "0x2A47":
                return "Supported New Alert Category";
            case "0x2A48":
                return "Supported Unread Alert Category";
            case "0x2A49":
                return "Blood Pressure Feature";
            case "0x2A4A":
                return "HID Information";
            case "0x2A4B":
                return "Report Map";
            case "0x2A4C":
                return "HID Control Point";
            case "0x2A4D":
                return "Report";
            case "0x2A4E":
                return "Protocol Mode";
            case "0x2A4F":
                return "Scan Interval Window";
            case "0x2A50":
                return "PnP ID";
            case "0x2A51":
                return "Glucose Feature";
            case "0x2A52":
                return "Record Access Control Point";
            case "0x2A53":
                return "RSC Measurement";
            case "0x2A54":
                return "RSC Feature";
            case "0x2A55":
                return "SC Control Point";
            case "0x2A5A":
                return "Aggregate";
            case "0x2A5B":
                return "CSC Measurement";
            case "0x2A5C":
                return "CSC Feature";
            case "0x2A5D":
                return "Sensor Location";
            case "0x2A5E":
                return "PLX Spot-Check Measurement";
            case "0x2A5F":
                return "PLX Continuous Measurement";
            case "0x2A60":
                return "PLX Features";
            case "0x2A63":
                return "Cycling Power Measurement";
            case "0x2A64":
                return "Cycling Power Vector";
            case "0x2A65":
                return "Cycling Power Feature";
            case "0x2A66":
                return "Cycling Power Control Point";
            case "0x2A67":
                return "Location and Speed";
            case "0x2A68":
                return "Navigation";
            case "0x2A69":
                return "Position Quality";
            case "0x2A6A":
                return "LN Feature";
            case "0x2A6B":
                return "LN Control Point";
            case "0x2A6C":
                return "Elevation";
            case "0x2A6D":
                return "Pressure";
            case "0x2A6E":
                return "Temperature";
            case "0x2A6F":
                return "Humidity";
            case "0x2A70":
                return "True Wind Speed";
            case "0x2A71":
                return "True Wind Direction";
            case "0x2A72":
                return "Apparent Wind Speed";
            case "0x2A73":
                return "Apparent Wind Direction";
            case "0x2A74":
                return "Gust Factor";
            case "0x2A75":
                return "Pollen Concentration";
            case "0x2A76":
                return "UV Index";
            case "0x2A77":
                return "Irradiance";
            case "0x2A78":
                return "Rainfall";
            case "0x2A79":
                return "Wind Chill";
            case "0x2A7A":
                return "Heat Index";
            case "0x2A7B":
                return "Dew Point";
            case "0x2A7D":
                return "Descriptor Value Changed";
            case "0x2A7E":
                return "Aerobic Heart Rate Lower Limit";
            case "0x2A7F":
                return "Aerobic Threshold";
            case "0x2A80":
                return "Age";
            case "0x2A81":
                return "Anaerobic Heart Rate Lower Limit";
            case "0x2A82":
                return "Anaerobic Heart Rate Upper Limit";
            case "0x2A83":
                return "Anaerobic Threshold";
            case "0x2A84":
                return "Aerobic Heart Rate Upper Limit";
            case "0x2A85":
                return "Date of Birth";
            case "0x2A86":
                return "Date of Threshold Assessment";
            case "0x2A87":
                return "Email Address";
            case "0x2A88":
                return "Fat Burn Heart Rate Lower Limit";
            case "0x2A89":
                return "Fat Burn Heart Rate Upper Limit";
            case "0x2A8A":
                return "First Name";
            case "0x2A8B":
                return "Five Zone Heart Rate Limits";
            case "0x2A8C":
                return "Gender";
            case "0x2A8D":
                return "Heart Rate Max";
            case "0x2A8E":
                return "Height";
            case "0x2A8F":
                return "Hip Circumference";
            case "0x2A90":
                return "Last Name";
            case "0x2A91":
                return "Maximum Recommended Heart Rate";
            case "0x2A92":
                return "Resting Heart Rate";
            case "0x2A93":
                return "Sport Type for Aerobic and Anaerobic Thresholds";
            case "0x2A94":
                return "Three Zone Heart Rate Limits";
            case "0x2A95":
                return "Two Zone Heart Rate Limits";
            case "0x2A96":
                return "VO2 Max";
            case "0x2A97":
                return "Waist Circumference";
            case "0x2A98":
                return "Weight";
            case "0x2A99":
                return "Database Change Increment";
            case "0x2A9A":
                return "User Index";
            case "0x2A9B":
                return "Body Composition Feature";
            case "0x2A9C":
                return "Body Composition Measurement";
            case "0x2A9D":
                return "Weight Measurement";
            case "0x2A9E":
                return "Weight Scale Feature";
            case "0x2A9F":
                return "User Control Point";
            case "0x2AA0":
                return "Magnetic Flux Density - 2D";
            case "0x2AA1":
                return "Magnetic Flux Density - 3D";
            case "0x2AA2":
                return "Language";
            case "0x2AA3":
                return "Barometric Pressure Trend";
            case "0x2AA4":
                return "Bond Management Control Point";
            case "0x2AA5":
                return "Bond Management Feature";
            case "0x2AA6":
                return "Central Address Resolution";
            case "0x2AA7":
                return "CGM Measurement";
            case "0x2AA8":
                return "CGM Feature";
            case "0x2AA9":
                return "CGM Status";
            case "0x2AAA":
                return "CGM Session Start Time";
            case "0x2AAB":
                return "CGM Session Run Time";
            case "0x2AAC":
                return "CGM Specific Ops Control Point";
            case "0x2AAD":
                return "Indoor Positioning Configuration";
            case "0x2AAE":
                return "Latitude";
            case "0x2AAF":
                return "Longitude";
            case "0x2AB0":
                return "Local North Coordinate";
            case "0x2AB1":
                return "Local East Coordinate";
            case "0x2AB2":
                return "Floor Number";
            case "0x2AB3":
                return "Altitude";
            case "0x2AB4":
                return "Uncertainty";
            case "0x2AB5":
                return "Location Name";
            case "0x2AB6":
                return "URI";
            case "0x2AB7":
                return "HTTP Headers";
            case "0x2AB8":
                return "HTTP Status Code";
            case "0x2AB9":
                return "HTTP Entity Body";
            case "0x2ABA":
                return "HTTP Control Point";
            case "0x2ABB":
                return "HTTPS Security";
            case "0x2ABC":
                return "TDS Control Point";
            case "0x2ABD":
                return "OTS Feature";
            case "0x2ABE":
                return "Object Name";
            case "0x2ABF":
                return "Object Type";
            case "0x2AC0":
                return "Object Size";
            case "0x2AC1":
                return "Object First -Created";
            case "0x2AC2":
                return "Object Last - Modified";
            case "0x2AC3":
                return "Object ID";
            case "0x2AC4":
                return "Object Properties";
            case "0x2AC5":
                return "Object Action Control Point";
            case "0x2AC6":
                return "Object List Control Point";
            case "0x2AC7":
                return "Object List Filter";
            case "0x2AC8":
                return "Object Changed";
            case "0x2AC9":
                return "Resolvable Private Address Only";
            case "0x2ACC":
                return "Fitness Machine Feature";
            case "0x2ACD":
                return "Treadmill Data";
            case "0x2ACE":
                return "Cross Trainer Data";
            case "0x2ACF":
                return "Step Climber Data";
            case "0x2AD0":
                return "Stair Climber Data";
            case "0x2AD1":
                return "Rower Data";
            case "0x2AD2":
                return "Indoor Bike Data";
            case "0x2AD3":
                return "Training Status";
            case "0x2AD4":
                return "Supported Speed Range";
            case "0x2AD5":
                return "Supported Inclination Range";
            case "0x2AD6":
                return "Supported Resistance Level Range";
            case "0x2AD7":
                return "Supported Heart Rate Range";
            case "0x2AD8":
                return "Supported Power Range";
            case "0x2AD9":
                return "Fitness Machine Control Point";
            case "0x2ADA":
                return "Fitness Machine Status";
            case "0x2ADB":
                return "Mesh Provisioning Data In";
            case "0x2ADC":
                return "Mesh Provisioning Data Out";
            case "0x2ADD":
                return "Mesh Proxy Data In";
            case "0x2ADE":
                return "Mesh Proxy Data Out";
            case "0x2AE0":
                return "Average Current";
            case "0x2AE1":
                return "Average Voltage";
            case "0x2AE2":
                return "Boolean";
            case "0x2AE3":
                return "Chromatic Distance from Planckian";
            case "0x2AE4":
                return "Chromaticity Coordinates";
            case "0x2AE5":
                return "Chromaticity in CCT and Duv Values";
            case "0x2AE6":
                return "Chromaticity Tolerance";
            case "0x2AE7":
                return "CIE 13.3 - 1995 Color Rendering Index";
            case "0x2AE8":
                return "Coefficient";
            case "0x2AE9":
                return "Correlated Color Temperature";
            case "0x2AEA":
                return "Count 16";
            case "0x2AEB":
                return "Count 24";
            case "0x2AEC":
                return "Country Code";
            case "0x2AED":
                return "Date UTC";
            case "0x2AEE":
                return "Electric Current";
            case "0x2AEF":
                return "Electric Current Range";
            case "0x2AF0":
                return "Electric Current Specification";
            case "0x2AF1":
                return "Electric Current Statistics";
            case "0x2AF2":
                return "Energy";
            case "0x2AF3":
                return "Energy in a Period of Day";
            case "0x2AF4":
                return "Event Statistics";
            case "0x2AF5":
                return "Fixed String 16";
            case "0x2AF6":
                return "Fixed String 24";
            case "0x2AF7":
                return "Fixed String 36";
            case "0x2AF8":
                return "Fixed String 8";
            case "0x2AF9":
                return "Generic Level";
            case "0x2AFA":
                return "Global Trade Item Number";
            case "0x2AFB":
                return "Illuminance";
            case "0x2AFC":
                return "Luminous Efficacy";
            case "0x2AFD":
                return "Luminous Energy";
            case "0x2AFE":
                return "Luminous Exposure";
            case "0x2AFF":
                return "Luminous Flux";
            case "0x2B00":
                return "Luminous Flux Range";
            case "0x2B01":
                return "Luminous Intensity";
            case "0x2B02":
                return "Mass Flow";
            case "0x2B03":
                return "Perceived Lightness";
            case "0x2B04":
                return "Percentage 8";
            case "0x2B05":
                return "Power";
            case "0x2B06":
                return "Power Specification";
            case "0x2B07":
                return "Relative Runtime in a Current Range";
            case "0x2B08":
                return "Relative Runtime in a Generic Level Range";
            case "0x2B09":
                return "Relative Value in a Voltage Range";
            case "0x2B0A":
                return "Relative Value in an Illuminance Range";
            case "0x2B0B":
                return "Relative Value in a Period of Day";
            case "0x2B0C":
                return "Relative Value in a Temperature Range";
            case "0x2B0D":
                return "Temperature 8";
            case "0x2B0E":
                return "Temperature 8 in a Period of Day";
            case "0x2B0F":
                return "Temperature 8 Statistics";
            case "0x2B10":
                return "Temperature Range";
            case "0x2B11":
                return "Temperature Statistics";
            case "0x2B12":
                return "Time Decihour 8";
            case "0x2B13":
                return "Time Exponential 8";
            case "0x2B14":
                return "Time Hour 24";
            case "0x2B15":
                return "Time Millisecond 24";
            case "0x2B16":
                return "Time Second 16";
            case "0x2B17":
                return "Time Second 8";
            case "0x2B18":
                return "Voltage";
            case "0x2B19":
                return "Voltage Specification";
            case "0x2B1A":
                return "Voltage Statistics";
            case "0x2B1B":
                return "Volume Flow";
            case "0x2B1C":
                return "Chromaticity Coordinate";
            case "0x2B1D":
                return "RC Feature";
            case "0x2B1E":
                return "RC Settings";
            case "0x2B1F":
                return "Reconnection Configuration Control Point";
            case "0x2B20":
                return "IDD Status Changed";
            case "0x2B21":
                return "IDD Status";
            case "0x2B22":
                return "IDD Annunciation Status";
            case "0x2B23":
                return "IDD Features";
            case "0x2B24":
                return "IDD Status Reader Control Point";
            case "0x2B25":
                return "IDD Command Control Point";
            case "0x2B26":
                return "IDD Command Data";
            case "0x2B27":
                return "IDD Record Access Control Point";
            case "0x2B28":
                return "IDD History Data";
            case "0x2B29":
                return "Client Supported Features";
            case "0x2B2A":
                return "Database Hash";
            case "0x2B2B":
                return "BSS Control Point";
            case "0x2B2C":
                return "BSS Response";
            case "0x2B2D":
                return "Emergency ID";
            case "0x2B2E":
                return "Emergency Text";
            case "0x2B2F":
                return "ACS Status";
            case "0x2B30":
                return "ACS Data In";
            case "0x2B31":
                return "ACS Data Out Notify";
            case "0x2B32":
                return "ACS Data Out Indicate";
            case "0x2B33":
                return "ACS Control Point";
            case "0x2B34":
                return "Enhanced Blood Pressure Measurement";
            case "0x2B35":
                return "Enhanced Intermediate Cuff Pressure";
            case "0x2B36":
                return "Blood Pressure Record";
            case "0x2B37":
                return "Registered User";
            case "0x2B38":
                return "BR - EDR Handover Data";
            case "0x2B39":
                return "Bluetooth SIG Data";
            case "0x2B3A":
                return "Server Supported Features";
            case "0x2B3B":
                return "Physical Activity Monitor Features";
            case "0x2B3C":
                return "General Activity Instantaneous Data";
            case "0x2B3D":
                return "General Activity Summary Data";
            case "0x2B3E":
                return "CardioRespiratory Activity Instantaneous Data";
            case "0x2B3F":
                return "CardioRespiratory Activity Summary Data";
            case "0x2B40":
                return "Step Counter Activity Summary Data";
            case "0x2B41":
                return "Sleep Activity Instantaneous Data";
            case "0x2B42":
                return "Sleep Activity Summary Data";
            case "0x2B43":
                return "Physical Activity Monitor Control Point";
            case "0x2B44":
                return "Activity Current Session";
            case "0x2B45":
                return "Physical Activity Session Descriptor";
            case "0x2B46":
                return "Preferred Units";
            case "0x2B47":
                return "High Resolution Height";
            case "0x2B48":
                return "Middle Name";
            case "0x2B49":
                return "Stride Length";
            case "0x2B4A":
                return "Handedness";
            case "0x2B4B":
                return "Device Wearing Position";
            case "0x2B4C":
                return "Four Zone Heart Rate Limits";
            case "0x2B4D":
                return "High Intensity Exercise Threshold";
            case "0x2B4E":
                return "Activity Goal";
            case "0x2B4F":
                return "Sedentary Interval Notification";
            case "0x2B50":
                return "Caloric Intake";
            case "0x2B51":
                return "TMAP Role";
            case "0x2B77":
                return "Audio Input State";
            case "0x2B78":
                return "Gain Settings Attribute";
            case "0x2B79":
                return "Audio Input Type";
            case "0x2B7A":
                return "Audio Input Status";
            case "0x2B7B":
                return "Audio Input Control Point";
            case "0x2B7C":
                return "Audio Input Description";
            case "0x2B7D":
                return "Volume State";
            case "0x2B7E":
                return "Volume Control Point";
            case "0x2B7F":
                return "Volume Flags";
            case "0x2B80":
                return "Volume Offset State";
            case "0x2B81":
                return "Audio Location";
            case "0x2B82":
                return "Volume Offset Control Point";
            case "0x2B83":
                return "Audio Output Description";
            case "0x2B84":
                return "Set Identity Resolving Key";
            case "0x2B85":
                return "Coordinated Set Size";
            case "0x2B86":
                return "Set Member Lock";
            case "0x2B87":
                return "Set Member Rank";
            case "0x2B88":
                return "Encrypted Data Key Material";
            case "0x2B89":
                return "Apparent Energy 32";
            case "0x2B8A":
                return "Apparent Power";
            case "0x2B8B":
                return "Live Health Observations";
            case "0x2B8C":
                return "CO \\{} text-subscript { 2 } Concentration";
            case "0x2B8D":
                return "Cosine of the Angle";
            case "0x2B8E":
                return "Device Time Feature";
            case "0x2B8F":
                return "Device Time Parameters";
            case "0x2B90":
                return "Device Time";
            case "0x2B91":
                return "Device Time Control Point";
            case "0x2B92":
                return "Time Change Log Data";
            case "0x2B93":
                return "Media Player Name";
            case "0x2B94":
                return "Media Player Icon Object ID";
            case "0x2B95":
                return "Media Player Icon URL";
            case "0x2B96":
                return "Track Changed";
            case "0x2B97":
                return "Track Title";
            case "0x2B98":
                return "Track Duration";
            case "0x2B99":
                return "Track Position";
            case "0x2B9A":
                return "Playback Speed";
            case "0x2B9B":
                return "Seeking Speed";
            case "0x2B9C":
                return "Current Track Segments Object ID";
            case "0x2B9D":
                return "Current Track Object ID";
            case "0x2B9E":
                return "Next Track Object ID";
            case "0x2B9F":
                return "Parent Group Object ID";
            case "0x2BA0":
                return "Current Group Object ID";
            case "0x2BA1":
                return "Playing Order";
            case "0x2BA2":
                return "Playing Orders Supported";
            case "0x2BA3":
                return "Media State";
            case "0x2BA4":
                return "Media Control Point";
            case "0x2BA5":
                return "Media Control Point Opcodes Supported";
            case "0x2BA6":
                return "Search Results Object ID";
            case "0x2BA7":
                return "Search Control Point";
            case "0x2BA8":
                return "Energy 32";
            case "0x2BA9":
                return "Media Player Icon Object Type";
            case "0x2BAA":
                return "Track Segments Object Type";
            case "0x2BAB":
                return "Track Object Type";
            case "0x2BAC":
                return "Group Object Type";
            case "0x2BAD":
                return "Constant Tone Extension Enable";
            case "0x2BAE":
                return "Advertising Constant Tone Extension Minimum Length";
            case "0x2BAF":
                return "Advertising Constant Tone Extension Minimum Transmit Count";
            case "0x2BB0":
                return "Advertising Constant Tone Extension Transmit Duration";
            case "0x2BB1":
                return "Advertising Constant Tone Extension Interval";
            case "0x2BB2":
                return "Advertising Constant Tone Extension PHY";
            case "0x2BB3":
                return "Bearer Provider Name";
            case "0x2BB4":
                return "Bearer UCI";
            case "0x2BB5":
                return "Bearer Technology";
            case "0x2BB6":
                return "Bearer URI Schemes Supported List";
            case "0x2BB7":
                return "Bearer Signal Strength";
            case "0x2BB8":
                return "Bearer Signal Strength Reporting Interval";
            case "0x2BB9":
                return "Bearer List Current Calls";
            case "0x2BBA":
                return "Content Control ID";
            case "0x2BBB":
                return "Status Flags";
            case "0x2BBC":
                return "Incoming Call Target Bearer URI";
            case "0x2BBD":
                return "Call State";
            case "0x2BBE":
                return "Call Control Point";
            case "0x2BBF":
                return "Call Control Point Optional Opcodes";
            case "0x2BC0":
                return "Termination Reason";
            case "0x2BC1":
                return "Incoming Call";
            case "0x2BC2":
                return "Call Friendly Name";
            case "0x2BC3":
                return "Mute";
            case "0x2BC4":
                return "Sink ASE";
            case "0x2BC5":
                return "Source ASE";
            case "0x2BC6":
                return "ASE Control Point";
            case "0x2BC7":
                return "Broadcast Audio Scan Control Point";
            case "0x2BC8":
                return "Broadcast Receive State";
            case "0x2BC9":
                return "Sink PAC";
            case "0x2BCA":
                return "Sink Audio Locations";
            case "0x2BCB":
                return "Source PAC";
            case "0x2BCC":
                return "Source Audio Locations";
            case "0x2BCD":
                return "Available Audio Contexts";
            case "0x2BCE":
                return "Supported Audio Contexts";
            case "0x2BCF":
                return "Ammonia Concentration";
            case "0x2BD0":
                return "Carbon Monoxide Concentration";
            case "0x2BD1":
                return "Methane Concentration";
            case "0x2BD2":
                return "Nitrogen Dioxide Concentration";
            case "0x2BD3":
                return "Non -Methane Volatile Organic Compounds Concentration";
            case "0x2BD4":
                return "Ozone Concentration";
            case "0x2BD5":
                return "Particulate Matter - PM1 Concentration";
            case "0x2BD6":
                return "Particulate Matter - PM2.5 Concentration";
            case "0x2BD7":
                return "Particulate Matter - PM10 Concentration";
            case "0x2BD8":
                return "Sulfur Dioxide Concentration";
            case "0x2BD9":
                return "Sulfur Hexafluoride Concentration";
            case "0x2BDA":
                return "Hearing Aid Features";
            case "0x2BDB":
                return "Hearing Aid Preset Control Point";
            case "0x2BDC":
                return "Active Preset Index";
            case "0x2BDD":
                return "Stored Health Observations";
            case "0x2BDE":
                return "Fixed String 64";
            case "0x2BDF":
                return "High Temperature";
            case "0x2BE0":
                return "High Voltage";
            case "0x2BE1":
                return "Light Distribution";
            case "0x2BE2":
                return "Light Output";
            case "0x2BE3":
                return "Light Source Type";
            case "0x2BE4":
                return "Noise";
            case "0x2BE5":
                return "Relative Runtime in a Correlated Color Temperature Range";
            case "0x2BE6":
                return "Time Second 32";
            case "0x2BE7":
                return "VOC Concentration";
            case "0x2BE8":
                return "Voltage Frequency";
            case "0x2BE9":
                return "Battery Critical Status";
            case "0x2BEA":
                return "Battery Health Status";
            case "0x2BEB":
                return "Battery Health Information";
            case "0x2BEC":
                return "Battery Information";
            case "0x2BED":
                return "Battery Level Status";
            case "0x2BEE":
                return "Battery Time Status";
            case "0x2BEF":
                return "Estimated Service Date";
            case "0x2BF0":
                return "Battery Energy Status";
            case "0x2BF1":
                return "Observation Schedule Changed";
            case "0x2BF2":
                return "Current Elapsed Time";
            case "0x2BF3":
                return "Health Sensor Features";
            case "0x2BF4":
                return "GHS Control Point";
            case "0x2BF5":
                return "LE GATT Security Levels";
            case "0x2BF6":
                return "ESL Address";
            case "0x2BF7":
                return "AP Sync Key Material";
            case "0x2BF8":
                return "ESL Response Key Material";
            case "0x2BF9":
                return "ESL Current Absolute Time";
            case "0x2BFA":
                return "ESL Display Information";
            case "0x2BFB":
                return "ESL Image Information";
            case "0x2BFC":
                return "ESL Sensor Information";
            case "0x2BFD":
                return "ESL LED Information";
            case "0x2BFE":
                return "ESL Control Point";
            case "0x2BFF":
                return "UDI for Medical Devices";
            default:
                return "Unknown Characteristics";
        }
    }

  同修改一下原有的getServiceUUID()getShortUUID(),只改名字而已,之前命名有点不太严谨,记得改一下使用的地方,如下图所示,在ServiceProvider

在这里插入图片描述

四、特性提供者

首先我们在layout下创建一个item_characteristic.xml,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<DependentLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_parent"
    ohos:background_element="#FFFFFF"
    ohos:bottom_margin="2vp"
    ohos:bottom_padding="8vp"
    ohos:end_padding="16vp"
    ohos:start_padding="16vp"
    ohos:top_padding="8vp">

    <Text
        ohos:id="$+id:tx_character_name"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$color:black"
        ohos:text="服务"
        ohos:text_size="16fp"/>

    <Text
        ohos:id="$+id:tx_uuid_title"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:below="$id:tx_character_name"
        ohos:text="UUID:"
        ohos:text_color="$color:gray"
        ohos:text_size="16fp"
        ohos:top_margin="2vp"/>

    <Text
        ohos:id="$+id:tx_uuid"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:background_element="$color:black"
        ohos:below="$id:tx_character_name"
        ohos:end_of="$id:tx_uuid_title"
        ohos:text="UUID"
        ohos:text_size="16fp"
        ohos:top_margin="2vp"/>

    <Text
        ohos:id="$+id:tx_property_title"
        ohos:height="match_content"
        ohos:width="match_content"
        ohos:below="$id:tx_uuid_title"
        ohos:text="Properties:"
        ohos:text_color="$color:gray"
        ohos:text_size="16fp"
        ohos:top_margin="2vp"/>

    <ListContainer
        ohos:id="$+id:lc_property"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:orientation="horizontal"
        ohos:align_bottom="$id:tx_property_title"
        ohos:align_top="$id:tx_property_title"
        ohos:end_of="$id:tx_property_title"/>

</DependentLayout>

  这个布局中唯一说明的一点就是ListContainerorientation="horizontal"属性,这表示列表是横向,默认是纵向的。这里显示特性的名称和UUIID,同时加载属性列表,然后写适配器,因为需要操作属性的缘故,这些写一个接口,在provider包下新建一个OperateCallback接口,代码如下所示:

public interface OperateCallback {

    /**
     * 属性操作
     */
    void onPropertyOperate(GattCharacteristic characteristic, String operateName);
}

  通过这个接口可以知道当前操作的是那个特性和属性名称。下面我们写适配器,在provider包下新建一个CharacteristicProvider类,代码如下所示:

public class CharacteristicProvider extends BaseItemProvider {

    private final List<GattCharacteristic> characteristicList;
    private final AbilitySlice slice;
    private final OperateCallback operateCallback;
    
    public CharacteristicProvider(List<GattCharacteristic> list, AbilitySlice slice, OperateCallback operateCallback) {
        this.characteristicList = list;
        this.slice = slice;
        this.operateCallback = operateCallback;
    }

    @Override
    public int getCount() {
        return characteristicList == null ? 0 : characteristicList.size();
    }

    @Override
    public Object getItem(int position) {
        if (characteristicList != null && position >= 0 && position < characteristicList.size()) {
            return characteristicList.get(position);
        }
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
        final Component cpt;
        ServiceHolder holder;

        GattCharacteristic characteristic = characteristicList.get(position);
        if (component == null) {
            cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_item_characteristic, null, false);
            holder = new ServiceHolder(cpt);
            //将获取到的子组件信息绑定到列表项的实例中
            cpt.setTag(holder);
        } else {
            cpt = component;
            // 从缓存中获取到列表项实例后,直接使用绑定的子组件信息进行数据填充。
            holder = (ServiceHolder) cpt.getTag();
        }

        holder.txCharacterName.setText(BleUtils.getCharacteristicsName(characteristic.getUuid()));
        holder.txUuid.setText(BleUtils.getShortUUID(characteristic.getUuid()));

        List<String> properties = BleUtils.getProperties(characteristic.getProperties());
        //加载属性
        holder.lcProperty.setItemProvider(new PropertyProvider(properties, slice));
        //属性列表点击
        holder.lcProperty.setItemClickedListener((listContainer, component1, propertyPosition, l) -> {
            if (operateCallback != null) {
                //属性操作回调
                operateCallback.onPropertyOperate(characteristic, properties.get(propertyPosition));
            }
        });
        return cpt;
    }

    /**
     * 用于保存列表项的子组件信息
     */
    public static class ServiceHolder {
        Text txCharacterName;
        Text txUuid;
        ListContainer lcProperty;

        public ServiceHolder(Component component) {
            txCharacterName = (Text) component.findComponentById(ResourceTable.Id_tx_character_name);
            txUuid = (Text) component.findComponentById(ResourceTable.Id_tx_uuid);
            lcProperty = (ListContainer) component.findComponentById(ResourceTable.Id_lc_property);
        }
    }
}

在这里我们就可以处理特性的名称和UUID显示,同时加载属性提供者,显示出来。

五、加载特性

  因为特性是在服务下的,所以我们可以在服务适配器中加载特性适配器。首先我们修改一下item_service.xml,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="match_content"
    ohos:width="match_parent"
    ohos:background_element="#FFFFFF"
    ohos:bottom_margin="2vp"
    ohos:orientation="vertical">

    <DependentLayout
        xmlns:ohos="http://schemas.huawei.com/res/ohos"
        ohos:id="$+id:item_service"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:background_element="#FFFFFF"
        ohos:bottom_padding="8vp"
        ohos:end_padding="16vp"
        ohos:start_padding="16vp"
        ohos:top_padding="8vp">

        <Text
            ohos:id="$+id:tx_service_name"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:background_element="$color:black"
            ohos:text="服务"
            ohos:text_size="16fp"/>

        <Text
            ohos:id="$+id:tx_uuid_title"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:below="$id:tx_service_name"
            ohos:text="UUID:"
            ohos:text_color="$color:gray"
            ohos:text_size="16fp"
            ohos:top_margin="2vp"/>

        <Text
            ohos:id="$+id:tx_uuid"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:background_element="$color:black"
            ohos:below="$id:tx_service_name"
            ohos:end_of="$id:tx_uuid_title"
            ohos:text="UUID"
            ohos:text_size="16fp"
            ohos:top_margin="2vp"/>

        <Text
            ohos:id="$+id:tx_service_info"
            ohos:height="match_content"
            ohos:width="match_content"
            ohos:below="$id:tx_uuid_title"
            ohos:text="PRIMARY SERVICE"
            ohos:text_color="$color:gray"
            ohos:text_size="16fp"
            ohos:top_margin="2vp"/>

        <Image
            ohos:id="$+id:iv_state"
            ohos:height="24vp"
            ohos:width="24vp"
            ohos:align_parent_end="true"
            ohos:end_margin="16vp"
            ohos:background_element="$graphic:ic_right_24"
            ohos:vertical_center="true"/>

    </DependentLayout>

    <ListContainer
        ohos:id="$+id:lc_characteristics"
        ohos:height="match_content"
        ohos:width="match_parent"
        ohos:start_padding="16vp"
        ohos:visibility="hide"/>
</DirectionalLayout>

  整体上变化不大,只是加了一个ListContainer,同时增加了一个Image,用于显示当前的服务下的特性列表是否显示,可以通过当前的服务item的方式控制是否显示特性列表,这里用到两个图标,在graphic下创建ic_right_24.xml,代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<vector
    xmlns:ohos="http://schemas.android.com/apk/res/android"
    ohos:height="24vp"
    ohos:tint="#000000"
    ohos:viewportHeight="24"
    ohos:viewportWidth="24"
    ohos:width="24vp">

    <path
        ohos:fillColor="#000000"
        ohos:pathData="M10,17l5,-5 -5,-5v10z"/>
</vector>

还有一个ic_down_24.xml

<?xml version="1.0" encoding="utf-8"?>
<vector
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    ohos:height="24vp"
    ohos:width="24vp"
    ohos:tint="#000000"
    ohos:viewportHeight="24"
    ohos:viewportWidth="24">

    <path
        ohos:fillColor="#000000"
        ohos:pathData="M7,10l5,5 5,-5z"/>
</vector>

下面修改一下ServiceAdapter,代码如下所示:

public class ServiceProvider extends BaseItemProvider {

    private final List<GattService> serviceList;
    private final AbilitySlice slice;

    private OperateCallback operateCallback;

    public void setOperateCallback(OperateCallback operateCallback) {
        this.operateCallback = operateCallback;
    }

    public ServiceProvider(List<GattService> list, AbilitySlice slice) {
        this.serviceList = list;
        this.slice = slice;
    }

    @Override
    public int getCount() {
        return serviceList == null ? 0 : serviceList.size();
    }

    @Override
    public Object getItem(int position) {
        if (serviceList != null && position >= 0 && position < serviceList.size()) {
            return serviceList.get(position);
        }
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
        final Component cpt;
        ServiceHolder holder;

        GattService service = serviceList.get(position);
        if (component == null) {
            cpt = LayoutScatter.getInstance(slice).parse(ResourceTable.Layout_item_service, null, false);
            holder = new ServiceHolder(cpt);
            //将获取到的子组件信息绑定到列表项的实例中
            cpt.setTag(holder);
        } else {
            cpt = component;
            // 从缓存中获取到列表项实例后,直接使用绑定的子组件信息进行数据填充。
            holder = (ServiceHolder) cpt.getTag();
        }

        holder.itemService.setClickedListener(component1 -> {
            boolean isShow = holder.lcCharacteristics.getVisibility() == Component.VISIBLE;
            //显示特性列表
            holder.lcCharacteristics.setVisibility(isShow ? Component.HIDE : Component.VISIBLE);
            //更换图标
            VectorElement vectorElement = new VectorElement(slice.getContext(), isShow ? ResourceTable.Graphic_ic_right_24 : ResourceTable.Graphic_ic_down_24);
            holder.ivState.setBackground(vectorElement);
            //刷新Item高度,这个很重要,不加会造成内容覆盖。
            notifyDataSetItemChanged(position);
        });
        //加载特性 设置属性回调
        holder.lcCharacteristics.setItemProvider(new CharacteristicProvider(service.getCharacteristics(), slice, operateCallback));

        holder.txServiceName.setText(BleUtils.getServiceName(service.getUuid()));
        holder.txUuid.setText(BleUtils.getShortUUID(service.getUuid()));

        return cpt;
    }

    /**
     * 用于保存列表项的子组件信息
     */
    public static class ServiceHolder {
        DependentLayout itemService;
        Text txServiceName;
        Text txUuid;
        Image ivState;
        ListContainer lcCharacteristics;
        public ServiceHolder(Component component) {
            itemService = (DependentLayout) component.findComponentById(ResourceTable.Id_item_service);
            txServiceName = (Text) component.findComponentById(ResourceTable.Id_tx_service_name);
            txUuid = (Text) component.findComponentById(ResourceTable.Id_tx_uuid);
            ivState = (Image) component.findComponentById(ResourceTable.Id_iv_state);
            lcCharacteristics = (ListContainer) component.findComponentById(ResourceTable.Id_lc_characteristics);
        }
    }
}

  和之前的区别就在于构造的时候增加了一个回调,并且在getComponent()方法中就处理了服务Item的点击事件,而不是像之前一样回调到页面中,在服务Item的点击事件中判断是否显示特性列表同时修改图标资源。最后再将接口回调到页面中。

  另外还需要注意一点,那就是Image我在xml中是设置的背景,而不是图片资源,因为在java代码中无法设置矢量图的资源,所以我就改成使用背景资源,需要注意的是背景资源要设置Image具体的大小,否则不会显示,在Java代码中通过VectorElement来加载矢量图资源,然后设置背景。同时notifyDataSetItemChanged(position)这样代码也很重要,因为我们的服务Item实际上有两部分内容,服务本身内容和特性列表内容,默认情况下显示服务内容,当点击服务Item时显示特性列表内容,此时如果你按照Android的习惯去搞,你就会发现,Item展开的内容会被其他Item遮挡,所以我们需要加上这样一行代码,让Item进行刷新,这样就不会被其他Item遮挡了。

  最后我们在MainAbilitySlice中添加serviceProvider.setOperateCallback(this);,然后再实现接口

在这里插入图片描述

重写里面的onPropertyOperate()方法。这个方法在下一篇文章中会用到。

    @Override
    public void onPropertyOperate(GattCharacteristic characteristic, String operateName) {

    }

运行一下看看效果。

在这里插入图片描述

六、源码

如果对你有所帮助的话,不妨 StarFork,山高水长,后会有期~

源码地址:HarmonyBle-Java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1284966.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之linux存储管理(5)》(21)

《Linux操作系统原理分析之linux存储管理&#xff08;5&#xff09;》&#xff08;21&#xff09; 6 Linux存储管理6.6 Linux 物理空间管理6.6.1 Linux 物理内存空间6.6.2 物理页面的管理6.6.3 空闲页面管理——buddy 算法 6.7 内存的分配与释放6.7.1 物理内存分配的数据结构 6…

Design patterns--代理模式

设计模式之代理模式 我们使用Qt开发大型应用程序时&#xff0c;经常遇见大型程序启动时需要加载一些配置信息、用户末次操作信息&#xff0c;以及算法模型等数据时比较费时&#xff0c;笔者在程序启动时设计欢迎页或加载页等窗体来提示用户程序正在加载某些数据&#xff0c;加载…

基于SSM框架的《超市订单管理系统》Web项目开发(第五天)供应商管理,增删改查

基于SSM框架的《超市订单管理系统》Web项目开发&#xff08;第五天&#xff09;供应商管理&#xff0c;增删改查 上一次我们实现了多表关联查询&#xff0c;还有分页显示数据的功能。还完善了用户管理这一模块。 因此今天我们需要完成的是供应商管理模块&#xff0c;这一模块…

SQL自学通之表达式条件语句与运算

目录 一、目标 二、表达式条件语句 1、表达式&#xff1a; 2、条件 2.1、WHERE 子句 三、运算 1、数值型运算: 1.1、加法() 1.2、减法 (-) 1.3、除法&#xff08;/&#xff09; 1.4、乘法 &#xff08;*&#xff09; 1.5、取模 &#xff08;%&#xff09; 优先级别…

第24章:Kubernetes Helm Introduction

目录 1. Helm简介2. Helm Charts文件&#xff08;.tgz&#xff09;组成3. Helm核心术语&#xff1a;4. Helm常用命令&#xff1a;5. DIY简单Helm Charts参考链接 1. Helm简介 Helm用于管理Kubernetes应用程序&#xff0c;Helm Charts可以用于定义、安装和升级最复杂的Kubernet…

西南科技大学模拟电子技术实验七(集成运算放大器的非线性应用)预习报告

一、计算/设计过程 说明:本实验是验证性实验,计算预测验证结果。是设计性实验一定要从系统指标计算出元件参数过程,越详细越好。用公式输入法完成相关公式内容,不得贴手写图片。(注意:从抽象公式直接得出结果,不得分,页数可根据内容调整) 预习计算内容根据运放的非线…

Android加载AnimatedImageDrawable播放gif动态图,Kotlin

Android加载AnimatedImageDrawable播放gif动态图&#xff0c;Kotlin import android.graphics.ImageDecoder import android.graphics.ImageDecoder.OnHeaderDecodedListener import android.graphics.drawable.AnimatedImageDrawable import android.os.Bundle import android…

SVG-椭圆弧-参数转换-计算公式-标准解读

文章目录 1.简介2.基本参数2.1.椭圆的表达2.2.参数变换2.3.注意事项 3.参考资料4.总结 1.简介 为了与其他路径段表示法保持一致&#xff0c; SVG 路径中的圆弧是根据曲线上的起点和终点定义的。椭圆弧的这种端点参数化。优点是它允许与其它路径一致的语法&#xff0c;其中所有…

Spring Security 6.x 系列(9)—— 基于过滤器链的源码分析(二)

一、前言 在本系列文章&#xff1a; Spring Security 6.x 系列&#xff08;4&#xff09;—— 基于过滤器链的源码分析&#xff08;一&#xff09;中着重分析了Spring Security在Spring Boot 的自动配置、 DefaultSecurityFilterChain 的构造流程、FilterChainProxy 的构造流…

深入学习锁--Synchronized各种使用方法

一、什么是synchronized 在Java当中synchronized通常是用来标记一个方法或者代码块。在Java当中被synchronized标记的代码或者方法在同一个时刻只能够有一个线程执行被synchronized修饰的方法或者代码块。因此被synchronized修饰的方法或者代码块不会出现数据竞争的情况&#x…

Spring Boot中使用Swagger

1. 启用Swagger 1.1 启用注解扫描和文档接口 直接在POM文件引入依赖 <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version> </dependency>1.2 启动swagger-u…

ARM与大模型,狭路相逢

编辑&#xff1a;阿冒 设计&#xff1a;沐由 从去年底至今&#xff0c;伴随着OpenAI旗下ChatGPT的火爆&#xff0c;一波AI大模型推动着AI应用全面进入了大模型时代。与此同时&#xff0c;随着边缘算力的提升&#xff0c;AI大模型的部署也逐渐从云端涉入到边缘。 世界对AI算力的…

黑马一站制造数仓实战1

1. 项目目标 一站制造 企业中项目开发的落地&#xff1a;代码开发 代码开发&#xff1a;SQL【DSL SQL】 SparkCore SparkSQL 数仓的一些实际应用&#xff1a;分层体系、建模实现 2. 内容目标 项目业务介绍&#xff1a;背景、需求 项目技术架构&#xff1a;选型、架构 项目环境…

Selenium 自动化高级操作与解决疑难杂症,如无法连接、使用代理等

解决 Selenium 自动化中的常见疑难杂症 这里记录一些关于 Selenium的常用操作和疑难杂症。 有一些细节的知识点就不重复介绍了&#xff0c;因为之前的文章中都有&#xff01; 如果对本文中的知识点有疑问的&#xff0c;可以先阅读我以前分享的文章&#xff01; 知识点&…

1-4、调试汇编程序

语雀原文链接 文章目录 1、执行过程第一步&#xff1a;源程序第二步&#xff1a;编译连接第三步&#xff1a;执行 2、DOSBox运行程序第1步 进入EDIT.EXE第2步 编写源程序第3步 编译第4步 连接第5步 执行完整过程 3、DEBUG跟踪执行过程加载程序到内存执行程序debug和源程序数字…

【导航控制器总结-导航控制器栈 Objective-C语言】

一、导航控制器总结 1.我们接着上一堂课的内容继续 我们上节课说到哪里了,是不是就是对这个导航控制器的一个总结啊 然后,使用的注意事项 2.导航控制器使用注意事项: 1)第一点,使用导航控制器,你在创建的时候,需要给它指定一个根控制器 创建导航控制器的同时,指定…

【译】如何在调试时分析CPU和内存(Analyze CPU and Memory while Debugging)

您想了解如何使您的代码运行得更快&#xff0c;使用更少的内存&#xff0c;或者只是找出您的代码是否有CPU或内存问题?你当然会——你是一名开发人员!但是&#xff0c;内存和性能调优经常会遇到“重要但不紧急”的任务&#xff0c;因为真正紧急的事情&#xff0c;您似乎根本无…

优化 SQL 日志记录的方法

为什么 SQL 日志记录是必不可少的 SQL 日志记录在数据库安全和审计中起着至关重要的作用&#xff0c;它涉及跟踪在数据库上执行的所有 SQL 语句&#xff0c;从而实现审计、故障排除和取证分析。SQL 日志记录可以提供有关数据库如何访问和使用的宝贵见解&#xff0c;使其成为确…

Dockerfile脚本编写流程及示例

学习dockerfile指令 Dockerfile 指令 说明 FROM 指定基础镜像 MAINTAINER 声明镜像的维护者 LABEL 添加元数据标签 RUN 在容器中执行命令 CMD 容器启动后默认执行的命令 EXPOSE 暴露容器的端口 ENV 设置环境变量 ADD 将文件、目录或远程文件添加到容器中 COP…

[ 蓝桥杯Web真题 ]-外卖给好评

目录 介绍 准备 目标 效果 规定 思路 解答参考 介绍 外卖是现代生活中必备的一环。收到外卖后&#xff0c;各大平台软件常常会邀请用户在口味&#xff0c;配送速度等多个方面给与评分。在 element-ui 组件中&#xff0c;已经有相应的 Rate 组件&#xff0c;但是已有组件…