In work and life, it is a common requirement for users to meet new colleagues or partners and exchange business cards. Paper business cards are often forgotten and easily lost, which is a pain point for customers. As a result, there are many apps and applets for exchanging electronic business cards on the market. So, how to develop a business card exchange function for your APP?

We can access Huawei NFC service and quickly realize one-to-one or one-to-many business card exchange through Nearby Message subscription. Below is a functional demonstration:

The specific development steps are as follows:

1. Development preparation

If you are already a Huawei developer, skip this step. If you have no previous experience in integrating Huawei mobile services, you need to configure AppGallery Connect, open NFC service and integrate HMS SDK first. For details, see the official documentation.

2. Add permissions

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

<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 Android6.0 or later. -->
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Copy the code

3. Code development

3.1 Dynamic Permission Application

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

@Override
 public void onStart(a) {
     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(a) {
     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); }}Copy the code

3.2 Encapsulating business card publishing interface and business card subscription interface

Subscribe to business card message (onFound), add business card to find business card dialog box display; When a 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);
 }
Copy the code

3.3 Business card exchange menu processing

Face to face exchange business card exchange code, issued personal business card after success, subscription business card message

private boolean onExchangeItemSelected(a) {
     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;
 }
Copy the code

3.4 Collecting business cards

Add the name card to the favorites list when you collect the name card, delete the name card from the parameter list when you cancel the favorites, and save the data to 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();
 }
Copy the code

The demo uses huawei HMS Nearby Service to subscribe to messages between devices. The Nearby Message capabilities can not only be used to exchange business cards face to face, but also help developers achieve many interesting functions, such as:

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

For more details

Visit the official website of Huawei NFC service to obtain the guide for developing Huawei NFC service. Open source repository of Huawei NFC service: GitHub and Gitee Huawei HMS Core Forum To resolve integration problems, go to Stack Overflow

Follow us to learn about the latest HMS Core technology