用androidpn来实现推送

真正解决了服务器重启客户端无法连接的bug

android端修改XmppManager这个类

package org.androidpn.client;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Registration;
import org.jivesoftware.smack.provider.ProviderManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Handler;
import android.util.Log;
/**
 * This class is to manage the XMPP connection between client and server.
 * 
 * @author Sehwan Noh (devnoh@gmail.com)
 */
public class XmppManager {
    private static final String LOGTAG = LogUtil.makeLogTag(XmppManager.class);
    private static final String XMPP_RESOURCE_NAME = "AndroidpnClient";
    private Context context;
    private NotificationService.TaskSubmitter taskSubmitter;
    private NotificationService.TaskTracker taskTracker;
    private SharedPreferences sharedPrefs;
    private String xmppHost;
    private int xmppPort;
    private XMPPConnection connection;
    private String username;
    private String password;
    private ConnectionListener connectionListener;
    private PacketListener notificationPacketListener;
    private Handler handler;
    private List<Runnable> taskList;
    private boolean running = false;
    private Future<?> futureTask;
    private Thread reconnection;
    public XmppManager(NotificationService notificationService) {
        context = notificationService;
        taskSubmitter = notificationService.getTaskSubmitter();
        taskTracker = notificationService.getTaskTracker();
        sharedPrefs = notificationService.getSharedPreferences();
        xmppHost = sharedPrefs.getString(Constants.XMPP_HOST, "localhost");
        xmppPort = sharedPrefs.getInt(Constants.XMPP_PORT, 5222);
        username = sharedPrefs.getString(Constants.XMPP_USERNAME, "");
        password = sharedPrefs.getString(Constants.XMPP_PASSWORD, "");
        connectionListener = new PersistentConnectionListener(this);
        notificationPacketListener = new NotificationPacketListener(this);
        handler = new Handler();
        taskList = new ArrayList<Runnable>();
        reconnection = new ReconnectionThread(this);
    }
    public Context getContext() {
        return context;
    }
    public void connect() {
        Log.d(LOGTAG, "connect()...");
        submitLoginTask();
    }
    public void disconnect() {
        Log.d(LOGTAG, "disconnect()...");
        terminatePersistentConnection();
    }
    public void terminatePersistentConnection() {
        Log.d(LOGTAG, "terminatePersistentConnection()...");
        Runnable runnable = new Runnable() {
            final XmppManager xmppManager = XmppManager.this;
            public void run() {
                if (xmppManager.isConnected()) {
                    Log.d(LOGTAG, "terminatePersistentConnection()... run()");
                    xmppManager.getConnection().removePacketListener(
                            xmppManager.getNotificationPacketListener());
                    xmppManager.getConnection().disconnect();
                }
                xmppManager.runTask();
            }
        };
        addTask(runnable);
    }
    public XMPPConnection getConnection() {
        return connection;
    }
    public void setConnection(XMPPConnection connection) {
        this.connection = connection;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public ConnectionListener getConnectionListener() {
        return connectionListener;
    }
    public PacketListener getNotificationPacketListener() {
        return notificationPacketListener;
    }
    public void startReconnectionThread() {
        synchronized (reconnection) {
            if (!reconnection.isAlive()) {
                reconnection.setName("Xmpp Reconnection Thread");
                reconnection.start();
            }
        }
    }
    public Handler getHandler() {
        return handler;
    }
    public void reregisterAccount() {
        removeAccount();
        submitLoginTask();
        runTask();
    }
    public List<Runnable> getTaskList() {
        return taskList;
    }
    public Future<?> getFutureTask() {
        return futureTask;
    }
    public void runTask() {
        Log.d(LOGTAG, "runTask()...");
        synchronized (taskList) {
            running = false;
            futureTask = null;
            if (!taskList.isEmpty()) {
                Runnable runnable = (Runnable) taskList.get(0);
                taskList.remove(0);
                running = true;
                futureTask = taskSubmitter.submit(runnable);
                if (futureTask == null) {
                    taskTracker.decrease();
                }
            }
        }
        taskTracker.decrease();
        Log.d(LOGTAG, "runTask()...done");
    }
    private String newRandomUUID() {
        String uuidRaw = UUID.randomUUID().toString();
        return uuidRaw.replaceAll("-", "");
    }
    private boolean isConnected() {
        return connection != null && connection.isConnected();
    }
    private boolean isAuthenticated() {
        return connection != null && connection.isConnected()
                && connection.isAuthenticated();
    }
    private boolean isRegistered() {
        return sharedPrefs.contains(Constants.XMPP_USERNAME)
                && sharedPrefs.contains(Constants.XMPP_PASSWORD);
    }
    private void submitConnectTask() {
        Log.d(LOGTAG, "submitConnectTask()...");
        addTask(new ConnectTask());
    }
    private void submitRegisterTask() {
        Log.d(LOGTAG, "submitRegisterTask()...");
        submitConnectTask();
        addTask(new RegisterTask());
    }
    private void submitLoginTask() {
        Log.d(LOGTAG, "submitLoginTask()...");
        submitRegisterTask();
        addTask(new LoginTask());
    }
    private void addTask(Runnable runnable) {
        Log.d(LOGTAG, "addTask(runnable)...");
        taskTracker.increase();
        synchronized (taskList) {
            if (taskList.isEmpty() && !running) {
                running = true;
                futureTask = taskSubmitter.submit(runnable);
                if (futureTask == null) {
                    taskTracker.decrease();
                }
            } else {
            
             taskList.add(runnable);
            }
        }
        Log.d(LOGTAG, "addTask(runnable)... done");
    }
    private void removeAccount() {
        Editor editor = sharedPrefs.edit();
        editor.remove(Constants.XMPP_USERNAME);
        editor.remove(Constants.XMPP_PASSWORD);
        editor.commit();
    }
    /**
     * A runnable task to connect the server. 
     */
    private class ConnectTask implements Runnable {
        final XmppManager xmppManager;
        private ConnectTask() {
            this.xmppManager = XmppManager.this;
        }
        public void run() {
            Log.i(LOGTAG, "ConnectTask.run()...");
            if (!xmppManager.isConnected()) {
                // Create the configuration for this new connection
                ConnectionConfiguration connConfig = new ConnectionConfiguration(
                        xmppHost, xmppPort);
                // connConfig.setSecurityMode(SecurityMode.disabled);
                connConfig.setSecurityMode(SecurityMode.required);
                connConfig.setSASLAuthenticationEnabled(false);
                connConfig.setCompressionEnabled(false);
                XMPPConnection connection = new XMPPConnection(connConfig);
                xmppManager.setConnection(connection);
                try {
                    // Connect to the server
                    connection.connect();
                    Log.i(LOGTAG, "XMPP connected successfully");
                    // packet provider
                    ProviderManager.getInstance().addIQProvider("notification",
                            "androidpn:iq:notification",
                            new NotificationIQProvider());
                } catch (XMPPException e) {
                    Log.e(LOGTAG, "XMPP connection failed", e);
                }
                xmppManager.runTask();
            } else {
                Log.i(LOGTAG, "XMPP connected already");
                xmppManager.runTask();
            }
        }
    }
    /**
     * A runnable task to register a new user onto the server. 
     */
    private class RegisterTask implements Runnable {
        final XmppManager xmppManager;
        private RegisterTask() {
            xmppManager = XmppManager.this;
        }
        public void run() {
            Log.i(LOGTAG, "RegisterTask.run()...");
            if (!xmppManager.isRegistered()) {
                final String newUsername = newRandomUUID();
                final String newPassword = newRandomUUID();
                Registration registration = new Registration();
                PacketFilter packetFilter = new AndFilter(new PacketIDFilter(
                        registration.getPacketID()), new PacketTypeFilter(
                        IQ.class));
                PacketListener packetListener = new PacketListener() {
                    public void processPacket(Packet packet) {
                        Log.d("RegisterTask.PacketListener",
                                "processPacket().....");
                        Log.d("RegisterTask.PacketListener", "packet="
                                + packet.toXML());
                        if (packet instanceof IQ) {
                            IQ response = (IQ) packet;
                            if (response.getType() == IQ.Type.ERROR) {
                                if (!response.getError().toString().contains(
                                        "409")) {
                                    Log.e(LOGTAG,
                                            "Unknown error while registering XMPP account! "
                                                    + response.getError()
                                                            .getCondition());
                                }
                            } else if (response.getType() == IQ.Type.RESULT) {
                                xmppManager.setUsername(newUsername);
                                xmppManager.setPassword(newPassword);
                                Log.d(LOGTAG, "username=" + newUsername);
                                Log.d(LOGTAG, "password=" + newPassword);
                                Editor editor = sharedPrefs.edit();
                                editor.putString(Constants.XMPP_USERNAME,
                                        newUsername);
                                editor.putString(Constants.XMPP_PASSWORD,
                                        newPassword);
                                editor.commit();
                                Log
                                        .i(LOGTAG,
                                                "Account registered successfully");
                                xmppManager.runTask();
                            }
                        }
                    }
                };
                connection.addPacketListener(packetListener, packetFilter);
                registration.setType(IQ.Type.SET);
                // registration.setTo(xmppHost);
                // Map<String, String> attributes = new HashMap<String, String>();
                // attributes.put("username", rUsername);
                // attributes.put("password", rPassword);
                // registration.setAttributes(attributes);
                registration.addAttribute("username", newUsername);
                registration.addAttribute("password", newPassword);
                connection.sendPacket(registration);
            } else {
                Log.i(LOGTAG, "Account registered already");
                xmppManager.runTask();
            }
        }
    }
    /**
     * A runnable task to log into the server. 
     */
    private class LoginTask implements Runnable {
        final XmppManager xmppManager;
        private LoginTask() {
            this.xmppManager = XmppManager.this;
        }
        public void run() {
            Log.i(LOGTAG, "LoginTask.run()...");
            if (!xmppManager.isAuthenticated()) {
                Log.d(LOGTAG, "username=" + username);
                Log.d(LOGTAG, "password=" + password);
                try {
                    xmppManager.getConnection().login(
                            xmppManager.getUsername(),
                            xmppManager.getPassword(), XMPP_RESOURCE_NAME);
                    Log.d(LOGTAG, "Loggedn in successfully");
                    // connection listener
                    if (xmppManager.getConnectionListener() != null) {
                        xmppManager.getConnection().addConnectionListener(
                                xmppManager.getConnectionListener());
                    }
                   
                    // packet filter
                    PacketFilter packetFilter = new PacketTypeFilter(
                            NotificationIQ.class);
                    // packet listener
                    PacketListener packetListener = xmppManager
                            .getNotificationPacketListener();
                    connection.addPacketListener(packetListener, packetFilter);
                  //判断是否处于连接状态(添加)
                    if(!getConnection().isConnected())
                   {
                    xmppManager.runTask();
                   }
                    xmppManager.runTask();
                } catch (XMPPException e) {
                    Log.e(LOGTAG, "LoginTask.run()... xmpp error");
                    Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: "
                            + e.getMessage());
                    String INVALID_CREDENTIALS_ERROR_CODE = "401";
                    String errorMessage = e.getMessage();
                    if (errorMessage != null
                            && errorMessage
                                    .contains(INVALID_CREDENTIALS_ERROR_CODE)) {
                        xmppManager.reregisterAccount();
                        return;
                    }
                    xmppManager.startReconnectionThread();
                } catch (Exception e) {
                    Log.e(LOGTAG, "LoginTask.run()... other error");
                    Log.e(LOGTAG, "Failed to login to xmpp server. Caused by: "
                            + e.getMessage());
                    xmppManager.startReconnectionThread();
                }
              //添加
            xmppManager.runTask();
            
            } else {
                Log.i(LOGTAG, "Logged in already");
                xmppManager.runTask();
            }
        }
    }
}

新添加代码344-348行和369行

1.运行客户端代码,需要注意的是把androidpn.properties中的xmppHost改为你的服务器ip地址

2.服务端 jdbc.properties修改mysql数据库连接

项目部署(服务器)

首先,我单独启动一个新的tomcat,将server端部署到这下面,修改配置文件config。properties,jdbc.properties。jdbc.properties这个文件是配置你本地数据库的参数的,不能有错。启动后,简单测试成功,在自己项目中使用http协议将数据POST到server端这个org.androidpn.server.console.controller.NotificationController类的send方法中。具体参数名称及获取参数的代码,可以修改server端。基本上,写到这里的话,应该可以满足项目需求了。如果你还需要将哪些用户在线的功能整合到你自己项目中。那你就得自己跟踪下代码了。

apiKey默认1234567890为了安全在config.properties里修改

NotificationController.java代码

/*
 * Copyright (C) 2010 Moduad Co., Ltd.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
package org.androidpn.server.console.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.androidpn.server.util.Config;
import org.androidpn.server.xmpp.push.NotificationManager;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
/** 
 * A controller class to process the notification related requests.  
 *
 * @author Sehwan Noh (devnoh@gmail.com)
 */
public class NotificationController extends MultiActionController {
    private NotificationManager notificationManager;
    public NotificationController() {
        notificationManager = new NotificationManager();
    }
    public ModelAndView list(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        ModelAndView mav = new ModelAndView();
        // mav.addObject("list", null);
        mav.setViewName("notification/form");
        return mav;
    }
    public ModelAndView send(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String broadcast = ServletRequestUtils.getStringParameter(request,
                "broadcast", "Y");
        String username = ServletRequestUtils.getStringParameter(request,
                "username");
        String title = ServletRequestUtils.getStringParameter(request, "title");
        String message = ServletRequestUtils.getStringParameter(request,
                "message");
        String uri = ServletRequestUtils.getStringParameter(request, "uri");
        String apiKey = Config.getString("apiKey", "");
        logger.debug("apiKey=" + apiKey);
        if (broadcast.equalsIgnoreCase("Y")) {
            notificationManager.sendBroadcast(apiKey, title, message, uri);
        } else {
            notificationManager.sendNotifcationToUser(apiKey, username, title,
                    message, uri);
        }
        ModelAndView mav = new ModelAndView();
        mav.setViewName("redirect:notification.do");
        return mav;
    }
}




参考博文:

真正解决了服务器重启客户端无法连接的bug

http://www.cnblogs.com/cnblogs-lin/archive/2012/04/28/AndroidXmpp.html

源码分析

http://www.cnblogs.com/sunzn/archive/2013/02/04/2891390.html

 

 

都是用myeclipse构建的

只有tomcat

http://www.iteye.com/topic/1117043

jetty和tomcat

http://mobile.51cto.com/aprogram-403300.htm

myeclipse发布对应关系

 

 

本文出自 “点滴积累” 博客,请务必保留此出处http://tianxingzhe.blog.51cto.com/3390077/1653717

时间: 2024-08-03 13:14:32

用androidpn来实现推送的相关文章

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

前面几篇给大家系统讲解的有关xmpp openfire smack asmack相关的技术和使用,大家如果有所遗忘可以参考 基于xmpp openfire smack开发之openfire介绍和部署[1] 基于xmpp openfire smack开发之smack类库介绍和使用[2] 基于xmpp openfire smack开发之Android客户端开发[3]   顺便也一起回顾下xmpp的历程 xmpp协议起源于著名的Linux即时通讯服务服务器jabber,有时候我们会把xmpp协议也叫j

怎样使用android客户端的消息推送开源包androidpn。

问题描述 怎样使用android客户端的消息推送开源包androidpn. 下载了androidpn 的server和client 0.5.0的版本,具体怎么部署,客户端怎么实现,服务端怎么实现呢,最好有实际经验的朋友帮忙解答一下.非常感谢.

Android下实现信息推送

最近有幸负责参与开发公司的CMPP短信网关程序,采用的是Apache Mina框架实现.通过该项目对Socket通 信.长连接有了更深一步的理解,于是就想试试将Mina用到Android平台的信息推送上.经过了解发现,目前 已经有不少成型的框架能够实现Android平台的信息推送,特别是AndroidPn. 平时我们开发手机客户 端,都少不了要于服务器交互,那么当服务器端有新的数据时,客户端是怎么知道的呢?一般可以采用如下两 种方式来实现: 1)客户端定期(每隔一段时间,轮询)向服务器发起请求,

mqtt推送介绍

方案1.使用GCM服务(Google Cloud Messaging)简介:Google推出的云消息服务,即第二代的C2DM.优点:Google提供的服务.原生.简单,无需实现和部署服务端.缺点:Android版本限制(必须大于2.2版本),该服务在国内不够稳定.需要用户绑定Google帐号,受限于Google. 方案2.使用XMPP协议(Openfire + Spark + Smack)简介:基于XML协议的通讯协议,前身是Jabber,目前已由IETF国际标准化组织完成了标准化工作.优点:协

Android、iOS和Windows Phone中的推送技术

推送并不是什么新技术,这种技术在互联网时代就已经很流行了.只是随着进入移动互联网时代,推送技术显得更加重要.因为在智能手机中,推送从某种程度上,可以取代使用多年的短信,而且与短信相比,还可以向用户展示更多的信息(如图像.表格.声音等). 推送技术的实现通常会使用服务端向客户端推送消息的方式.也就是说客户端通过用户名.Key等ID注册到服务端后,在服务端就可以将消息向所有活动的客户端发送. 实际上,在很多移动操作系统中,官方都为其提供了推送方案,例如,Google的云推送.IOS.Windows 

Android实现推送方式解决方案

原文:http://www.cnblogs.com/hanyonglu/archive/2012/03/04/2378971.html 本文介绍在Android中实现推送方式的基础知识及相关解决方案.推送功能在手机开发中应用的场景是越来起来了,不说别的,就我们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息.这种推送功能是好的一面,但是也会经常看到很多推送过来的垃圾信息,这就让我们感到厌烦了,关于这个我们就不能多说什么了,毕竟很多商家要做广告.本文就是来探讨下Andro

Android推送通知指南

在开发Android和iPhone应用程序时,我们往往需要从服务器不定的向手机客户端即时推送各种通知消息,iPhone上已经有了比较简单的和完美的推送通知解决方案,可是Android平台上实现起来却相对比较麻烦,最近利用几天的时间对Android的推送通知服务进行初步的研究. 在Android手机平台上,Google提供了C2DM(Cloudto Device Messaging)服务,起初我就是准备采用这个服务来实现自己手机上的推送功能. Android Cloud to Device Mes

Android 服务器推送技术

  在开发Android和iPhone应用程序时,我们往往需要从服务器不定的向手机客户端即时推送各种通知消息,iPhone上已经有了比较简单的和完美的推送通知解决方案,可是Android平台上实现起来却相对比较麻烦,最近利用几天的时间对Android的推送通知服务进行初步的研究. 在Android手机平台上,Google提供了C2DM(Cloudto Device Messaging)服务,起初我就是准备采用这个服务来实现自己手机上的推送功能. Android Cloud to Device M

推送 从入门到放弃

推送 推送简直就是一种轻量级的骚扰方式 自从有了推送,各个公司基本上都在使用推送,这确实是一个比较好的提醒方式,Android较iOS强的一个部分,也就是在于Android的Notification.Google教育我们利用好Android的通知模块,做更多友好的交互,可这句话,翻译成中文,不知不觉,就变成了在Notification中推送各种广告,而且仅仅就是一些广告,Notification各种牛逼的功能,完全不需要,这也违背了Google设计Notification的初衷. 更关键的是,现