日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4]

發(fā)布時間:2023/12/4 Android 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4] 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

http://blog.csdn.net/shimiso/article/details/8156439

前面幾篇給大家系統(tǒng)講解的有關(guān)xmpp openfire smack asmack相關(guān)的技術(shù)和使用,大家如果有所遺忘可以參考

順便也一起回顧下xmpp的歷程

xmpp協(xié)議起源于著名的Linux即時通訊服務(wù)服務(wù)器jabber,有時候我們會把xmpp協(xié)議也叫jabber協(xié)議,其實這是不規(guī)范的,xmpp是個協(xié)議,而jabber是個服務(wù)器,因為jabber開源,設(shè)計精良,安全,穩(wěn)定,跨語言,跨平臺,封裝開發(fā)簡便,越來越多人開始使用它,并且逐步完善,不久它便形成了一個強大的標準化體系,Google?GTalk、Pidgin、PSI、Spark、Pandion、MSN、Yahoo、ICQ..諸如此類一些軟件在這個強大的標準體系下實現(xiàn)了互聯(lián).那么XMPP到底是什么意思,用通俗的話講它和基于xml格式的一些協(xié)議原理差不多,只不過是個針對服務(wù)器的軟件協(xié)議罷了。

那么在java領(lǐng)域是否存在一個類似jabber那么強大開源穩(wěn)定的也完美支持xmpp協(xié)議的服務(wù)器呢?答案有的,那便是openfire,openfire是純java開發(fā)的基于XMPP的協(xié)議,目前最終版本鎖定在了2011年openfire?3.7,它一共有l(wèi)inux?windows?mac?三個版本,安裝也非常簡單,openfire這個服務(wù)器是個開放式的平臺,它內(nèi)部集成的服務(wù)包括即時通訊服務(wù),會議室服務(wù),用戶安全驗證和管理服務(wù),搜索服務(wù),組織機構(gòu)服務(wù),會話服務(wù),這幾大服務(wù)都有相應(yīng)的管理類和對外接口,它的二次開發(fā)和擴展都是在插件基礎(chǔ)上直接嫁接進去的,早期有很多第三方為他做了插件,有語音服務(wù),red5視頻服務(wù),郵件服務(wù)等等,語音和視頻在openfire上一直是個雞肋,沒有非常好的解決方案,而做這些插件的大部分都停止更新,大家如果選用openfire做視頻和語音還要慎重!拋開這些插件,openfire在IM及時通訊上還是相當強大穩(wěn)定的,不少公司拿它來做二次開發(fā)!但即便如此openfire的二次開發(fā)成本還是比較高昂的,筆者曾經(jīng)成功費了九牛二虎之力將源碼環(huán)境搭建起來,并成功將它與我們JAVAEE?經(jīng)典架構(gòu)SSH成功組裝,用openfire的桌面客戶端spark軟件和android開源xmpp客戶端Beam軟件,web端聊天軟件Claros?Chat享受了一把在自己服務(wù)器上“隨時隨地聊天”,不過這些都是實驗階段,距離成熟可用還很遠!研究技術(shù)可以這么勾兌嘗試,真的給人用可不能這么隨意,我們還是要挖掘真正對我們有用的價值!

openfire過于龐大繁復,許多對我們來說都是沒什么用的,甚至要砍掉改造,能不能有精簡的xmpp服務(wù)器呢?答案是有的,androidpn,筆者認真比對過openfire和androidpn的源碼,最后驚奇的發(fā)現(xiàn),原來它就是從openfire里面庖丁解牛出來的一部分,做這件事的人非常的了不起,為我們省了很大力氣,在此感謝他的開源和共享精神,那么androidpn分離出來的是消息推送服務(wù),簡言之就是從服務(wù)端向android客戶端推送消息的服務(wù),因為openfire的源碼架構(gòu)是在jetty基礎(chǔ)上建立的,它的啟動和部署方式和我們傳統(tǒng)的服務(wù)器tomcat和weblogic等有點區(qū)別,所以androidpn也有jetty的影子,在和我們傳統(tǒng)架構(gòu)組合的時候還要再把它和jetty拆開,?androidpn的搭建和使用網(wǎng)上的教程很多,大家可以發(fā)現(xiàn)大部分千篇一律,出現(xiàn)一個OK界面就沒了,堂而皇之的寫上原創(chuàng),有的只是改了下hello?world,如此糊弄,實在難為所用!


androidpn消息推送采用的是apache的mina框架做的,服務(wù)端和客戶端兩邊都有監(jiān)聽,也就是我們所說的socket編程,有人說socket編程有什么難的,就那么回事,其實不然,我們平時寫的socket聊天都只是在局域網(wǎng)的,但是要穿透路由和防火墻,讓信息安全及時的傳送到另一個網(wǎng)關(guān)的局域網(wǎng)電腦中,就不是一件簡單的活了,其中涉及到在nat上打洞,還有線程,斷網(wǎng)重連,安全加密等等,那么androidpn配合mina相當于把這些活都干了,那么我們要的干活就相對比較精細了,第一學習mina的安裝配置的規(guī)則,第二學習xmpp協(xié)議組裝和解析的規(guī)則,第三學習androidpn推和收消息的核心代碼,如此三點我們便能靈活駕馭住androidpn出現(xiàn)再大的問題自己也能動手去調(diào)了。


在和spring整合的時候大家要注意不要讓mina服務(wù)啟動2次,筆者整合時候無意發(fā)現(xiàn)在linux64位系統(tǒng),weblogic上啟動時候總是報5222已經(jīng)被占用,反復查看代碼發(fā)現(xiàn)mina在隨web容器啟動過一次5222端口后,xmppserver類中的start方法中ClassPathXmlApplicationContext類又加載了一次spring配置,導致端口被重復開啟兩次,最后終于發(fā)現(xiàn)問題所在:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> <context:component-scan base-package="org.androidpn.server.*" /><!-- 自動裝配 --> <!-- =============================================================== --> <!-- Resources --> <!-- =============================================================== --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> </list> </property> </bean> <!-- =============================================================== --> <!-- Data Source --> <!-- =============================================================== --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbcDriverClassName}" /> <property name="url" value="${jdbcUrl}" /> <property name="username" value="${jdbcUsername}" /> <property name="password" value="${jdbcPassword}" /> <property name="maxActive" value="${jdbcMaxActive}" /> <property name="maxIdle" value="${jdbcMaxIdle}" /> <property name="maxWait" value="${jdbcMaxWait}" /> <property name="defaultAutoCommit" value="true" /> </bean> <!-- sessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> </bean> <!-- 配置事務(wù)管理器 --> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> <property name="dataSource" ref="dataSource" /> </bean> <!-- 采用注解來管理事務(wù)--> <tx:annotation-driven transaction-manager="txManager" /> <!-- spring hibernate工具類模板 --> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- spring jdbc 工具類模板 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource"> <ref bean="dataSource" /> </property> </bean> <!-- =============================================================== --> <!-- SSL --> <!-- =============================================================== --> <!-- <bean id="tlsContextFactory" class="org.androidpn.server.ssl2.ResourceBasedTLSContextFactory"> <constructor-arg value="classpath:bogus_mina_tls.cert" /> <property name="password" value="boguspw" /> <property name="trustManagerFactory"> <bean class="org.androidpn.server.ssl2.BogusTrustManagerFactory" /> </property> </bean> --> <!-- MINA --> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.net.SocketAddress"> <bean class="org.apache.mina.integration.beans.InetSocketAddressEditor" /> </entry> </map> </property> </bean> <bean id="xmppHandler" class="org.androidpn.server.xmpp.net.XmppIoHandler" /> <bean id="filterChainBuilder" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder"> <property name="filters"> <map> <entry key="executor"> <bean class="org.apache.mina.filter.executor.ExecutorFilter" /> </entry> <entry key="codec"> <bean class="org.apache.mina.filter.codec.ProtocolCodecFilter"> <constructor-arg> <bean class="org.androidpn.server.xmpp.codec.XmppCodecFactory" /> </constructor-arg> </bean> </entry> <!-- <entry key="logging"> <bean class="org.apache.mina.filter.logging.LoggingFilter" /> </entry> --> </map> </property> </bean> <bean id="ioAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor" init-method="bind" destroy-method="unbind" scope="singleton"> <property name="defaultLocalAddress" value=":5222" /> <property name="handler" ref="xmppHandler" /> <property name="filterChainBuilder" ref="filterChainBuilder" /> <property name="reuseAddress" value="true" /> </bean> <bean id="serviceLocator" class="org.androidpn.server.service.ServiceLocator" scope="singleton" /> <!-- Services--> <bean id="userService" class="org.androidpn.server.service.impl.UserServiceImpl"/> <bean id="notificationService" class="org.androidpn.server.service.impl.NotificationServiceImpl"/> </beans>

配置serviceLocator是為了保證spring容器只能由一個上下文,也就是spring容器只被啟動一次,我們將BeanFactory交給了serviceLocator,這樣一來有什么好處呢?

控制層,服務(wù)層,數(shù)據(jù)庫操作層都受spring管理,在他們中去跟spring要資源,一定是要什么有什么想怎么拿就怎么拿,都很方便,但是如果想在沒有被spring所管理的類中去拿spring的資源,動作就不那么優(yōu)雅了,有人建議用ClassPath加載器初始化spring工廠來獲取資源,問題就處在這里,這種做法必定會產(chǎn)生2個spring上下文,一個是web容器所啟動的,一個是java類加載器所啟動的,我們的MINA服務(wù)器也就被啟動了2次,其實資源被重復多次實例化除了影響性能外,對程序影響可能并不大,但是MINA被啟動2次,肯定會出問題的。為保證spring只有一個上下文,我們將容器上下文交給了serviceLocator,脫離spring管控的環(huán)境可以面向serviceLocator來調(diào)度spring中的資源操作MINA服務(wù)器。

package org.androidpn.server.service; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; public class ServiceLocator implements BeanFactoryAware { private static BeanFactory beanFactory = null; private static ServiceLocator servlocator = null; public static String USER_SERVICE = "userService"; public static String NOTIFICATION_SERVICE = "notificationService"; public void setBeanFactory(BeanFactory factory) throws BeansException { this.beanFactory = factory; } public BeanFactory getBeanFactory() { return beanFactory; } public static ServiceLocator getInstance() { if (servlocator == null) servlocator = (ServiceLocator) beanFactory.getBean("serviceLocator"); return servlocator; } /** * 根據(jù)提供的bean名稱得到相應(yīng)的服務(wù)類 * * @param servName * bean名稱 */ public static Object getService(String servName) { return beanFactory.getBean(servName); } /** * 根據(jù)提供的bean名稱得到對應(yīng)于指定類型的服務(wù)類 * * @param servName * bean名稱 * @param clazz * 返回的bean類型,若類型不匹配,將拋出異常 */ public static Object getService(String servName, Class clazz) { return beanFactory.getBean(servName, clazz); } /** * Obtains the user service. * * @return the user service */ public static UserService getUserService() { return (UserService) getService(USER_SERVICE); } public static NotificationService getNotificationService() { return (NotificationService) getService(NOTIFICATION_SERVICE); } } 在config.properties中還要特別注意xmpp.resourceName必須跟客戶端中XmppManager的private?static?final?String?XMPP_RESOURCE_NAME?=?"AndroidpnClient";保持一致,否則連不上服務(wù)器,還xmpp.session.maxInactiveInterval=-1表示永不中斷,如果設(shè)定了時間超過這個時間范圍沒有任何活動就會自動斷開,這里的時間單位全部是毫秒。

apiKey=1234567890 xmpp.ssl.storeType=JKS xmpp.ssl.keystore=conf/security/keystore xmpp.ssl.keypass=changeit xmpp.ssl.truststore=conf/security/truststore xmpp.ssl.trustpass=changeit xmpp.resourceName=AndroidpnClient ##Added by ken username=admin password=admin #資源名稱 resource_name=AndroidpnClient #校驗超時時間間隔 xmpp.session.checkTimeoutInterval=10000 #Session timeout最大非活動時間間隔 xmpp.session.maxInactiveInterval=1000000

在androidpn.properties中端口和IP不要寫錯,有人喜歡寫localhost,在手機上是無法識別的,必須寫絕對IP地址。

apiey=1234567890

xmppHost=192.168.1.78

xmppPort=5222

?

運行結(jié)果如下:





離線消息也支持,先給離線用戶發(fā)個消息,效果如下:


在數(shù)據(jù)庫中我們看到有一條離線消息是發(fā)給用戶4aa50dde313f4b63907c2430bf00b413,status為0標記為離線


這時我們再上線,大約等待20秒左右,查看系統(tǒng)控制臺打印:


查看android端看看用戶4aa50dde313f4b63907c2430bf00b413上線情況:


這時候數(shù)據(jù)庫記錄發(fā)生了變化,status變成了2,表示已經(jīng)接收,用戶點擊OK的時候,它又變成了3表示已經(jīng)查看


離線消息的原理相對比較簡單,當系統(tǒng)給指定用戶發(fā)送消息時候,會首先判斷用戶是夠在線,如果在線就直接發(fā)送,如果沒有在線就暫時標記保存,等用戶上線時候先查離線消息然后彈出,其實整個項目都是開源的,可能唯一的難點就是對MINA和XMPP協(xié)議的不了解,再加上本身對socket和多線程的畏懼,如果這些全部都掌握,駕馭好這套源碼還是很有信心的,了解其基本原理以后,我們就可以放心的做更多的擴展。

?????????網(wǎng)上現(xiàn)在也有不少androidpn版本,五花八門什么都有,里面到底有沒問題,改了什么沒改什么都不知道,基本上已經(jīng)追溯不到原創(chuàng)到底是誰了,索性就只能從國外的一個網(wǎng)站上下了一個比較可靠的版本自己動手去量身改造,終于出了一個比較穩(wěn)定版本。對于消息提醒來說,它僅僅是個notification,許多人非要把業(yè)務(wù)數(shù)據(jù)也做進去,更有夸張好幾兆的xml數(shù)據(jù)就這么硬塞提醒過去,這種做法本身就背離了設(shè)計的初衷,非要把跑車當牛車使能不出問題嗎?其實業(yè)務(wù)數(shù)據(jù)還是用http拉比較好,xmpp及時的前提是用資源消耗作為代價的,我們能適度就適度用,用好用穩(wěn)就行!


項目源碼下載:?Androidpn威力加強版(4月17日更新)

下載地址:http://download.csdn.net/detail/shimiso/5267500

項目

總結(jié)

以上是生活随笔為你收集整理的Android之基于xmpp openfire smack开发之Android消息推送技术原理分析和实践[4]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 97超碰97| 美女扒开让男人桶爽 | 在线观看黄色大片 | 激情噜噜| 风间由美在线视频 | 国产综合在线播放 | 国产视频www| 熟女精品一区二区三区 | 国产精品人妻 | 亚洲性天堂| 99久久精品一区二区成人 | 老熟女毛茸茸浓毛 | 成人在线观看免费 | 乌克兰做爰xxxⅹ性视频 | 一级做a爱片久久 | 欧美乱码精品一区二区 | 中文字幕一区二区三区不卡 | 在线视频91| 国产卡一卡二 | 日本特级毛片 | 在线播放毛片 | 国产又粗又猛又黄又爽无遮挡 | 亚洲一页| 一级黄色录像大片 | 国产剧情av在线播放 | 最新永久地址 | 中文字幕乱码人妻一区二区三区 | 日本一区二区三区免费看 | 亚洲精品视频观看 | 黑人高潮一区二区三区在线看 | 成人无码精品1区2区3区免费看 | 精品成人在线 | 日日躁狠狠躁 | 18在线观看免费入口 | 波多野结衣一区二区三区四区 | 黄色福利在线观看 | 国产精品无套 | 色偷偷资源网 | 性色浪潮 | 1000部啪啪| 日韩精品成人 | 久久这里 | 天天干天天摸天天操 | 日本h漫在线观看 | 亚洲一二三av | 天天干,天天干 | www四虎影院| 亚洲黄色免费视频 | 精品久久久久久久久久久久久久久久久久 | 臭脚猛1s民工调教奴粗口视频 | 久久久国产免费 | 四虎综合 | 国产综合无码一区二区色蜜蜜 | 红桃视频一区二区三区免费 | 亚洲中文字幕一区在线 | 都市激情校园春色 | 亚洲网友自拍 | 国产日韩精品在线 | 美女扒开腿让男人 | 久草中文视频 | 制服丝袜国产在线 | 性做久久 | 97视频总站 | 亚洲av无码乱码国产精品fc2 | 伊人久久一区二区 | 免费99精品国产自在在线 | 国产第一毛片 | 日本欧美一本 | 日韩av免费在线看 | 涩涩网站视频 | 超碰超碰97| 国产免费一级视频 | 天天摸天天操天天射 | 亚洲av无码日韩精品影片 | 精品婷婷色一区二区三区蜜桃 | 好看的中文字幕电影 | 51嘿嘿嘿国产精品伦理 | 91中文视频| 在线观看一二三区 | 99国产精品久久久久久久成人热 | 91高潮大合集爽到抽搐 | 精品亚洲成人 | 日韩欧美网址 | 女人扒开腿免费视频app | 岛国大片在线 | 在线观看av免费 | 精品久久久久久久久久久久久久久久久久 | 国产福利视频一区二区 | 一本色道久久综合亚洲精品图片 | 五月天激情开心网 | 综合av第一页| 亚洲欧美自拍偷拍 | 国产三级网 | 99热3| 成人免费毛片糖心 | 影音先锋亚洲天堂 | 国产偷人妻精品一区 | 欧美成年人在线视频 | 葵司一区二区 |