1

In work and life, when meeting new colleagues or partners, exchanging business cards is a common user demand. Paper business cards are often forgotten and easily lost, which is a pain point for customers. Therefore, there are many APPs and small programs for exchanging electronic business cards on the market. So, how to develop a business card exchange function for your APP?

We can access the Huawei short-range communication service , and quickly realize one-to-one or one-to-many business card exchange through the nearby message subscription (Nearby Message) between devices. The following figure is a functional demonstration:

The specific steps of development are as follows:

1. Development Preparation

If you are already a Huawei developer, you can omit this step. If you have no previous experience in integrating Huawei mobile services, you need to configure AppGallery Connect first, activate the short-distance communication service, and integrate the HMS SDK. For related steps, please refer to official document .

2. Add permissions

Before using Nearby Message, you need to add network permissions, Bluetooth permissions, and location permissions. Add the following permissions to the AndroidManifest.xml file of the project:

<uses-permission android:name="android.permission.INTERNET " />
 <uses-permission android:name="android.permission.BLUETOOTH" />
 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
 <!-- The location permission is also required in Android 6.0 or later. -->
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

3. Code Development

3.1 Dynamic permission application

Check whether the Bluetooth switch and position switch are turned on, whether the network is available, and apply for dynamic permission for location permissions

@Override
 public void onStart() {
     super.onStart();
     getActivity().getApplication().registerActivityLifecycleCallbacks(this);
     checkPermission();
 }
 
 @Override
 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
     for (int i = 0; i < permissions.length; ++i) {
         if (grantResults[i] != 0) {
             showWarnDialog(Constants.LOCATION_ERROR);
         }
     }
 }
 
 private void checkPermission() {
     if (!BluetoothCheckUtil.isBlueEnabled()) {
         showWarnDialog(Constants.BLUETOOTH_ERROR);
         return;
     }
 
     if (!LocationCheckUtil.isLocationEnabled(this.getActivity())) {
         showWarnDialog(Constants.LOCATION_SWITCH_ERROR);
         return;
     }
 
     if (!NetCheckUtil.isNetworkAvailable(this.getActivity())) {
         showWarnDialog(Constants.NETWORK_ERROR);
         return;
     }
 
     String[] deniedPermission = PermissionUtil.getDeniedPermissions(this.getActivity(), new String[] {
             Manifest.permission.ACCESS_COARSE_LOCATION,
             Manifest.permission.ACCESS_FINE_LOCATION
     });
     if (deniedPermission.length > 0) {
         PermissionUtil.requestPermissions(this.getActivity(), deniedPermission, 10);
     }
 }

3.2 Encapsulate business card publishing interface and business card subscription interface

Subscribed to the business card message (onFound), add the business card to the find business card dialog box for display; when the business card message is lost (onLost), delete the business card from the find business card dialog box

private MessageHandler mMessageHandler = new MessageHandler() {
     @Override
     public void onFound(Message message) {
         CardInfo cardInfo = JsonUtils.json2Object(new String(message.getContent(), Charset.forName("UTF-8")),
                 CardInfo.class);
         if (cardInfo == null) {
             return;
         }
 
         mSearchCardDialogFragment.addCardInfo(cardInfo);
     }
 
     @Override
     public void onLost(Message message) {
         CardInfo cardInfo = JsonUtils.json2Object(new String(message.getContent(), Charset.forName("UTF-8")),
                 CardInfo.class);
         if (cardInfo == null) {
             return;
         }
 
         mSearchCardDialogFragment.removeCardInfo(cardInfo);
     }
 };
 
 private void publish(String namespace, String type, int ttlSeconds, OnCompleteListener<Void> listener) {
     Message message = new Message(JsonUtils.object2Json(mCardInfo).getBytes(Charset.forName("UTF-8")), type,
             namespace);
     Policy policy = new Policy.Builder().setTtlSeconds(ttlSeconds).build();
     PutOption option = new PutOption.Builder().setPolicy(policy).build();
     Nearby.getMessageEngine(getActivity()).put(message, option).addOnCompleteListener(listener);
 }
 
 private void subscribe(String namespace, String type, int ttlSeconds, OnCompleteListener<Void> listener,
                        GetCallback callback) {
     Policy policy = new Policy.Builder().setTtlSeconds(ttlSeconds).build();
     MessagePicker picker = new MessagePicker.Builder().includeNamespaceType(namespace, type).build();
     GetOption.Builder builder = new GetOption.Builder().setPolicy(policy).setPicker(picker);
     if (callback != null) {
         builder.setCallback(callback);
     }
     Nearby.getMessageEngine(getActivity()).get(mMessageHandler, builder.build()).addOnCompleteListener(listener);
 }

3.3 Business card exchange menu processing

Face-to-face exchange of business card exchange codes, after successful publishing of personal business cards, subscribe to business card messages

private boolean onExchangeItemSelected() {
     PinCodeDialogFragment dialogFragment = new PinCodeDialogFragment(passwrod -> {
         MyCardFragment.this.publish(passwrod, passwrod, Policy.POLICY_TTL_SECONDS_MAX, result -> {
             if (!result.isSuccessful()) {
                 String str = "Exchange card fail, because publish my card fail. exception: "
                         + result.getException().getMessage();
                 Log.e(TAG, str);
                 Toast.makeText(getActivity(), str, Toast.LENGTH_LONG).show();
                 return;
             }
             MyCardFragment.this.subscribe(passwrod, passwrod, Policy.POLICY_TTL_SECONDS_INFINITE, ret -> {
                 if (!ret.isSuccessful()) {
                     MyCardFragment.this.unpublish(passwrod, passwrod, task -> {
                         String str = "Exchange card fail, because subscribe is fail, exception("
                                 + ret.getException().getMessage() + ")";
                         if (!task.isSuccessful()) {
                             str = str + " and unpublish fail, exception(" + task.getException().getMessage()
                                     + ")";
                         }
 
                         Log.e(TAG, str);
                         Toast.makeText(getActivity(), str, Toast.LENGTH_LONG).show();
                     });
                     return;
                 }
                 mSearchCardDialogFragment.setOnCloseListener(() -> {
                     MyCardFragment.this.unpublish(passwrod, passwrod, task -> {
                         if (!task.isSuccessful()) {
                             Toast.makeText(getActivity(), "Unpublish my card fail, exception: "
                                     + task.getException().getMessage(), Toast.LENGTH_LONG).show();
                         }
                     });
                     MyCardFragment.this.unsubscribe(task -> {
                         if (!task.isSuccessful()) {
                             Toast.makeText(getActivity(), "Unsubscribe fail, exception: "
                                     + task.getException().getMessage(), Toast.LENGTH_LONG).show();
                         }
                     });
                 });
                 mSearchCardDialogFragment.show(getParentFragmentManager(), "Search Card");
             }, null);
         });
     });
     dialogFragment.show(getParentFragmentManager(), "pin code");
 
     return true;
 }

3.4 Collection of business card processing

Add the business card to the favorite list when the business card is favorited, and delete the business card from the parameter list when the business card is unfavored, and save the data to the local storage.

@Override
 public void onFavorite(CardInfo cardInfo, boolean isFavorite) {
     if (isFavorite) {
         mFavoriteMap.put(cardInfo.getId(), cardInfo);
     } else {
         mFavoriteMap.remove(cardInfo.getId());
     }
     Set<String> set = new HashSet<>(mFavoriteMap.size());
     for (CardInfo card : mFavoriteMap.values()) {
         set.add(JsonUtils.object2Json(card));
     }
     SharedPreferences sharedPreferences = getContext().getSharedPreferences("data", Context.MODE_PRIVATE);
     sharedPreferences.edit().putStringSet(Constants.MY_FAVORITES_KEY, set).apply();
 }

The demo we will show you this time uses the message subscription function of Huawei's HMS Nearby service between close-range devices. The ability based on Nearby Message can not only be used to exchange business cards face-to-face, but also help developers implement many interesting functions, such as:

  • Face-to-face team function in competitive mobile games
  • Face-to-face appointment function in chess and card mobile games
  • Near-field AA collection function
  • Music track sharing function

For more details

Visit the official website of Huawei NFC service
Huawei's short-range communication service development guidance document
Huawei NFC open source warehouse address: GitHub , Gitee
Huawei HMS Core official forum
To solve integration problems, please go to Stack Overflow

Follow us and learn about the latest technology of HMS Core for the first time~


HarmonyOS_SDK
596 声望11.7k 粉丝

HarmonyOS SDK通过将HarmonyOS系统级能力对外开放,支撑开发者高效打造更纯净、更智能、更精致、更易用的鸿蒙原生应用,和开发者共同成长。