生也有涯,知也无涯。这篇文章主要讲述这么递名片才高效!教你给应用开发个交换名片功能相关的知识,希望能为你提供帮助。
在工作和生活中,遇见新的同事或者合作伙伴,交换名片是一个常见的用户需求,纸质名片常忘带、易丢失,是客户的一个痛点。因此,市场上出现了很多交换电子名片的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最新技术~
推荐阅读
- 八天让iOS开发者上手Flutter!
- Flutter如何状态管理
- iOS开发面试只需知道这些,技术基本通关!(多线程篇)
- 如何使用JavaScript将文本轻松复制到剪贴板
- 如何在JavaScript中为DOM元素创建自定义事件
- 混淆你的JavaScript,使用户无法阅读
- IntersectionObserver功能(Chrome 51功能,知道特定元素何时处于视口内或视口外)
- 如何覆盖JavaScript中的console方法
- “use strict”是什么(用JavaScript表示)