原文位址:http://phonepush.sinaapp.com/forum.php?mod=viewthread&tid=6&extra=page%3D1
最近有需要做手機推送方面的項目,本人以前沒做過網絡程式設計也沒做過安卓,是以隻能GOOGLE,發現Androidpn用的比較廣泛,但Androidpn還不成熟,存在一些BUG。
目前比較困擾大家的BUG主要有:
1.當服務端連續發送多條通知時,用戶端都是顯示同一條通知内容。
2.服務端重新開機,用戶端也需要重新開機建立連接配接。
最後還有一個問題當我們伺服器端重新開機的時候,用戶端就無法在連接配接到伺服器了,除非把android背景的服務
關掉,然後重新開機才行.在XmmpManager中加上如下紅色代碼就可:
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 {
//解決伺服器端重新開機後,用戶端不能成功連接配接androidpn伺服器
runTask();
taskList.add(runnable);
}
}
Log.d(LOGTAG, "addTask(runnable)... done");
}
由于沒有經驗,有BUG也隻能繼續GOOGLE,最終發現 http://jclick.iteye.com/blog/1289383 這個TOMCAT版本比較符合項目的需求。在此還是要感謝這位大神,真是造福廣大人民群衆。在這個版本中主要修複了第二個問題,相信很多朋友都已經看過了這篇BLOG ,但是大神在回複中寫錯了類名XMPPWriter,所有導緻大家并不知道問題是怎麼解決的, 其實是修改了org.androidpn.client.XmppManager,org.jivesoftware.smack.PacketWriter(smack源碼)這2個類,這個将他2個版本的代碼比較一下就可以看出來了,廢話了那麼多,在此說一下大神解決此問題的方法。代碼在
http://phonepush.sinaapp.com/forum.php?mod=viewthread&tid=5&extra=page%3D1 篇文章中已經貼出來了。在org.androidpn.client.XmppManager的LoginTask方法中加了一行代碼getConnection().startKeepAliveThread(xmppManager);跟蹤進去發現是開啟了一個線程發送心跳,當發送失敗時捕獲異常,用戶端每隔一段時間進行重連。
org.jivesoftware.smack.PacketWriter的run方法
Java代碼
- catch (SocketException e) {
- Log.e("PacketReader", e.toString());
- connection.disconnect();
- xmppManager.startReconnectionThread();
- } catch (IOException e) {
- e.printStackTrace();
- }
這樣就達到了當與服務端失去連接配接時,用戶端能夠進行重新連接配接的效果。後來群裡有朋友說在LoginTask方法中加入
getConnection().startKeepAliveThread(xmppManager); 編譯就報錯,那是因為他用的是第一個版本 ,所有請先下載下傳第二個版本,第二個版本帶大神精簡過smack源碼。 其實心跳機制在官方的asmack中就已經存在,并且在建立XmppConnection的時候就已經啟動,但是遺憾的是asmack的開發人員并沒有進行異常之後的重連
Java代碼
- catch (Exception e) {
- // Do nothing
- }
所有才出現這個困擾大家的問題。
然後是第二個問題,我們剛才下載下傳的這個版本并沒有處理這個BUG,其實很簡單,群裡的高手經解決,就是将org.androidpn.client.Notifier中的notify方法的
- PendingIntent contentIntent = PendingIntent.getActivity(context, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
複制代碼 改成
- PendingIntent contentIntent = PendingIntent.getActivity(context, random.nextInt(),
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
複制代碼
好了,這2個問題基本上就解決了,本人也隻是在此将前輩們的經驗寫一下,友善大家集中修正BUG。其實在碰到架構BUG時,看看架構的源碼還是有幫助,可能會有很多不解,但我覺得多多少少還是能看出一點東西來。以後大家碰到什麼問題也可以提出來,大家一起研究讨論,集思廣益,總比一個人瞎想的強,有什麼好的想法也可以拿出來分享。再次謝謝各位前輩。
在網上androidpn上的BUG基本都解決了,也多虧牛人們頂力相助,灰常感謝啊。在這裡要說的問題是手機鎖屏後,用戶端心跳包不再發送了。由于android也接觸不是很久,對一些系統的機制不太了解,經過多次測試與分析,才發現了是由于鎖屏後CPU處于睡眠狀态,線程都被挂起,是以在伺服器端設定的閑置時間内收不到心跳包,強制移除使用者下線。
OK問題已經找到了就好辦多了,既然是被挂起了我們就隻有讓心跳一直在跑了,不啰嗦了。既而在網上有找到兩種方法,第一種是讓系統不睡眠,第二種則是使用AlarmManager來做我們的操作,在這裡我是用的第二種方案來解決我們的問題的。但這樣可能有點費電,暫時隻能這樣解決了了,不知道大家有木有更好點的解決辦法能說出來大家一起研究研究。
1).
[java] view plain copy print ?
- //申請裝置電源鎖
- public void acquireWakeLock()
- {
- if (null == mWakeLock)
- {
- PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NotificationService");
- if (null != mWakeLock)
- {
- mWakeLock.acquire();
- }
- }
- }
- //釋放裝置電源鎖
- public void releaseWakeLock()
- {
- if (null != mWakeLock)
- {
- mWakeLock.release();
- mWakeLock = null;
- }
- }
//申請裝置電源鎖
public void acquireWakeLock()
{
if (null == mWakeLock)
{
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NotificationService");
if (null != mWakeLock)
{
mWakeLock.acquire();
}
}
}
//釋放裝置電源鎖
public void releaseWakeLock()
{
if (null != mWakeLock)
{
mWakeLock.release();
mWakeLock = null;
}
}
2).
public void registerAlarmManager(){
am = (AlarmManager)getSystemService(ALARM_SERVICE);
pi = PendingIntent.getBroadcast(this, 0, new Intent(this, HeartActionBroadCast.class), Intent.FLAG_ACTIVITY_NEW_TASK);
long now = System.currentTimeMillis();
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, now, 20000, pi);
}