如何在Smack 4.2中注册设备令牌?实现离线/后台推送通知
嘿,我来帮你搞定Smack 4.2里的设备令牌注册,同时实现你要的两种通知场景——离线/应用终止时的推送,以及后台在线时通过IQ获取通知。
在Smack 4.2中注册设备令牌并实现双场景通知
一、注册设备令牌到Ejabberd服务器
首先得把设备的推送令牌(比如FCM/APNs令牌)通过Smack传给Ejabberd,让服务器知道该设备的推送通道。这里我们用自定义IQ请求来实现,适配Ejabberd的处理逻辑。
步骤1:定义自定义IQ类封装令牌数据
public class PushTokenIQ extends IQ { public static final String ELEMENT = "push-token"; public static final String NAMESPACE = "urn:xmpp:push:token"; private String token; private String platform; // 标记是"fcm"还是"apns" public PushTokenIQ() { super(ELEMENT, NAMESPACE); } @Override protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) { xml.rightAngleBracket(); xml.element("token", token); xml.element("platform", platform); return xml; } // Getter & Setter public String getToken() { return token; } public void setToken(String token) { this.token = token; } public String getPlatform() { return platform; } public void setPlatform(String platform) { this.platform = platform; } }
步骤2:连接成功后发送令牌到服务器
// 假设你已经通过FCM获取到了设备令牌 String fcmDeviceToken = "你的FCM令牌字符串"; PushTokenIQ pushTokenIQ = new PushTokenIQ(); pushTokenIQ.setType(IQ.Type.set); pushTokenIQ.setTo("你的ejabberd服务器域名"); // 比如"your-server.com" pushTokenIQ.setToken(fcmDeviceToken); pushTokenIQ.setPlatform("fcm"); // 获取已建立的Smack连接 AbstractXMPPConnection xmppConnection = getYourActiveSmackConnection(); // 发送IQ并监听结果 xmppConnection.sendIqWithResponseCallback(pushTokenIQ, stanza -> { IQ response = (IQ) stanza; if (response.getType() == IQ.Type.result) { Log.d("SmackPush", "设备令牌注册成功!"); } else { Log.e("SmackPush", "令牌注册失败: " + response.getError().getMessage()); } }, exception -> Log.e("SmackPush", "发送令牌出错: " + exception.getMessage()) );
二、实现离线/应用终止时的推送通知
当设备离线或应用被杀死时,Ejabberd需要把离线消息转发到你的推送服务(比如FCM)。这一步需要在Ejabberd服务器上配置推送模块,同时客户端处理推送回调。
服务器端配置(Ejabberd.yml)
确保启用推送相关模块,并配置FCM/APNs的服务信息:
modules: mod_push: {} mod_push_keepalive: {} mod_offline: store_messages: true push_notifications: true # 开启离线消息转推送 mod_push: backend: ejabberd_push push_service: fcm: api_key: "你的FCM服务器密钥" endpoint: "https://fcm.googleapis.com/fcm/send"
客户端处理FCM推送
在Android的FirebaseMessagingService中接收并展示通知:
public class MyFirebaseMsgService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { Map<String, String> pushData = remoteMessage.getData(); String sender = pushData.get("from"); String msgContent = pushData.get("body"); // 构建并显示本地通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "XMPP_PUSH_CHANNEL") .setSmallIcon(R.drawable.ic_notification) .setContentTitle("来自" + sender) .setContentText(msgContent) .setPriority(NotificationCompat.PRIORITY_HIGH); NotificationManagerCompat.from(this).notify((int) System.currentTimeMillis(), builder.build()); } }
三、应用后台时通过IQ获取实时通知
当应用在后台但Smack连接仍活跃时,我们可以监听服务器发送的自定义IQ来获取通知,避免依赖推送延迟。
步骤1:定义IQ监听器处理通知
public class BackgroundNotificationListener implements StanzaListener { @Override public void processStanza(Stanza stanza) throws SmackException.NotConnectedException, InterruptedException { if (!(stanza instanceof IQ)) return; IQ notificationIQ = (IQ) stanza; // 匹配服务器发送的通知IQ的命名空间和元素名 if (notificationIQ.getType() == IQ.Type.set && "notification".equals(notificationIQ.getChildElementName()) && "urn:xmpp:notification:0".equals(notificationIQ.getChildElementNamespace())) { // 解析通知内容 String msgBody = notificationIQ.getChildElement().getFirstChildElement("body").getText(); String fromUser = notificationIQ.getFrom().toString(); // 在后台显示本地通知 showBackgroundNotification(fromUser, msgBody); } } private void showBackgroundNotification(String from, String content) { // 这里的逻辑和FCM推送的通知构建一致 NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), "XMPP_IQ_CHANNEL") .setSmallIcon(R.drawable.ic_notification) .setContentTitle("后台通知:" + from) .setContentText(content) .setPriority(NotificationCompat.PRIORITY_DEFAULT); NotificationManagerCompat.from(getApplicationContext()).notify((int) System.currentTimeMillis(), builder.build()); } }
步骤2:注册监听器到Smack连接
AbstractXMPPConnection xmppConnection = getYourActiveSmackConnection(); // 添加同步监听器,只监听IQ类型的Stanza xmppConnection.addSyncStanzaListener(new BackgroundNotificationListener(), new StanzaTypeFilter(IQ.class));
几个关键注意点
- 后台要保持Smack连接稳定:可以启用
ReconnectionManager自动重连,避免连接断开导致收不到IQ通知。 - 服务器端的自定义IQ要和客户端匹配:确保命名空间、元素名完全一致,否则监听器会过滤掉消息。
- 通知渠道要提前创建:Android 8.0+需要先创建通知渠道才能显示通知。
内容的提问来源于stack exchange,提问作者Rajesh Gauswami
相关产品推荐
相关产品推荐

