基于AndroidPN的消息推送应用

AndroidPN的入门

  1. 推送方案介绍
    1、常见的推送应用:软件更新 + 商家推送的消息
    2、邮件到达的提示消息
  2. 推送方式:
    1、Push(推模式):服务端向客户端发送
    2、Pull(拉模式):客户端向服务端请求
  3. 常见的推送方案
    基于XMPP的协议的Androidpn

Androidpn框架搭建

xmpp + Spring + Hibernate + SpringMVC + Ehcache + mina

  1. 服务端的修改
    1、修改相应的配置文件:
    ①、jdbc.properties:数据库连接的基本属性信息
    ②、config.properties:服务器配置的相关信息(ip + 默认端口号(5222))——修改成本地IP
admin.console.host=127.0.0.1    //设置成本地的IP
admin.console.port=7070     //端口号可以不修改

③、hibernate.cfg.xml:数据库连接的信息——修改连接数据库的信息(与jdbc.properties文件有冗余,最好两个都修改下)

<!-- Database connection settings -->
<property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="hibernate.connection.url">jdbc:hsqldb:db/androidpn;shutdown=true</property>
<property name="hibernate.connection.username">sa</property>
<property name="hibernate.connection.password"/>

<!-- SQL dialect -->
<property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>

注意:数据库androidpn必须提前先创建
Mapping_info + 用于初始过程反向生成table:User(启动时会创建的表格信息)

//hibernate.cfg.xml文件
<mapping class="org.androidpn.server.model.User"/>

修改好后就可以/bin/run.bat运行服务器了(注意run.bat中要配置了正确的JAVA_HOME)

但是这样修改后倒入MyEclipse运行服务器还是会报这样一个错误:Cannot load jdbc driver class…,原因是我们修改了Androidpn原来的服务器的数据库编程自己使用的MySQL,因此要倒入自己的sqljdbc.jar包导入到lib中
之后再运行即可:http://loclahost:7070
这里写图片描述

  1. Androidpn客户端修改
    1、修改res/row/androidpn.properties文件中客户端和服务器请求的Host和Port
xmppHost=192.168.0.5    //修改成自己的本机
xmppPort=5222   //如果这个客户端端口要修改的话则要在服务端/config/spring-config.xml文件
<property name="defaultLocalAddress" value=":5222"/>

2、修改后运行有可能会出错:Link of class … fail
找不到链接依赖的库(这有可能是SDK版本不一样,lib目录变成了libs目录),将lib改成libs目录后先删除错误依赖的jar包后再重新导入即可。

修改成功后,即可运行,实现服务端向客户端信息的推送

但是有以下几点地方是要修改的
1、服务端推送了多条消息,点开后显示的都只是最后一条推送的消息,这是客户端接收的问题
2、如何集成到现有的web项目
3、数据库不一样该怎么修改
4、加入使用的框架不是SSH,该如何改动
5、发送自定义的消息包

将androidpn_server改进成Tomcat web项目

androidpn-Server src目录介绍
1. Maven构建环境(Androidpn的实现是基于Maven的)
2. Androidpn_server包含了三个工程:Server + Console + Starter
3. Maven导入Androidpn常见的问题

将 androidpn-Server该进程Tomcat web项目

  1. Androidpn使用的服务器是jetty而不是Tomcat,因此如果自己的项目是使用tomcat作为服务器的时候,就应该改进Tomcat
    1、项目框架构建:Hiberate + Spring + SpringMVC
    2、WEB CONTENT:赋值Console web文件 +Web.xml.schema声明方式
    3、Resourses:配置文件
    4、整合src代码:Console、Server

  2. 可能会引入的问题:lib引入的问题(从源码中拷贝 + 数据库驱动包)
    1、包冲突
    2、找不到XXX包

  3. 改进过程中涉及到的问题
    1、Hiberate + Spring + SpringMVC的项目相关配置
    2、通讯端口:默认是5222,如果是企业的话有专门的网络管理
    3、server/src/main/java/org目录下的源码的中全部代码拷到自己的项目中去 + server/src/main/sresources配置文件(多了conf.security配置文件) + 将要引用的库放到WEB_INF/lib目录下 + console下的org + starter代码
    4、引入jar包是不要引入与jetty相关的包(jasper + jetty不用)

  4. 将 androidpn-Server该进程Tomcat web项目总结
    1、首先Androidpn采用的服务器是jetty,如果使用Tomcat做服务器的话就要移除或者屏蔽jetty的相关配置信息,添加Tomcat的配置信息(libm目录的Spring、Hibernate、SpringMVC)
    2、Androidpn的实现框架的话是基于Maven的,如果使用SSH作为项目框架的话也要修改相应的配置文件信息(Web.xml、Spring.xml、hibernate.cfg.xml、conf.properties)
    4、Androidpn服务器默认的数据库是HSQLDB,如果采用的是MySQL数据库的话则要添加相应的jar包和修改连接数据库的相应信息(jdbc.properties、MySQL.jar)。
    5、以及重要类库的改动:XmppServer.java与UI路径的改动

Androidpn体系结构和消息推送流程分析

Androidpn概述

  1. androidpn是一个基于xmpp开源组件的一个整合方案
    1、服务端:openfire + apache mina
    2、客户端:基于smack的asmack
  2. 技术支持
    1、Spring + Hibernate + SpringMVC
    2、socket + Thread + XML

androidpn消息推送流程

  1. 建立连接(XMPP + XML)
  2. 服务端消息推送
  3. 客户端接收和显示
  4. 客户端发送消息

Server端代码结构
dao + model + service + util(加载resource中的配置文件) + xmpp(推送的核心包,入口类为XmppServer,用来启动和停止Server程序)

  1. server.xmpp包结构说明
    1、auth:认证信息类,可以扩展认证模块(自定义自己的认证方式)
    2、codec:xmpp协议的xml文件解析包,server收发消息通过此包进行编码和解码(可自定义自己的编码和解码规则)
    3、handler:消息处理(根据自己的消息类型定义自己的消息handler)
    4、net:负责客户端与服务端持久的连接
    5、presence:用来维护客户端的在线状态(PresenceManager)
    6、push:服务端向客户端发送消息(NotificationManager)
    7、router:将受到的消息包发送到相应的Handler进行处理
    8、session:定义了用来表示持久链接的session,每个session包含了一条连接的状态信息
    9、ssl(Socket security layer):连接进行ssl认证的工具包

关于apache mina

xmpp包含的两个核心:Apache mina +
核心:Socket的连接管理以及通信的IO操作

  1. Apache mina涉及到的类
    1、 Socket的连接管理
    2、I/OServer:负责实际的IO操作
    3、I/O Filter Chain:IO操作中设计到数据的加密、编码、压缩等
    4、. IO Handler(apace mina的应用层):负责实际的业务逻辑处理,这是开发人员要关注的(实现的类为XMPPHandler)
  2. Apache mina 实现的基本流程
    1、IOAcceptor监听客户端的连接
    2、连接成功后创建一个Session
    3、Session接收到数据后过滤器
    4、最后将数据交给handler处理

Androidpn客户端的Asmack

  1. Asmack的简单介绍
    1、smack:基于XMPP协议的及时通信客户端编程库(J2EE)
    2、Asmack:smack库的Android版本 + 基于xmpp协议与服务器端的Socket连接
  2. 客户端服务器之间通信流程图解
    这里写图片描述

Androidpn 客户端执行流程
client主要包括消息的收发、解析以及持久连接的发起

  1. 涉及到的类
    1、XmppManager:主控制器,业务逻辑的核心代码,NotificationService通过这个类,在后台维护与服务器的连接
    2、Notifier:客户端发送通知的类
    3、ServiceManager:管理消息服务和加载相关配置
    4、NotificationSettingActivity:推送消息页面设置的类
    。。。

  2. Androidpn客户端执行的流程
    1、创建服务ServiceManager
    在构造方法中读取配置文件的信息(XMPP连接的主机啊、IP啊、Activity的类名啊,用于回调)并保存在sharePreference中,下次的的话就不用再读取配置文件而直接从sp中取就行了
    2、启动服务

        Thread serviceThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Intent intent = NotificationService.getIntent();
                context.startService(intent);
            }
        });
        serviceThread.start();
  1. androidpn客户端涉及到的任务
    1、涉及到连接的任务ConnectTask
    这里写图片描述
    2、注册和登录任务:RegisterTask + LoginTask
    这里写图片描述
    3、客户端接收/发送消息流程
    ①、NotificationPacketListener
    做的事情有:
    一直坚挺从服务器发送过来的数据包Packet
    重复执行数据包的解析:NotificationIQ(客户端现有的消息结构:id、apiKey、title、message、uri)——Intent
    发送广播:sendBroadcast给NotificationReceiver
    ②:NotificationReceiver的onReceive方法接收广播
    ③:notificationDetailActivity回发消息
    封装消息成IQ
    XMPPConnection的sendPacket方法回发消息
  2. Server发送消息流程
    1、NotificationManager的push接口被调用
    ①使用Sessionanager 在当前session集合中查找相应的client连接
    ②XMPP消息格式
    2、通过相应的Session,想Client发送消息
  3. Server接收消息的流程
    1、connection收到packet,使用codec解码消息
    2、router根据packet的namespace信息,将packet路由到相应的handler
    3、handler进行处理

Androidpn的不足地方及修改
1、服务器重启,客户端如何重新连接
2、消息处理
①、服务器收到消息后如果知道要发给哪个
②、服务器如何保存消息
③、消息如何跟踪:用户是否收到消息、用户是否读取消息
④、客户端离线如何处理消息

Androidpn服务端发送自定义消息

(androidpn服务器端自定义消息及消息处理流程)
(客户端XmppManager类中的三个线程(连接、注册和登录三个任务)与服务器端交互)
各种消息的处理

  1. 连接以及消息发送的数据处理
    1、客户端请求连接的时候用创建Session对象保存客户端的相关连接信息
    2、接收客户端发送过来的XML消息,之后交给StanzaHandler类中的process方法用于处理XML消息
    3、XML消息处理完之后将是数据的发送处理,该数据为一个raw数据
  2. Login消息的处理
    登录时首先要判断是否有该用户,没有则启动RegisterTaste任务线程
  3. IQRegisterHandler处理
    用户注册成功,则将数据保存在
  4. 客户端close的消息处理
    当客户端服务stop的时候向服务器发送“不可用消息”

消息包的结构(xml文件)
(会在stanzaHandler中处理)

<stream>
    <presence>              // 用户状态
        </show>        
    </presence>
    <message to='foo'>
        <body/>
    </message>              // 用户发送的消息
    <iq to=bar'>            //iq:信息/请求(认证信息 + 注册信息+ 联系人列表roster,Androidpn中没有写,要自己实现)
        </query>
    </iq>
</stream>

简单的业务应用

  1. 应用场景
    电信给客户经理推送工单信息
    工单信息包含有工单的各种状态
  2. 需求
    客户经理收集客户端要分别收到:
    ①各种状态的工单数目
    ②各种不同状态需要不同的通知图片
    ③通过通知进入不同攻打状态的UI进行处理
  3. 解决方案
    消息包的扩展和处理

服务器端的消息处理
NotificationManager.createNotificationIQ + 自定义封装IQ + 在用到这个函数的地方也要改(sendXXX)

//在这里扩展成自己的数据类型,使用如下代码来添加新的XML元素:notification.addElement("uri").setText(uri);
   private IQ createNotificationIQ(String apiKey, String title,
            String message, String uri) {
        Random random = new Random();
        String id = Integer.toHexString(random.nextInt());
        // String id = String.valueOf(System.currentTimeMillis());

        Element notification = DocumentHelper.createElement(QName.get(
                "notification", NOTIFICATION_NAMESPACE));
        notification.addElement("id").setText(id);
        notification.addElement("apiKey").setText(apiKey);
        notification.addElement("title").setText(title);
        notification.addElement("message").setText(message);
        notification.addElement("uri").setText(uri);

        IQ iq = new IQ();
        iq.setType(IQ.Type.set);
        iq.setChildElement(notification);

        return iq;
    }

自定义编码解码的扩展
自定义用户验证的扩展
IQRegisterHandler:用户信息的扩展
IQAuthHandler:用户验证信息扩展
IQRosterHandler:所有用户 + 所有在线/离线用户扩展

Androidpn客户端自定义消息和逻辑处理

消息处理:
(添加消息 + 修改消息的XML解析 +监听消息的到达并封装成实体类NotificationIQ,并广播 + 广播后NotificationReceiver.onReceive中接收并且通过Notifier.notify方法显示在通知栏 + 点击通知栏后再NotificationDetailActivity.onCreate中显示)
1. 自定义消息时需要定义的3个类
1、xxIQ定义消息的实体
2、xxIQProvider将消息转化为xxIQ实体
3、对实体进行处理
2. 具体的实现可参考如下三个类:
1、NotificationIQ:extendsIQ,消息实体
2、NotificationIQProvider:parseIQ,封装IQ,将接收的xml数据转换成实体
3、NotificationPacketListener:IQ处理
①将IQ数据存入到Intent数据中
②将intent数据广播出去:xmppManager.getContext().sendBradcast(intent)
4、之后广播的消息由NotificationReceiver类中的onRecevier方法接收,其中会调用Notify与Notification类建立起关联关系

消息处理:注册

  1. 在XmppServerManager中注册,参考如下三个类
    1、LoginTask:NotificationIQ + NotificationPacketListene
    2、ConnectTask:NotificationIQProvider

应用扩展:用户

  1. 用户注册信息:XmppManager.RegisterTask—IQRegister
  2. 用户登录验证:XmppManager.LoginTask—IQAuthHandler
  3. 用户好友列表:IQRosterHandler

Android客户端的改进

通讯机制的改进
1. 关于心跳处理(Socket)
2. 服务器掉线重连(现有的客户端在服务器停止后不会重连)
3. Wakeup lock
4. 用户验证改进
5. 网络选择:WiFi—3G、GPRS

通知服务的改进
(后台运行的服务)
1. 开机启动服务
2. 退出程序:退出或不退出服务

通知消息的改进

  1. 通知各种消息模式
    1、保存最后一条消息
    2、所有消息
    3、消息归类
  2. 通知回写服务器(现有的Androidpn服务端对客户端已阅读的消息没有回写,需改进)
  3. 自定义通知UI

xmpp客户端asmack源码可能要改动,下载源码替代原来的jar包XMPPConnection对象)

XMPPConnection:创建连接XMPP服务器的Socket对象
(服务端使用mima,实际上是对socket连接的管理)

  1. sendPacket方法:发送消息包
    还有建立连接的方法(匿名连接 + 提供用户密码的连接 )
  2. startKeepAliveThread:保持长连接的机制

XMPPManager

  1. ConnetTask:负责连接服务器的线程(服务器主机、端口、连接安全的配置、connect()发起连接),最后将任务加入到任务嘟列钟来
    1、如果没有连接到服务器,程序会从sp中读取服务器主机ip和端口号,并使用XMPPConnection通过配置信息实例化一个连接对象向服务器发起连接;连接成功调用XMPPManager runTask方法来执行之前添加到任务集合中的任务RegisterTask,同时TaskTracker计数减一
  2. LoginTask
    先登录,但是要有连接、其次是要有注册
  3. RegisterTask
    线程管理:线程池

客户端服务器的连接

  1. 长连接机制
  2. 心跳机制
    1/按需来发送信息,而不是时刻都与服务器保持连接
    2、SmackConfiguration:keepAliveInterval= 30000(30秒),即每个30秒通信一次,发送一个空的字符
    3、如果发送失败,则作为异常处理:重新连接(自己修改代码)
    4、数据包超时响应的时间:packetReplyTimeout
    5、客户端不能重连:服务端重启或晚于客户端启动 +网络类型的切换

综上所述,改进为:
1、登录之后保持长连接或者心跳连接
2、客户端重连

通讯建立

  1. 通知服务:NotificationService类
  2. 按需服务管理
    开机启动服务:booterReceiver广播接收器,把开机的广播接收器交给ServiceManager,
    • 程序退出方式:退出程序后是否关闭服务
  3. 普通优先级的service会在系统资源不够的时候,会被自动回收(kill)

关于程序休眠
如果保持长时间待机时,程序休眠问题引起通讯不正常,wake_lock

通讯安全的改进

  1. 用户注册:
    1、添加用户注册信息
    2、设备ID最为用户的唯一ID
    3、后台管理记录设备ID(绑定用户)
    4、参考Google Map API
  2. 验证改进:多终端用户 + 单一终端用户

服务端消息通知
(不覆盖 + 分类)
1. 原来的Androidpn消息通知问题
1、当服务端连续发送多跳消息是,客户端都只显示同一条消息内容
2、当服务端连续发送多跳消息是,客户端都只显示各自的通知内容

  1. 改进:
    requestCode :表示通知的不同类型
  2. PendingIntent

消息的回发

  1. 客户端收到通知后告诉服务器
  2. 如何改进:
    1、回发动作:收到通知回发给服务器NotificationPacketListener收到消息后向服务器会送一个IQ消息,如果服务端没有收到该消息,则请求重发
    2、阅读完消息之后怎么做:已读消息的回发

自定义通知的UI

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值