一步一步开发自各儿的Openfire插件(IOS推送插件APNS)
一步一步开发自己的Openfire插件(IOS推送插件APNS)
使用IOS强大的APNS 和openfire实现IOS推送
开发环境:win7/eclipse/jdk1.6/mysql5.0/openfire3.7
IOS的推送需要用到3个jar包: IOS推送APNS必须的三个包
开发步骤:
源码下载: http://www.igniterealtime.org/downloads/source.jsp
1. 布署openfire3.7源码 部署方法链接: Openfire源代码部署
2. src/plugins目录下新建文件夹push。并按下图的目录结构新建对应的文件。
plugin.xml文件代码如下:
<?xml version="1.0" encoding="UTF-8"?> <plugin> <class>com.d3.push.PushPlugin</class> <name>IOSPush</name> <description>IOS Push</description> <author>mzh</author> <version>1.0.0</version> <date>13/04/2014</date> <minServerVersion>1.0.0</minServerVersion> </plugin>
ChatHistoryInterceptor.java文件代码如下:
package com.d3.push; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javapns.devices.Device; import javapns.devices.implementations.basic.BasicDevice; import javapns.notification.AppleNotificationServerBasicImpl; import javapns.notification.PushNotificationManager; import javapns.notification.PushNotificationPayload; import javapns.notification.PushedNotification; import org.apache.commons.lang.StringUtils; import org.jivesoftware.database.DbConnectionManager; import org.jivesoftware.openfire.PresenceManager; import org.jivesoftware.openfire.XMPPServer; import org.jivesoftware.openfire.interceptor.InterceptorManager; import org.jivesoftware.openfire.interceptor.PacketInterceptor; import org.jivesoftware.openfire.interceptor.PacketRejectedException; import org.jivesoftware.openfire.session.Session; import org.jivesoftware.openfire.user.UserManager; import org.jivesoftware.openfire.user.UserNotFoundException; import org.jivesoftware.util.JiveGlobals; import org.xmpp.packet.JID; import org.xmpp.packet.Message; import org.xmpp.packet.Packet; import org.xmpp.packet.Presence; /** * <b>function:</b> send offline msg plugin * @author MZH */ public class PushInterceptor implements PacketInterceptor{ //Hook for intercpetorn private InterceptorManager interceptorManager; private UserManager userManager; private PresenceManager presenceManager; public PushInterceptor(){ interceptorManager = InterceptorManager.getInstance(); interceptorManager.addInterceptor(this); XMPPServer server = XMPPServer.getInstance(); userManager = server.getUserManager(); presenceManager = server.getPresenceManager(); } /** * intercept message */ @Override public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) throws PacketRejectedException { if (processed || !(packet instanceof Message) || !incoming || Message.Type.chat != ((Message) packet).getType()) return; this.doAction(packet, incoming, processed, session); } /** * <b>send offline msg from this function </b> */ private void doAction(Packet packet, boolean incoming, boolean processed, Session session) { Message message = (Message) packet; JID recipient = message.getTo(); // get message try { // if (recipient.getNode() == null // || !UserManager.getInstance().isRegisteredUser(recipient.getNode())) { // // Sender is requesting presence information of an anonymous // //throw new UserNotFoundException("Username is null"); // } Presence status = presenceManager.getPresence(userManager.getUser(recipient.getNode())); if (status == null) { //offline String deviceToken = getDeviceToken(recipient.getNode()); if(isApple(deviceToken)) pns(deviceToken, message.getBody()); }// end if } catch (UserNotFoundException e) { System.out.println("user not found"); // e.printStackTrace(); } } /** * 判断是否苹果 * @param deviceToken * @return */ private boolean isApple(String deviceToken){ if(deviceToken!=null&&deviceToken.length()>0){ return true; } return false; } public String getDeviceToken(String userId) { String deviceToken = ""; Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement("SELECT code_ios FROM ofUser where username = ?"); pstmt.setString(1, userId); rs = pstmt.executeQuery(); if (rs.next()) { deviceToken = rs.getString(1); } } catch (SQLException e) { e.printStackTrace(); } finally { DbConnectionManager.closeConnection(rs, pstmt, con); } return deviceToken; } public void pns(String token, String msg) { String sound = "default";// 铃音 String certificatePath = JiveGlobals.getProperty("plugin.push.apnsPath",""); String certificatePassword = JiveGlobals.getProperty("plugin.push.apnsKey",""); // 此处注意导出的证书密码不能为空因为空密码会报错 boolean isProduct = JiveGlobals.getBooleanProperty("plugin.push.isProduct", false); try { PushNotificationPayload payLoad = new PushNotificationPayload(); payLoad.addAlert(msg); // 消息内容 payLoad.addBadge(1); // iphone应用图标上小红圈上的数值 if (!StringUtils.isBlank(sound)) { payLoad.addSound(sound);// 铃音 } PushNotificationManager pushManager = new PushNotificationManager(); // true:表示的是产品发布推送服务 false:表示的是产品测试推送服务 pushManager.initializeConnection(new AppleNotificationServerBasicImpl( certificatePath, certificatePassword, isProduct)); // 发送push消息 Device device = new BasicDevice(); device.setToken(token); PushedNotification notification = pushManager.sendNotification( device, payLoad, true); pushManager.stopConnection(); } catch (Exception e) { e.printStackTrace(); } } }
ChatHistoryPlugin.java文件代码如下:
package com.d3.push; import java.io.File; import org.jivesoftware.openfire.container.Plugin; import org.jivesoftware.openfire.container.PluginManager; import org.jivesoftware.openfire.interceptor.InterceptorManager; public class PushPlugin implements Plugin { private PushInterceptor pushInterceptor = null; @Override public void destroyPlugin() { if(pushInterceptor != null){ InterceptorManager.getInstance().removeInterceptor(pushInterceptor); } } @Override public void initializePlugin(PluginManager manager, File pluginDirectory) { pushInterceptor = new PushInterceptor(); InterceptorManager.getInstance().addInterceptor(pushInterceptor); } }
3.打包插件
a.第一次打包需配置ant工具。在环境变量中,
添加 path=C:\Program Files\Java\jdk1.5.0_09\;D:\Program Files\MyEclipse6.5\eclipse\plugins\org.apache.ant_1.7.0.v200706080842\bin (如果原来有path,在变量值的尾部添加半角分号 ; 然后再加入上面的jdk和ant路径 )
b.编译
进入cmd,进入 openfire/build所在目录:输入命令:ant plugins 等待执行完,而且没有报错,说明打包成功。在openfire3.6.3\target\openfire\plugins目录下就生成了push.jar
4.测试
启动openfire ,没有报错,一切OK。
如果是通过源码直接运行,在openfire_src\work\lib 下添加三个apns的包
如果是直接用openfire.exe运行, 在Openfire\lib 下添加三个包 ,然后登陆控制台加入插件push
最后记得在mysql的ofproperty里加入三个参数值
add plugin.push.apnsPathPath , p12文件路径
plugin.push.apnsPathKey, 密码
plugin.push.isProduct to ofProperty 是否正式发布
用户需要有个字段判断是否有token