這麼遞名片才高效!教你給應用開發個交換名片功能
在工作和生活中,遇見新的同事或者合作伙伴,交換名片是一個常見的使用者需求,紙質名片常忘帶、易丟失,是客戶的一個痛點。因此,市場上出現了很多交換電子名片的APP和小程式。那麼,如何給自己的APP開發一個名片交換功能呢?
我們可以接入華為近距離通訊服務,通過近距離裝置間訊息訂閱(Nearby Message),快速實現一對一或一對多名片交換。下圖是功能演示:
開發具體步驟如下:
1. 開發準備
如果您已經是華為的開發者,可以省略此步驟。如果您以前沒有整合華為移動服務的經驗,那麼需要先配置AppGallery Connect,開通近距離通訊服務並整合HMS SDK。相關步驟請參考官方文件。
2. 新增許可權
在使用Nearby Message之前,需要新增網路許可權、藍芽許可權、位置許可權。在工程的AndroidManifest.xml檔案中新增如下許可權:
<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. 程式碼開發
3.1 動態許可權申請
檢查藍芽開關、位置開關是否開啟、網路是否可用,並對位置許可權進行動態許可權申請
@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 封裝名片釋出介面和名片訂閱介面
訂閱到的名片訊息(onFound),把名片新增到查詢名片對話方塊中顯示;名片訊息丟失時(onLost),從查詢名片對話方塊中刪除該名片
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 名片交換選單處理
面對面交換名片交換碼,釋出個人名片成功後,訂閱名片訊息
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 收藏名片處理
收藏名片時把名片加入收藏列表,名片取消收藏時把名片從引數列表中刪除,並把資料儲存到本地儲存中。
@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();
}
本次給大家演示的demo用到了華為HMS Nearby service的近距離裝置間訊息訂閱功能。基於Nearby Message能力不僅僅可以用來做面對面交換名片,還可以幫助開發者實現很多有趣的功能,例如:
- 競技類手遊中的面對面組隊功能
- 棋牌類手遊中的面對面約局功能
- 近場AA收款功能
- 音樂曲目共享功能
欲瞭解更多詳情
訪問華為近距離通訊服務官網
獲取華為近距離通訊服務開發指導文件
華為近距離通訊服務開源倉庫地址:GitHub、Gitee
華為HMS Core官方論壇
解決整合問題請到Stack Overflow
關注我們,第一時間瞭解HMS Core最新技術~