We use essential cookies for the website to function, as well as analytics cookies for analyzing and creating statistics of the website performance. To agree to the use of analytics cookies, click "Accept All". You can manage your preferences at any time by clicking "Cookie Settings" on the footer. More Information.

Only Essential Cookies
Accept All
Dear developer,

    Due to business adjustments, we will no longer support new developer registrations for Nearby Service starting from September 10, 2024. Existing developers who have already activated Nearby Service can continue to use it. We will notify you separately if there are any changes. Thank you for your support!

GuidesNearby ServiceNearby MessageBeacon Message Publishing and Subscription

Beacon Message Publishing and Subscription

Service Process

A Bluetooth beacon is a physical device based on the BLE technology. Eddystone and iBeacon are the two major beacon protocols. After purchasing a Bluetooth beacon, you can use the app provided by the beacon vendor to configure beacon parameters. In scenarios where messages are published and subscribed to based on Bluetooth beacons, the Nearby Service cloud provides beacon parameters and attachment management capabilities. For details, please refer to REST. You can use the Nearby Service cloud to configure and publish messages, and use Nearby Message API to scan beacons and obtain published messages. Beacon message subscription can be implemented in one of the following ways: Subscribing to Beacon Messages in the Foreground, Subscribing to Beacon Messages in the Background, and Registering a Beacon Scanning Task (Beta). Foreground subscription discovers surrounding Bluetooth beacons more quickly; background subscription consumes less power than foreground subscription does; beacon scanning task registrationbeta keeps scanning beacons in the background. Beacon scanning task registration gives a timely notification when a beacon is discovered, even when the app is closed, but consumes slightly more power than the former two ways do.

Configuring a Beacon

For details about how to configure a beacon, please refer to Beacon Management.

When configuring a beacon, you can associate the beacon ID with an attachment, which is a specific byte stream. Nearby Message stores the attachment without parsing it. An attachment can contain up to 1024 characters. One beacon ID can be associated with up to 9 attachments.

Subscribing to Beacon Messages in the Foreground

Foreground subscription allows your app to discover devices faster, but may be more power-consuming. Note that foreground subscription can only be enabled when your app is running in the foreground. When your app exits the foreground, the message subscription will stop.

The following sample code demonstrates calling get(MessageHandler, GetOption) to enable foreground subscription:
MessageHandler mMessageHandler = new MessageHandler() {
     // Obtain new messages from nearby devices.
    @Override
    public void onFound(Message message) {
        super.onFound(message);
        // Called back when a new message is found. Process your service.
    }
     // Called back when no Bluetooth device is found or the cloud message is lost.
    @Override
    public void onLost(Message message) {
        super.onLost(message);
        // Called back when a new message is found. Process your service.
    }
};
// By default, all types of messages are subscribed to. Multiple filtering rules can be added.
MessagePicker msgPicker = new MessagePicker.Builder()
            .includeNamespaceType("dev91050203040506", "HMS")
            .includeEddystoneUids("5dc33487f02e477d4058", "0117c5986919")
            .includeIBeaconIds(UUID.fromString("01122334-4556-6778-899a-abbccddeeff0"), (short)0x3e8, (short)0x2711)
            .build();
Policy policy = Policy.BLE_ONLY;
GetOption getOption = new GetOption.Builder().setPicker(msgPicker).setPolicy(policy).build();
Task<Void> task = Nearby.getMessageEngine(getApplicationContext()).get(mMessageHandler, getOption);
NOTE
  • An original beacon message maps only one beacon. Subscribing to an original beacon message means to subscribe to status changes of the current target beacon. You can register a beacon on HUAWEI Developers and create an attachment message whose attribute can be NameSpace or Type. When the subscription attribute is NameSpace or Type, the status change of this type of messages is subscribed to.
  • You can use MessageHandler to set the processing logic for message discovery, loss, distance change, and signal strength change that meet the conditions.
  • The default condition of MessagePicker is includeAllTypes(). An app with this condition will subscribe to messages published by all apps in the same project in AppGallery Connect. In addition, you can also customize a combination of multiple message filtering conditions using the following modes: NamespaceType, Eddystone UID, and iBeacon. By default, NamespaceType allows only beacons whose beacon IDs' prefixes are 6bff00f723fdf7471402 to be discovered by Nearby Service. Below is the table for the examples of the filtering conditions.

Examples of beacon message filtering conditions

Expand

Mode

Example

Filtering Condition

Remarks

NamespaceType

includeNamespaceType("dev91050203040506", "HMS")

Scan only beacons whose beacon IDs use the default prefix 6bff00f723fdf7471402 and filter beacon messages whose namespace is dev91050203040506 and type is HMS.

  • For details about how to obtain the namespace and type, see Querying an Attachment List.
  • This condition allows an app to scan beacons, discover beacons, and obtain message attachments that meet namespace and type requirements. Therefore, please configure beacons in AppGallery Connect. For details, see Registering a Beacon.

Eddystone UID

includeEddystoneUids("5dc33487f02e477d40580117c5986919", "0117c5986919")

Scan only beacons of the Eddystone UID format, whose beacon IDs are 5dc33487f02e477d40580117c5986919. In the Eddystone UID, the Namespace ID is 5dc33487f02e477d4058, and Instance ID is 0117c5986919.

This condition allows an app to scan and discover beacons, without obtaining the message attachment. Therefore, you do not need to configure beacons in AppGallery Connect.

iBeacon

includeIBeaconIds(UUID.fromString("14a01af0232a45189c0e899aabbccddeeff03e82711"), (short)0x3e8, (short)0x2711)

Scan only beacons of the iBeacon format, whose beacon IDs are 14a01af0232a45189c0e899aabbccddeeff03e82711. The iBeacon UUID is 14a01af0-232a-4518-9c0e-899a-abbccddeeff0, Major value is (short)0x3e8, and Minor value is (short)0x2711.

This condition allows an app to scan and discover beacons, without obtaining the message attachment. Therefore, you do not need to configure beacons in AppGallery Connect.

Subscribing to Beacon Messages in the Background

The device discovery speed for this mode is much slower than that for the foreground subscription, but this mode is more power-efficient.

The following sample code calls get(PendingIntent) to enable background subscription:
PendingIntent pendingIntent = PendingIntent.getService(this, 0, new Intent(this, BackgroundGetIntentService.class), PendingIntent.FLAG_UPDATE_CURRENT);
Nearby.getMessageEngine(this).get(pendingIntent);

// This IntentService is triggered when the target device is discovered in the background.
public class BackgroundGetIntentService extends IntentService {
    public BackgroundGetIntentService(String name) {
        super(name);
    }
    protected void onHandleIntent(Intent intent) {
        MessageEngine messageEngine = Nearby.getMessageEngine(context);// context is the instance of Context.
        messageEngine.handleIntent(intent, new MessageHandler() {
            @Override
            public void onFound(Message message) {
                Log.i(TAG, "onFound " + new String(message.getContent()));
            }

            @Override
            public void onLost(Message message) {
                Log.i(TAG, "onLost " + new String(message.getContent()));
            }
        });
    }
}

Registering a Beacon Scanning Task (Beta)

NOTICE

This function is not recommended for non-Huawei phones. If it is used on such a phone, exceptions may occur.

  • To better use resources occupied during scanning and reduce power consumption, Nearby Message automatically removes a scanning task that has existed for seven days. If a task needs to exist longer than this period, re-register this task within seven days after it is registered.
  • When this API is called, a popup may be shown to request the location and other permissions from the user. To prevent user experience from being affected, do not call this API when your app runs in the background.

A beacon scanning task keeps running in the background. When detecting a beacon, the task will notify your app of the beacon in Broadcast or Service mode. An app can register only one scanning task. When it is necessary to modify configuration parameters of a registered task, the app needs to unregister the task and then register a new one.

NOTICE

If you need your app to receive beacon messages when it is closed, it is recommended that the following switches be toggled on for your app: Secondary launch and Run in background. Specifically speaking, go to Settings > Apps & services > App launch. Find the app as needed, toggle off Auto-launch, and toggle on the mentioned two switches.

The following is an example for calling registerScanTask(Intent intent, GetBeaconOption option) to register a beacon scanning task:

TriggerOption triggerOption = new TriggerOption.Builder()
    // Set the notification mode (TriggerMode).
    .setTriggerMode(2)
    // Set the class name to Broadcast or Service, which should be consistent with TriggerMode.
    .setTriggerClassName(SampleReceiver.class.getName())
    .build();
Intent intent = new Intent();
intent.putExtra(GetBeaconOption.KEY_TRIGGER_OPTION, triggerOption);

BeaconPicker beaconPicker = new BeaconPicker.Builder()
    // Filter beacons based on NamespaceType.
    .includeNamespaceType("dev91050203040506", "HMS")
    // Filter beacons based on the beacon ID prefix and NamespaceType.
    .includeNamespaceType("dev91050203040506", "HMS", "6bff00f723fdf7471402", BeaconPicker.BEACON_TYPE_IBEACON)
    // Filter beacons based on beacon ID prefix.
    .includeBeaconId("6bff00f723fdf7471402", BeaconPicker.BEACON_TYPE_IBEACON)
    .build();
GetBeaconOption getOption = new GetBeaconOption.Builder().picker(beaconPicker).build();
Nearby.getBeaconEngine(this).registerScanTask(intent, getOption).addOnSuccessListener(new OnSuccessListener<Void>() {
    @Override
    public void onSuccess(Void unused) {
        Log.i(TAG, "registerScanTask success");
    }
    }).addOnFailureListener(new OnFailureListener() {
    @Override
    public void onFailure(Exception e) {
        Log.i(TAG, "registerScanTask fail:" + e.getMessage());
    }
});

BeaconPicker defines filtering conditions for Bluetooth beacons and beacon message attachments, which is different from MessagePicker. The former supports beacon filtering based on beacon ID prefix, NamespaceType, or beacon ID prefix + NamespaceType.

Examples of conditions for filtering beacons and beacon message attachments

Expand

Mode

Example

Filtering Condition

Filtering Condition Constraint

Remarks

Beacon ID prefix

includeBeaconId("5dc33487f02e477d40", BeaconPicker.BEACON_TYPE_IBEACON)

Scan only beacons of the iBeacon format, whose beacon IDs have, for example, 5dc33487f02e477d40 as the custom prefix.

  • The custom prefix of a beacon ID contains 16 to 40 characters.
  • An app can configure multiple filtering conditions at a time, but in all conditions, there can be no more than two different custom prefixes.

This condition allows an app to scan and discover beacons, without obtaining the message attachment. Therefore, you do not need to configure beacons in AppGallery Connect.

NamespaceType

includeNamespaceType("dev91050203040506", "HMS")

Scan only beacons whose beacon IDs use the default prefix 6bff00f723fdf7471402 and filter beacon messages whose namespace is dev91050203040506 and type is HMS.

  • For details about how to obtain the namespace and type, see Querying an Attachment List.
  • This condition allows an app to scan beacons, discover beacons, and obtain message attachments that meet namespace and type requirements. Therefore, please configure beacons in AppGallery Connect. For details, see Registering a Beacon.

"Beacon ID prefix + NamespaceType"

includeNamespaceType("dev91050203040506", "HMS","5dc33487f02e477d40", BeaconPicker.BEACON_TYPE_IBEACON)

Scan only beacons whose beacon IDs use the custom prefix 5dc33487f02e477d40 and filter beacon messages whose namespace is dev91050203040506 and type is HMS.

When a beacon that meets the condition is discovered, your app will be notified of the beacon via either the Broadcast or Service mode (based on TriggerMode. For details, see setTriggerMode). The following is the sample code for receiving a beacon message:

  • Service mode ("triggerMode = 1")
    public class SampleService extends Service {
        private static final String TAG = "SampleService";
        // 0: A beacon is lost; 1: A beacon is found.
        private static final String KEY_SCAN_ONFOUND_FLAG = "SCAN_ONFOUND_FLAG";
        // Information about the lost or found beacon.
        private static final String KEY_SCAN_BEACON_DATA = "SCAN_BEACON";
        
        private static final String BEACON_NOTIFY_CHANNEL_ID = "beacon_notification_channel_id";
    
        private static final String BEACON_NOTIFY_CHANNEL_NAME = "beacon_notification_channel_name";
    
        private static final int NOTIFICATION_SERVICE_ID = 101;
    
        public SampleService() {
        }
    
        @Override
        public void onCreate() {
            Log.i(TAG, "onCreate");
            new Handler().postDelayed(this::startForeground, 1000);
            super.onCreate();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i(TAG, "onStartCommand");
            startForeground();
            int onFound = intent.getIntExtra(KEY_SCAN_ONFOUND_FLAG, 0);
            Log.i(TAG, "onFound:" + onFound);
    
            // Obtain the beacon information for service processing.
            List<BeaconInfo> beaconList = intent.getParcelableArrayListExtra(KEY_SCAN_BEACON_DATA);
            return super.onStartCommand(intent, flags, startId);
        }
    
        public void startForeground() {
            // The notification bar logic is determined by yourself.
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel channel = new NotificationChannel(BEACON_NOTIFY_CHANNEL_ID,
                        BEACON_NOTIFY_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.createNotificationChannel(channel);
            }
            Notification notification = new NotificationCompat.Builder(this, BEACON_NOTIFY_CHANNEL_ID)
                    // Set the notification icon.
                    .setSmallIcon(R.mipmap.ic_launcher)
                    // Set the notification title.
                    .setContentTitle("Beacon notification")
                    // Set the notification content.
                    .setContentText("A beacon is found.")
                    .setAutoCancel(true)
                    .setOngoing(true)
                    .build();
            // Android versions later than 8.0 do not want apps to run in the background. Therefore, call startForeground() to avoid ANRs or crashes.
            startForeground(NOTIFICATION_SERVICE_ID, notification);
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
  • Broadcast mode ("triggerMode = 2")
    // Register broadcast in the AndroidManifest.xml file.
    <receiver
        android:name="com.demo.SampleReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.huawei.hms.nearby.action.ONFOUND_BEACON" />
        </intent-filter>
    </receiver>
    
    // Define the broadcast receiver.
    public class SampleReceiver extends BroadcastReceiver {
        private static final String TAG = "SampleReceiver";
        private static final String ACTION_SCAN_ONFOUND_RESULT = "com.huawei.hms.nearby.action.ONFOUND_BEACON";
        // 0: A beacon is lost; 1: A beacon is found.
        private static final String KEY_SCAN_ONFOUND_FLAG = "SCAN_ONFOUND_FLAG";
        // Information about the lost or found beacon.
        private static final String KEY_SCAN_BEACON_DATA = "SCAN_BEACON";
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_SCAN_ONFOUND_RESULT.equals(action)) {
                // Obtain the beacon information for service processing.
                int onFound = intent.getIntExtra(KEY_SCAN_ONFOUND_FLAG, 0);
                List<BeaconInfo> beaconList = intent.getParcelableArrayListExtra(KEY_SCAN_BEACON_DATA);
                ...
            }
        }
    }

Estimating Beacon Signal Strength and Distance

A subscriber can estimate its distance from a beacon device based on the strength of the beacon signal associated with the received messages. The sample code is as follows:
MessageHandler mMessageHandler = new MessageHandler() {
    // Called back when the distance change of the target device exceeds 1 meter.
    @Override
    public void onDistanceChanged(Message message, Distance distance) {
       super.onDistanceChanged(message, distance); }
    // Called back when the RSSI change of the target device exceeds 10 dBm.
    @Override
    public void onBleSignalChanged(Message message, BleSignal bleSignal) {     
       super.onBleSignalChanged(message, bleSignal); }
};
// By default, all types of messages are subscribed to. Customize the types of subscribed messages by referring to the API reference.
MessagePicker msgPicker = new MessagePicker.Builder().includeAllTypes().build(); 
Policy policy = Policy.BLE_ONLY; 
GetOption getOption = new GetOption.Builder().setPicker(msgPicker).setPolicy(policy).build(); 
Task<Void> task = Nearby.getMessageEngine(getApplicationContext()).get(mMessageHandler, getOption);
Search
Enter a keyword.