>伺服器推送技術,目前應用廣泛的大部分都是對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`檔案
apiKey=1234567890 #key
xmppHost=192.168.1.1 #ip
xmppPort=5222 #連接埠
step2:
//建立新的服務
ServiceManager serviceManager = new ServiceManager(this);
//設定通知欄表徵圖
serviceManager.setNotificationIcon(R.drawable.notification);
//啟動服務
serviceManager.startService();
詳細分析
---
初始化ServiceManager:
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()
//用一個線程開啟服務
Thread serviceThread = new Thread(new Runnable() {
@Override
public void run() {
Intent intent = NotificationService.getIntent();
context.startService(intent);
}
});
serviceThread.start();
NotificationService類分析,它是Service的子類,著重分析一下這個Service
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);
}
一切聲明好以後,就開始執行服務了
private void start() {
Log.d(LOGTAG, "start()...");
//註冊通知廣播接收者
registerNotificationReceiver();
//註冊行動電話通訊串連狀態接收者
registerConnectivityReceiver();
// Intent intent = getIntent();
// startService(intent);
//開始與伺服器進行xmpp長連結
//關於XmppManager後面會有分析
xmppManager.connect();
}
XmppManager 管理Xmpp連結:
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();
/* 當xmppManager因異常與伺服器取消連結時
* ReconnectionThread會在一定的時間內嘗試重新串連
* 也就是說,當PersistentConnectionListener監聽器監聽到異常中斷連線
* 會調用ReconnectionThread中重新串連的方法以進行串連嘗試
reconnection = new ReconnectionThread(this);
}
androidpn與伺服器串連流程
---
這裡涉及很多smack包的操作,下篇會分析android下xmpp協議的封裝smack。
_Runable 1: ConnectTask_
與伺服器建立連結
_Runable 1.5: RegisterTask_
如果沒有配置androidpn用戶端的賬戶資訊,它會自動產生一個隨機賬戶並註冊到伺服器
_Runalbe 2: LoginTask_
讀取本地的賬戶資訊,並登入,開始等待伺服器推送訊息