服务器推送技术,目前应用广泛的大部分都是对xmpp协议的在此封装。 没接触过xmpp?在linux用一些im客户端,默认都会让你添加支持xmpp协议的账户,比如icq、msn等等,另外,不都说qq也是基于xmpp的么,包括android下gmail、gtalk等等也都是基于xmpp协议的。 下面对android下服务器推送技术的一个封装androidpn进行简单的分析,以后还会对xmpp协议的android封装smack进行分析学习。 androidpn也是构建与xmpp协议之上,好在它把服务端与客户端都进行了封装,很容易使用与扩展,提高了很多开发人员的效率,这也是选择它最好的理由。
step1:配置客户端
位于工程->res->raw->androidpn.properties
文件
1 2 3 | apiKey= 1234567890 #key xmppHost= 192.168 . 1.1 #ip xmppPort= 5222 #端口 |
step2:
1 2 3 4 5 6 | //创建新的服务 ServiceManager serviceManager = new ServiceManager( this ); //设置通知栏图标 serviceManager.setNotificationIcon(R.drawable.notification); //启动服务 serviceManager.startService(); |
初始化ServiceManager:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | this .context = context; //这里获取调用者activity得包名类名 if (context instanceof Activity) { Log.i(LOGTAG, "Callback Activity..." ); Activity callbackActivity = (Activity) context; callbackActivityPackageName = callbackActivity.getPackageName(); callbackActivityClassName = callbackActivity.getClass().getName(); } //loadProperties()读取raw中androidpn.properties文件的内容,并返回Properties对象 props = loadProperties(); apiKey = props.getProperty( "apiKey" , "" ); xmppHost = props.getProperty( "xmppHost" , "127.0.0.1" ); xmppPort = props.getProperty( "xmppPort" , "5222" ); //将上面获取的Properties存入SharedPreferences方便以后直接调用 sharedPrefs = context.getSharedPreferences( Constants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); Editor editor = sharedPrefs.edit(); ... ... ... editor.commit(); |
启动服务startService()
1 2 3 4 5 6 7 8 9 | //用一个线程开启服务 Thread serviceThread = new Thread( new Runnable() { @Override public void run() { Intent intent = NotificationService.getIntent(); context.startService(intent); } }); serviceThread.start(); |
NotificationService类分析,它是Service的子类,着重分析一下这个Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public NotificationService() { /*NotificationReceiver为BroadcastReceiver的子类 *用于接收推送广播并用NotificationManager通知用户 *也就是系统通知栏的通知 */ notificationReceiver = new NotificationRece /*ConnectivityReceiver接收手机网络状态的广播 *来管理xmppManager与服务器的连接与断开 */ connectivityReceiver = new ConnectivityReceiver(this); /*集成于android.telephony.PhoneStateListener, *同上,用于监听数据链接的状态 */ phoneStateListener = new PhoneStateChangeListener(this); //线程池 executorService = Executors.newSingleThreadExecutor(); /*TaskSubmitter类包含了向上面的线程池提交一个Task任务 *的方法 */ taskSubmitter = new TaskSubmitter(this); /*任务计数器 *用以维护当前工作的Task */ taskTracker = new TaskTracker( this ); } |
一切声明好以后,就开始执行服务了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private void start() { Log.d(LOGTAG, "start()..." ); //注册通知广播接收者 registerNotificationReceiver(); //注册手机网络连接状态接收者 registerConnectivityReceiver(); // Intent intent = getIntent(); // startService(intent); //开始与服务器进行xmpp长链接 //关于XmppManager后面会有分析 xmppManager.connect(); } |
XmppManager 管理Xmpp链接:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | public XmppManager(NotificationService notificationService) { context = notificationService; //获取Task提交管理器,这里用于维护并行任务 taskSubmitter = notificationService.getTaskSubmitter(); //Task的计数器 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, "" ); /*设置xmpp链接状态的监听器,查看代码发现Xmpp链接状态有5种 * 1 connectionClosed * 2 connectionClosedOnError * 3 reconnectingIn * 4 reconnectionFailed * 5 reconnectionSuccessful */ connectionListener = new PersistentConnectionListener(this); /* 服务器推送监听器 * 服务器如果有消息推送,NotificationPacketListener会 * 自己解析好,并通过XmppManager发送广播 */ notificationPacketListener = new NotificationPacketListener( this ); //当xmpp因异常重新连接服务器时,这期间发生异常的话,会在这个handler中处理 handler = new Handler(); //任务队列 taskList = new ArrayList<Runnable>(); /* 当xmppManager因异常与服务器断开链接时 * ReconnectionThread会在一定的时间内尝试重新连接 * 也就是说,当PersistentConnectionListener监听器监听到异常断开连接 * 会调用ReconnectionThread中重新连接的方法以进行连接尝试 reconnection = new ReconnectionThread( this ); |
联系客服