# MinewMWB02Kit Documentation

This SDK only supports Bluetooth devices produced by Minew company.

SDK can assist developers in handling all tasks between mobile phones and Bluetooth devices, including scanning devices, broadcasting data, connecting devices, writing data to devices, receiving data from devices, etc.

At present, the SDK only supports the use of Wearable SOS Button devices.

# Preliminary work

Overall framework: MWB02BleManager is a device management class that remains singleton during app runtime. MWB02Model is a device instance class that generates an instance for each device, which is used after scanning and connecting. It contains device broadcast data, which is updated as the device broadcasts continuously during scanning. ``MWB02BleManager: Device management class that can scan surrounding devices, connect them, verify them, etcMWB02Model: The BLE LTE Location Badge device instance obtained during scanning, inherited from BaseBleDeviceEntity`

# Import into project

  1. development environment

    The SDK supports a minimum of Android 5.0 and corresponds to API Level 21. Set minSdkVersion to 21 or above in the build. gradle of the module:

    android {
        defaultConfig {
            applicationId "com.xxx.xxx"
            minSdkVersion 21
        }
    }
    
    1
    2
    3
    4
    5
    6
  2. Add the jar package to the libs folder of the moduleand add the following statement in the build. gradle of the module (directly add dependencies):

    implementation files('libs/lib_ble_base.jar')
    implementation files('libs/lib_ble_mwb02.jar')
    implementation files('libs/lib_ble_nl.jar')
    api 'org.lucee:bcprov-jdk15on:1.52.0'
    api 'com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:2.16.0'
    
    1
    2
    3
    4
    5

Alternatively, right-click on the jar file and select Add as Library to add it to the current module.

Add the. so library file and add the following configuration to build. gradle in the App directory:

   android {
       defaultConfig {
           ndk {
               abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
           }
       }
       sourceSets {
           main {
               jniLibs.srcDirs = ['libs']
           }
       }
   }
1
2
3
4
5
6
7
8
9
10
11
12
  1. The following permissions are required in AndroidManifest. xml If targetSdkVersion is greater than 23, permission management needs to be done to obtain the permissions:

        <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" tools:node="replace" />
        <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" tools:node="replace" />
        <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
        <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
        <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
        <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
        <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
        <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13

# USE

SDK is divided into three stages: scanning, connection, and read-write.

For Android 6.0 and above systems, when performing BLE scanning, it is necessary to first apply for Bluetooth permission and turn on the location switch before proceeding.

# Start Scan

For Android 6.0 and above systems, when performing BLE scanning, it is necessary to first apply for Bluetooth permission and turn on the location switch before proceeding.

To enable Bluetooth scanning, you need to first turn on Bluetooth. If you scan without turning on Bluetooth, the app will flash back. BLETool. checkBluetooth (this) can be used to determine if Bluetooth is turned on. If it's not turned on, you can turn on Bluetooth first.

MWB02BleManager mBleManager = MWB02BleManager.getInstance();

switch (BLETool.checkBluetooth(this)){
    case BLE_NOT_SUPPORT:
        Toast.makeText(this, "Not Support BLE", Toast.LENGTH_SHORT).show();
        break;
    case BLUETOOTH_ON:
		//Set the scanning time to 5 minutes, the SDK defaults to a scanning time of 5 minutes
		mBleManager.startScan(this, 5 * 60 * 1000, new OnScanDevicesResultListener<MWB02Model>() {
            @Override
            public void onScanResult(List<MWB02Model> list) {
            }

            @Override
            public void onStopScan(List<MWB02Model> list) {
            }
        });
        break;
    case BLUETOOTH_OFF:
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableIntent, 4);
        break;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

During the scanning process, the APP can obtain a portion of the current device data through the SDK. Obtain device data through the MWB02Model as shown below, which is saved in the broadcast frame object.

The SDK providesBaseBleDeviceEntity as the base class for MWB02Model to store public data of devices, as shown in the following table:

field type description
macAddress String mac
name String device name
rssi int blue strength

BaseBleDeviceEntity also stores a BaseNanoLinkFrame, which is used internally to store the device broadcast data frames obtained during scanning. It can be retrieved in the following ways:

MWB02Model module;
MWB02AdvFrame mwb02AdvFrame = (MWB02AdvFrame) module.getNanoLinkFrame();
if (mwb02AdvFrame != null) {
    //mac
    String macAddress = mwb02AdvFrame.getMac();
    //deviceName
    String deviceName = mwb02AdvFrame.getDeviceName();
    //firmwareVersion
    String firmwareVersion = mwb02AdvFrame.getFirmwareVersion();
    //battery Battery percentage,default:Integer.MIN_VALUE Indicates that battery information is not available
    int battery = mwb02AdvFrame.getBattery();
    //motion: 0 Active (moving)  1 Idle (stationary)
    int motion = mwb02AdvFrame.getMotion();
    //modeSos :0 Device is NOT in mode SOS ,1 Device is in mode SOS
    int modeSos = mwb02AdvFrame.getModeSos();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Wearable SOS Button have 1 types of broadcast frames available。

  1. MWB02AdvFrame

    • MWB02AdvFrame

      field type description
      mac String mac
      deviceName String device Name
      firmwareVersion String firmware Version
      battery int Battery percentage,default:Integer.MIN_VALUE Indicates that battery information is not available
      motion int 0 Active (moving) 1 Idle (stationary)
      modeSos int 0 Device is NOT in mode SOS ,1 Device is in mode SOS

# Connect

Before connecting, it is generally necessary to stop scanning. The SDK provides methods for connecting and disconnecting.

MWB02BleManager mBleManager = MWB02BleManager.getInstance();
//stop
mBleManager.stopScan(context);
//Connection: The module is the device to be connected to
MWB02Model module;
mBleManager.connect(context,module);
//Disconnect: macAddress is the device's MAC address
mBleManager.disConnect(macAddress);
1
2
3
4
5
6
7
8

Attention: Before connecting the device, please confirm if the device is scanned. If the device broadcast is not scanned, calling the connection method will result in a connection failure.

After calling 'connect()', the SDK will monitor the status of the connection process.

//Set up listener
mBleManager.setOnConnStateListener(new OnConnStateListener() {
    /*
     * State callback during connection process
     * @param macAddress      mac
     * @param BleConnectionState connectionState
     */
    @Override
    public void onUpdateConnState(String address, BleConnectionState state) {
        switch (state) {
            case Connecting:
				//After calling connect(), the state will be called back
                break;
            case Connected:
                //The initial connection was successful, but as a transitional stage, it was not truly successful at this time
                break;
            case Bond_None:
				//device pairing callback, this is an invalid pairing state
                break;
            case Bond_Bonding:
				//device pairing callback, this is in the pairing state
                break;
            case Bond_Bonded:
				//device pairing callback, here is the pairing completion status
                //devices must be paired before they can be operated using the methods provided in MWB02BleManager
                break;
            case ConnectComplete:
				//devices must be connected before they can be operated using the methods provided in MWB02BleManager
                break;
            case Disconnect:
				//Connection failure or device disconnection will trigger a callback, while active disconnection will not trigger this status
                break;
            default:
                break;
        }
    }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

During the connection process, the SDK will return multiple connection states to the app, and the app needs to handle them properly.

  • BleConnectionState.ConnectingBleConnectionState.Connected: In the connected device, do not perform time-consuming operations in this state, as the device discovers services and sends authentication data.
  • BleConnectionState.Bond_None: device pairing is invalid.
  • BleConnectionState.Bond_Bonding: device is currently in pairing mode.
  • BleConnectionState.Bond_Bonded: device pairing status is complete. Only after the device pairing is completed can device be operated using the methods provided in MWB02BleManager .
  • BleConnectionState.ConnectComplete: device has been successfully connected and can perform read and write operations, such as configuring broadcast parameters and reading historical data.
  • BleConnectionState.Disconnect: Connection failure or device disconnection will result in a callback.

# Device configuration read and write operations

The API for device configuration read and write operations is as follows, which can be called using the MWB02BleManager mBleManager=MWB02BleManager. getInstance() object:

    /**
     * Clear the list of scanning devices
     */
     void clearScanResult();

    /**
     * Set default scanning duration
     *
     * @param scanTime Scanning duration, in milliseconds
     */
     void setDefaultScanTime(int scanTime);

    /**
     * Start scanning device
     *
     * @param context context
     * @param listener OnScanDevicesResultListener
     */
     void startScan(Context context, OnScanDevicesResultListener listener) ;

    /**
     * Start scanning device
     *
     * @param context context
     * @param scanTime Scanning duration, in milliseconds
     * @param listener OnScanDevicesResultListener
     */
     void startScan(Context context, int scanTime, OnScanDevicesResultListener listener) ;

    /**
     * Stop scanning device
     *
     * @param context context
     */
     void stopScan(Context context) ;

    /**
     * Determine if scanning is in progress
     *
     */
     boolean isScanning() ;

    /**
     * Restore factory settings
     *
     * @param macAddress mac
     * @param listener OnModifyConfigurationListener
     */
     void reset(String macAddress, OnModifyConfigurationListener listener);

    /**
     * Shutdown
     *
     * @param macAddress mac
     * @param listener OnModifyConfigurationListener
     */
     void powerOff(String macAddress, OnModifyConfigurationListener listener);

    /**
     * Restart
     *
     * @param macAddress mac
     * @param listener OnModifyConfigurationListener
     */
     void reboot(String macAddress, OnModifyConfigurationListener listener);

    /**
     * Connected Device
     *
     * @param context context
     * @param macAddress mac
     */
	 void connect(Context context, String macAddress);

    /**
     * Connected Device
     *
     * @param context context
     * @param module MWC03Model
     */
	 void void connect(Context context, MWC03Model module);

    /**
     * Disconnect
     *
     * @param macAddress mac
     */
	 void void disConnect(String macAddress);

    /**
     * Set up device connection listener
     *
     * @param listener OnConnStateListener
     */
	void setOnConnStateListener(OnConnStateListener listener)

    /**
     * device firmware upgrade
     *
     * @param macAddress  mac
     * @param isLinkUpgrade :true -> upgrade by url,false -> upgrade by file。Default value false, does not support URL upgrade method
     * @param filePath OTA file path, it can be null when upgrading by URL
     * @param upgradeData OTA file data bytes, it can be null when upgrading by URL
     
     * @param fileUpgradeTarget : Upgrade firmware target, OTA data, default fileUpgradeTarget="main", link upgrade method does not need to be modified, only file upgrade method needs to be filled in
     
     * @param linkUpgradeTarget : Upgrade firmware target, OTA data, default linkUpgradeTarget="app", file upgrade method does not need to be modified, only link upgrade method needs to be filled in
     
     * @param listener OnFirmwareUpgradeListener : Upgrade firmware callback
     */
     void firmwareUpgrade(Context context, String macAddress, boolean isLinkUpgrade, String filePath, byte[] upgradeData, String fileUpgradeTarget,String linkUpgradeTarget, OnFirmwareUpgradeListener listener) ;

    /**
     * Query firmware version
     *
     * @param macAddress mac
     * @param listener OnQueryResultListener
     */
	void getFirmwareVersion(String macAddress, OnQueryResultListener<FirmwareVersionModel> listener);

    //Brief content about the FirmwareVersionsModel class
	public class FirmwareVersionModel {
        List<VersionInfo> versionInfoList;
    }

    //About the brief content of the VersionsInfo class
	public class VersionInfo {
        // Firmware Name
        private String firmwareName;
        // Firmware type
        private int firmwareType;
        // Firmware version
        private String firmwareVersion;
        // Firmware slot
        private String slot;
        // methods :Upgrade methods corresponding to firmware types: 'img' supports image file upgrade, 'hl' supports link upgrade, 'file' supports file upgrade
        private ArrayList<String> methods;
    }

	
	/**
     * Obtain the trigger mode
     * @param macAddress  MAC 
     * @param listener
     */
	void getTriggerMode(String macAddress, OnQueryResultListener<TriggerMode> listener);
	
	//About the brief content of the TriggerMode class
	public class TriggerMode {
        //Press event type
        public static final String KEVT_PRESS = "10";
        //Double-click event type
    	public static final String KEVT_DOUBLE = "2";
        //The event type must be a numerical value of KEVT-PRESS or KEVT-DUBLE
        private String kevt;
        //This field represents the duration for which the device remains in Trigger mode after activation. A value of 0 is a special case, indicating that the mode remains active indefinitely. The unit is seconds.
        private int dur;
        //Exit event type must be a numerical value of KEVT-PRESS or KEVT-DUBLE
        private String e_kevt;
    }

    /**
     * Set the trigger mode
     * @param macAddress  MAC
     * @param kevt :The trigger event must be either the value of KEVT_PRESS or KEVT_DOUBLE
     * @param cont :Trigger duration,The unit is seconds.The range is 1 second to 300 seconds.
     * @param listener
     */
    void setTriggerMode(String macAddress, String kevt,int cont,String e_kevt, OnModifyConfigurationListener listener);

    /**
     * Trigger state reset
     * @param macAddress  MAC
     * @param force :Mandatory or not
     
     * @param isNeedAddForce : True indicates that the force setting above is valid, false indicates that the force setting above is invalid
     
     * @param listener
     */
    void setStatusReset(String macAddress, boolean force, boolean isNeedAddForce,OnModifyConfigurationListener listener);


    /**
     * Get broadcast parameters
     * @param macAddress  MAC
     * @param listener
     */
    void getAdvParameter(String macAddress, OnQueryResultListener<AdvParameter> listener);

	//About the brief content of the AdvParameter class
	public class AdvParameter {
        //Normal mode parameters
    	private AdvParameterNormal norm;
		//Trigger mode parameter - SOS mode or Button mode
    	private AdvParameterTrigger trig;
    }

	//About the brief content of the AdvParameterNormal class
	public class AdvParameterNormal {
		//The on/off status of this mode
    	private boolean en;
		//The broadcast parameters of this mode
    	private AdvParameterParam param;
    }

	//About the brief content of the AdvParameterTrigger class
	public class AdvParameterTrigger {
		//The on/off status of this mode
    	private boolean en;
		//The broadcast parameters of this mode
    	private AdvParameterParam param;
    }

	//About the brief content of the AdvParameterParam class
	public class AdvParameterParam {
		//The broadcast interval of this mode, Adjustable from 100ms to 10000ms, with a scale of 100ms
    	private int intvl;
		//The broadcast power of this mode,There are 8: -40, -20, -16, -12, -8, -4, 0, 4, 8
    	private int txpwr;
    }

    /**
     * Configure broadcast parameters
     * @param macAddress MAC
     * @param advParameter Broadcast parameters
     * @param listener
     */
    void setAdvParameter(String macAddress, AdvParameter advParameter, OnModifyConfigurationListener listener);

    /**
     * Obtain scanning parameter configuration
     * @param macAddress  MAC
     * @param listener
     */
    void getLeScanFilter(String macAddress, OnQueryResultListener<LeScanFilter> listener);

	//About the brief content of the LeScanFilter class
    public class LeScanFilter {
		//scanning mode
        public LeScanFilterMode mode;
		//Scan filter, the key is just one of rssi, re_mac, re_raw
        //When the key is rssi, the value is int type data, ranging from -100 to 0
        //When the key is re_mac, the value is a regular expression of type String with a length of 64 characters
        //When the key is re_raw, the value is a regular expression of type String with a length of 192 characters
        public List<TypeMap<String, Object>> filter;
    }

	//About the brief content of the LeScanFilterMode class
    public class LeScanFilterMode {
		//Normal Mode
    	public LeScanFilterNorm norm;
		//Trigger mode: SOS or button press
    	public LeScanFilterTrig trig;
    }

	//About the brief content of the LeScanFilterNorm class
    public class LeScanFilterNorm {
		//Normal mode scan switch status
        public boolean en;
		//Normal mode scanning parameters
        public LeScanFilterParam param;
    }

	//About the brief content of the LeScanFilterTrig class
    public class LeScanFilterTrig {
		//Trigger [SOS or button] mode to scan switch status
        public boolean en;
		//Trigger [SOS or button] mode to scan parameters
        public LeScanFilterParam param;
    }

	//About the brief content of the LeScanFilterParam class
    public class LeScanFilterParam {
		//Scan interval duration, Adjustable from 100ms to 10000ms, with a scale of 100ms
        public float intvl;
		//Scan window duration,Scan Window defines how long to scan at each interval. The unit is milliseconds. The valid range for this field is 2.5ms to 10240ms (10.24s).
        public float window;
		//Scan timeout duration,LE scan timeout, the duration of a single scan in PRD. The unit is milliseconds. The unit is milliseconds. The valid range for this field is 500ms to 655350ms (655.35s). 
        public int timeout;
		//Scan restart duration,Time between two LE scan. The unit is milliseconds.
        public int gap;
		//Is it active scanning: true Active scanning false Passive scanning
        public boolean active;
    }

    /**
     * Set scanning parameters
     * @param macAddress  MAC
     * @param leScanFilter
     * @param listener
     */
    void setLeScanFilter(String macAddress, LeScanFilter leScanFilter, OnModifyConfigurationListener listener);

    /**
     * Obtain lighting effect configuration
     * @param macAddress  MAC
     * @param listener
     */
    void getDeviceLEDConfig(@NonNull String macAddress, OnQueryResultListener<LedConfigEntity> listener);

	//About the brief content of the LedConfigEntity class
    public class LedConfigEntity {
        public static final String COLOR_BLUE = "blue";
        public static final String COLOR_GREEN = "green";
        public static final String COLOR_RED = "red";
        public static final String COLOR_YELLOW = "yellow";
        public static final String COLOR_WHITE = "white";
        public static final String COLOR_MAGENTA = "magenta";
        public static final String COLOR_CYAN = "cyan";
        
        public static final String EFFECT_OFF = "off";
        public static final String EFFECT_STEADY = "steady";
        public static final String EFFECT_BLINK = "blink";
        
        //This field represents the color of the LED and must be one of the following strings: "blue", "green", "red", "yellow", "white", "magenta", "cyan". This is an optional field and only takes effect if the device supports multi-color LEDs.
        private String color;
        //This field specifies the LED effect and must be one of the following strings: "off", "steady", or "blink".
        private String effect;
        //This field is of array type and defines the detailed behavior when the LED is set to blink. The 1st parameter indicates the duration (in milliseconds) that the LED stays on in a single cycle(Range 1-65535). The 2nd parameter indicates the duration (in milliseconds) that the LED stays off in the same cycle(Range 1-65535). The 3rd parameter specifies the number of cycles to perform.
        private int[] params;
    }

    /**
     * Set the lighting effect
     * @param macAddress  MAC
     * @param ledConfig
     * @param listener
     */
    void setDeviceLEDConfig(@NonNull String macAddress, LedConfigEntity ledConfig, OnModifyConfigurationListener listener);

    /**
     * Get Relay Control configuration
     * @param macAddress  MAC
     * @param listener
     */
    void getRelayControl(String macAddress, OnQueryResultListener<RelayControl> listener);

	//About the brief content of the RelayControl class
    public class RelayControl {
		//This field specifies the type of message to be relayed. It has two case-insensitive options: "mac" and "imm". "mac" means the relayed content is a Bluetooth LE MAC address; "imm" means the relayed content is the Major & Minor values from an Apple iBeacon.
        private String type;
		//This field specifies how many bytes of the MAC address must be retained when relaying. Allowed lengths are 2, 3, 4, and 6. This field is optional and defaults to 2. It is effective only when the type field is set to "mac".If the value obtained is Integra.MN_VALUE, it means that no data has been obtained.
        private Integer aln = Integer.MIN_VALUE;
		//This field specifies the upper limit on the number of data items to relay at one time (i.e., the maximum number of devices per round). When relaying, the device always selects the most recent records. For example, if the previous Bluetooth scan produced 5 records and the limit is set to 4, the oldest record is discarded; if the limit is set to 6 and only 5 valid records were found, then 5 records are relayed. This field is optional and defaults to 5.If the value obtained is Integra.MN_VALUE, it means that no data has been obtained. The range is 1-100.
        private Integer max = Integer.MIN_VALUE;
		//This field specifies the number of relay attempts. It is optional. If it is not present, it indicates continuous relay advertising.If the value obtained is Integra.MN_VALUE, it means that no data has been obtained.
        private Long cnt = Long.MIN_VALUE;
    }

    /**
     * Set Relay Control
     * @param macAddress  MAC
     * @param relayControl
     * @param listener
     */
    void setRelayControl(String macAddress, RelayControl relayControl, OnModifyConfigurationListener listener);

    /**
     * Get Apple Ibeacon Frame configuration
     * @param macAddress  MAC
     * @param listener
     */
    void getAppleIbeaconFrame(String macAddress, OnQueryResultListener<AppleIbeaconFrame> listener);

	//About the brief content of the AppleIbeaconFrame class
    public class AppleIbeaconFrame {
		//Normal mode parameters
        public AppleIbeaconNorm norm;
    }

	//About the brief content of the AppleIbeaconNorm class
    public class AppleIbeaconNorm {
		//iBeacon frame broadcast on/off status
        public Boolean en;
		//iBeacon frame broadcast data
        public AppleIbeaconData data;
		//ibeacon number of participants
        public AppleIbeaconParam param;
    }

	//About the brief content of the AppleIbeaconData class
    public class AppleIbeaconData {
        //UUID in Apple iBeacon ad frames,The length must be 32.
        private String uuid;
		//major in Apple iBeacon ad frames,Range 0-65535
        private Integer major;
		//minor in Apple iBeacon ad frames,Range 0-65535
        private Integer minor;
		//This field indicates the Calibrated Tx power at 1 m in the Apple iBeacon advertising frame, in dBm, ranging from -128 to 127.
        private Integer cpwr;
    }

	//About the brief content of the AppleIbeaconParam class
    public class AppleIbeaconParam {
        //Advertising interval, Unit: ms.Adjustable from 100ms to 10000ms, with increments of 100ms.
        private Integer intvl;
		//Advertising transmit power, Uint: dBm. If the input value is NOT directly supported by the device, the closest supported value will be used instead.There are 8 values: -40, -20, -16, -12, -8, -4, 0, 4, 8 (unit: dBm)
        private Integer txpwr;
    }

    /**
     * Set Apple Ibeacon Frame
     * @param macAddress  MAC
     * @param appleIbeaconFrame
     * @param listener
     */
    void setAppleIbeaconFrame(String macAddress, AppleIbeaconFrame appleIbeaconFrame, OnModifyConfigurationListener listener);

    /**
     * Get Eddystone Uid Frame configuration
     * @param macAddress  MAC
     * @param listener
     */
    void getEddystoneUidFrame(String macAddress, OnQueryResultListener<EddystoneUidFrame> listener);

	//About the brief content of the EddystoneUidFrame class
    public class EddystoneUidFrame {
		//Normal mode parameters
        public EddystoneUidNorm norm;
    }

	//About the brief content of the EddystoneUidNorm class
    public class EddystoneUidNorm {
		//UID frame broadcast on/off status
        private Boolean en;
		//UID frame broadcast data
        private EddystoneUidData data;
		//UID frame broadcast parameters
        private EddystoneUidParam param;
    }

	//About the brief content of the EddystoneUidData class
    public class EddystoneUidData {
		//This field indicates the Calibrated Tx power at 0 m in the Eddystone URL advertising frame, in dBm,Range -100 ~ 20
        private Integer cpwr;
		//Namespace ID length must be 20.
        private String nid;
		//Instance ID length must be 12.
        private String bid;
    }

	//About the brief content of the EddystoneUidParam class
    public class EddystoneUidParam {
        //uid Advertising interval, Unit: ms,Adjustable from 100ms to 10000ms, with increments of 100ms.
        private Integer intvl;
		//uid Advertising transmit power, Uint: dBm. If the input value is NOT directly supported by the device, the closest supported value will be used instead,There are 8 values: -40, -20, -16, -12, -8, -4, 0, 4, 8 (unit: dBm)
        private Integer txpwr;
    }

    /**
     * Set EddystoneUidFrame parameters
     * @param macAddress  MAC
     * @param eddystoneUidFrame
     * @param listener
     */
    void setEddystoneUidFrame(String macAddress, EddystoneUidFrame eddystoneUidFrame, OnModifyConfigurationListener listener);

    /**
     * Get Eddystone URL Frame Configuration
     * @param macAddress  MAC
     * @param listener
     */
    void getEddystoneUrlFrame(String macAddress, OnQueryResultListener<EddystoneUrlFrame> listener);

    /**
     * Get Eddystone Url Frame configuration
     * @param macAddress
     * @param listener
     */
    void getEddystoneUrlFrame(String macAddress, OnQueryResultListener<EddystoneUrlFrame> listener);

	//About the brief content of the EddystoneUrlFrame class
    public class EddystoneUrlFrame {
		//正常模式参数
        public EddystoneUrlNorm norm;
    }

	//About the brief content of the EddystoneUrlNorm class
    public class EddystoneUrlNorm {
		//URL frame broadcast on/off status
        private Boolean en;
		//URL frame broadcast data
        private EddystoneUrlData data;
		//URL frame broadcast parameters
        private EddystoneUrlParam param;
    }

	//About the brief content of the EddystoneUrlData class
    public class EddystoneUrlData {
		//This field indicates the Calibrated Tx power at 0 m in the Eddystone URL advertising frame, in dBm,Range -100 ~ 20
        private Integer cpwr;
		//URL data in the Advertising frame
        private String url;
    }

	//About the brief content of the EddystoneUrlParam class
    public class EddystoneUrlParam {
        //url Advertising interval, Unit: ms,Adjustable from 100ms to 10000ms, with increments of 100ms.
        private Integer intvl;
		//url Advertising transmit power, Uint: dBm. If the input value is NOT directly supported by the device, the closest supported value will be used instead,There are 8 values: -40, -20, -16, -12, -8, -4, 0, 4, 8 (unit: dBm)
        private Integer txpwr;
    }

    /**
     * Set EddystoneUrlFrame
     * @param macAddress  MAC
     * @param eddystoneUrlFrame
     * @param listener
     */
    void setEddystoneUrlFrame(String macAddress, EddystoneUrlFrame eddystoneUrlFrame, OnModifyConfigurationListener listener);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

Provide additional explanations for some methods:

  1. Grant the device the current mobile phone time:

    	
    	// First, check if Bluetooth is turned on. The CurrentTimeService service on your phone can only be started when Bluetooth is on. If Bluetooth is off, attempting to start it may cause errors on some Android phones. You also need to monitor the Bluetooth status. When Bluetooth is on, the startSyncTimeServer service needs to be started; when Bluetooth is off, the closeSyncTimeServer service needs to be stopped. Note that the closeSyncTimeServer service also needs to be stopped when the activity page is executed in ondestroy.
    	MWB02BleManager mBleManager = MWB02BleManager.getInstance();
    	// Start service
    	mBleManager.startSyncTimeServer(context);
        // Close Service
        mBleManager.closeSyncTimeServer(context); 
    
    
    	// Because some phones may occasionally fail to synchronize time, it's necessary to determine if synchronization was successful. It's recommended to check 3 seconds after the device successfully connects.
    	mBleManager.isDeviceReadSyncTime(context); 
    	// If the time synchronization operation fails, then you need to actively send a time synchronization command to the device.
    	mBleManager.writeTimeToDevice(macAddress, onWriteTimeToDeviceListener);
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  2. Firmware upgrade:

    /**
     * Firmware upgrade:
     *
     * @param macAddress  mac
     * @param upgradeData Upgrade package data
     * @param listener    OnFirmwareUpgradeListener
     */
    mBleManager.firmwareUpgrade(mac,false,0, upgradeData, new OnFirmwareUpgradeListener() {
        
        /**
         * Update package data writing progress
         */
        @Override
        public void updateProgress(int progress) {
        }
    
        /**
         * Upgrade successful callback, at this point the device will actively disconnect from the phone, triggering the On State Listener callback and returning the BleeConnectionState.Disconnect status
         */
        @Override
        public void upgradeSuccess() {
        }
        
        /**
         * Upgrade failed
         */
        @Override
        public void upgradeFailed() {
        }
    });
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
  3. Search History Record

    
    // Because reading historical records is a time-consuming operation, it must be called in a background thread, not in the main thread.
    lifecycleScope.launch(Dispatchers.IO) {
        					//Historical record Searcher: StorageIndexRecordSearcher
        					//Generic type of query data callback: StorageActualDataClick
        					//Call getStorageIndexRecordsNeedSearchFile to perform a query, with the following parameters:
                            StorageIndexRecordSearcher<StorageActualDataClick>().getStorageIndexRecordsNeedSearchFile(
                                //context
                                context,
                                //macAddress
                                macAddress,
                                //Enable logging of query history; false means disabled, true means enabled.
                                false,
                                //Query conditions for history
                                StorageIndexRecordCondition()
                                	//Data type to query
                                    .setStorageDataBlockType(StorageDataBlockType.Click)
                                	//Querying instances of the corresponding data type, generally using: StorageIndexInstance.INSTANCE_DEFAULT
                                    .setInstance(StorageIndexInstance.INSTANCE_DEFAULT)
                                	//The `queryAllData` variable specifies the start time for querying historical data. It is defined by the developer; `true` retrieves all data, and `false` retrieves data by time period. The unit for this parameter is seconds.
                                    .setStartTime(when (queryAllData){
                                        true ->0
                                        else  ->selectedStartTimeDate.time/1000
                                    })
                                	//The `queryAllData` variable specifies the end time for querying historical data. It is defined by the developer; `true` retrieves all data, and `false` retrieves data by time period. The unit for this parameter is seconds.
                                    .setEndTime(when (queryAllData){
                                        true ->System.currentTimeMillis()/1000
                                        else  ->selectedEndTimeDate.time/1000
                                    })
                            ) { 
                                //resultClickList The query results for historical data of type StorageDataBlockType.Click are as follows: If the result is empty, it means that there are no historical records for that time period.
                                //exceptionClick If any data errors occur during the query, a notification will be displayed to the developer here. If no errors occur, the value will be null.
                                resultClickList,exceptionClick ->
                                LogUtil.e("exceptionClick  ${exceptionClick?:" exceptionClick null "}")
                                    
    							//The generic type of the query data callback is StorageActualDataScanResultAdvertisingRawData.
                                StorageIndexRecordSearcher<StorageActualDataScanResultAdvertisingRawData>().getStorageIndexRecordsNeedSearchFile(
                                    //context
                                    context,
                                    //macAddress
                                    macAddress,
                                    //Enable logging of query history; false means disabled, true means enabled.
                                    false,
                                    //Query conditions for history
                                    StorageIndexRecordCondition()
                                    	//Data type to query
                                        .setStorageDataBlockType(StorageDataBlockType.Scan_Result)
                                    	//Querying instances of the corresponding data type, generally using: StorageIndexInstance.INSTANCE_DEFAULT
                                        .setInstance(StorageIndexInstance.INSTANCE_DEFAULT)
                                    	//The `queryAllData` variable specifies the start time for querying historical data. It is defined by the developer; `true` retrieves all data, and `false` retrieves data by time period. The unit for this parameter is seconds.
                                        .setStartTime(when (queryAllData){
                                            true ->0
                                            else  ->selectedStartTimeDate.time/1000
                                        })
                                    	//The `queryAllData` variable specifies the end time for querying historical data. It is defined by the developer; `true` retrieves all data, and `false` retrieves data by time period. The unit for this parameter is seconds.
                                        .setEndTime(when (queryAllData){
                                            true ->System.currentTimeMillis()/1000
                                            else  ->selectedEndTimeDate.time/1000
                                        })
                                    	//Due to Android phone system memory limitations on apps, querying too much data may cause memory overflow, so it is necessary to limit the maximum amount of historical data that can be queried.
                                        .setMaximumQuantityLimit(StorageIndexRecordCondition.QuantityLimit.LIMIT_10000)
                                ) { 
                                    //resultStorageActualDataScanResultAdvertisingRawDataList  The query results for historical data of type StorageDataBlockType.Scan_Result are as follows: If the result is empty, it means that there are no historical records for that time period.
                                    //exceptionScanResult If any data errors occur during the query, a notification will be displayed to the developer here. If no errors occur, the value will be null.
                                    resultStorageActualDataScanResultAdvertisingRawDataList,exceptionScanResult ->
                                    LogUtil.e("exceptionScanResult  ${exceptionScanResult?:" exceptionScanResult null "}")
                                    storageActualDataScanResultAdvertisingRawDataList = resultStorageActualDataScanResultAdvertisingRawDataList
                                    if (resultStorageActualDataScanResultAdvertisingRawDataList!=null){
                                        LogUtil.e("resultStorageActualDataScanResultAdvertisingRawDataList  ${resultStorageActualDataScanResultAdvertisingRawDataList!!.size}")
                                    }
                                    /**
                                    * Once historical data reading is complete, it is necessary to switch to the main thread to update the user interface.
                                    */
                                    lifecycleScope.launch (Dispatchers.Main){
                                        //The main thread handles operations related to historical data.
                                    }
                                }
                            }
                        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79

# Document update record

  • 2026/02/11 Add MWB02 device operation basic function API
Last Updated:: 2/11/2026, 10:36:25 AM