天天看點

androidpn的學習研究(五)【轉】androidpn-client 常見BUG解決方法

原文位址: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代碼 

  1. catch (SocketException e) {
  2. Log.e("PacketReader", e.toString());
  3. connection.disconnect();
  4. xmppManager.startReconnectionThread();
  5. } catch (IOException e) {
  6. e.printStackTrace();
  7. }

這樣就達到了當與服務端失去連接配接時,用戶端能夠進行重新連接配接的效果。後來群裡有朋友說在LoginTask方法中加入

getConnection().startKeepAliveThread(xmppManager); 編譯就報錯,那是因為他用的是第一個版本 ,所有請先下載下傳第二個版本,第二個版本帶大神精簡過smack源碼。 其實心跳機制在官方的asmack中就已經存在,并且在建立XmppConnection的時候就已經啟動,但是遺憾的是asmack的開發人員并沒有進行異常之後的重連 

Java代碼 

  1. catch (Exception e) {
  2. // Do nothing
  3. }

所有才出現這個困擾大家的問題。

       然後是第二個問題,我們剛才下載下傳的這個版本并沒有處理這個BUG,其實很簡單,群裡的高手經解決,就是将org.androidpn.client.Notifier中的notify方法的

  1. PendingIntent contentIntent = PendingIntent.getActivity(context, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);

複制代碼 改成

  1. PendingIntent contentIntent = PendingIntent.getActivity(context, random.nextInt(),
  2.                     intent, PendingIntent.FLAG_UPDATE_CURRENT);

複制代碼

       好了,這2個問題基本上就解決了,本人也隻是在此将前輩們的經驗寫一下,友善大家集中修正BUG。其實在碰到架構BUG時,看看架構的源碼還是有幫助,可能會有很多不解,但我覺得多多少少還是能看出一點東西來。以後大家碰到什麼問題也可以提出來,大家一起研究讨論,集思廣益,總比一個人瞎想的強,有什麼好的想法也可以拿出來分享。再次謝謝各位前輩。

 在網上androidpn上的BUG基本都解決了,也多虧牛人們頂力相助,灰常感謝啊。在這裡要說的問題是手機鎖屏後,用戶端心跳包不再發送了。由于android也接觸不是很久,對一些系統的機制不太了解,經過多次測試與分析,才發現了是由于鎖屏後CPU處于睡眠狀态,線程都被挂起,是以在伺服器端設定的閑置時間内收不到心跳包,強制移除使用者下線。

      OK問題已經找到了就好辦多了,既然是被挂起了我們就隻有讓心跳一直在跑了,不啰嗦了。既而在網上有找到兩種方法,第一種是讓系統不睡眠,第二種則是使用AlarmManager來做我們的操作,在這裡我是用的第二種方案來解決我們的問題的。但這樣可能有點費電,暫時隻能這樣解決了了,不知道大家有木有更好點的解決辦法能說出來大家一起研究研究。

1).

[java] view plain copy print ?

  1. //申請裝置電源鎖   
  2.     public void acquireWakeLock()  
  3.     {  
  4.         if (null == mWakeLock)  
  5.         {  
  6.             PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);  
  7.             mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NotificationService");  
  8.             if (null != mWakeLock)  
  9.             {  
  10.                 mWakeLock.acquire();  
  11.             }  
  12.         }  
  13.     }  
  14.     //釋放裝置電源鎖   
  15.     public void releaseWakeLock()  
  16.     {  
  17.         if (null != mWakeLock)  
  18.         {  
  19.             mWakeLock.release();  
  20.             mWakeLock = null;  
  21.         }  
  22.     }  
//申請裝置電源鎖
  	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);
    }