在訊息的擷取上是選擇輪詢還是推送得根據實際的業務需要來技術選型,例如對訊息即時性比較高的需求,比如微博新通知或新聞等那就最好是用推送了。但如果只是一般的訊息檢測比如更新檢查,可能是半個小時或一個小時一次,那用輪詢也是一個不錯的選擇,因為不需要額外搭建推送伺服器,不用額外配置推送服務。另外推送現在一般以維持長串連的方式實現,在手機用戶端也會耗費一定的電量。今天就介紹一個在Android上實現輪詢機制的方法——使用AlarmManager
AlarmManager在Android中主要用來定時處理一個事件或是定期處理一個事件,比如鬧鐘應用就是使用AlarmManager來實現的,我們今天要使用AlarmManager的定期執行功能來實現輪詢的功能。對於定期執行任務也可以用Timer和TimerTask來實現,也可以開一個Service在Thread裡面以while迴圈來實現。但最好的方案還是選用AlarmManager,這裡涉及一個Android系統鎖的機制,即系統在檢測到一段時間沒有活躍以後,會關閉一些不必要的服務來減少資源和電量消耗。使用Timer和Service來實現的話很可能出現的情況就是螢幕熄滅後一段時間,服務就被停止了,當然輪詢也就被停止了。這個大家可以實驗一下,之前我寫過一篇文章也介紹了一種保持後台喚醒的機制《使用WakeLock使Android應用程式保持後台喚醒》,感興趣的可以看看。那麼接下來就開始使用AlarmManager+Service+Thread來實現我們的輪詢服務吧!
一、建立輪詢工具類PollingUtils.java
public class PollingUtils {//開啟輪詢服務public static void startPollingService(Context context, int seconds, Class<?> cls,String action) {//擷取AlarmManager系統服務AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);//封裝需要執行Service的IntentIntent intent = new Intent(context, cls);intent.setAction(action);PendingIntent pendingIntent = PendingIntent.getService(context, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);//觸發服務的起始時間long triggerAtTime = SystemClock.elapsedRealtime();//使用AlarmManger的setRepeating方法設定定期執行的時間間隔(seconds秒)和需要執行的Servicemanager.setRepeating(AlarmManager.ELAPSED_REALTIME, triggerAtTime,seconds * 1000, pendingIntent);}//停止輪詢服務public static void stopPollingService(Context context, Class<?> cls,String action) {AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);Intent intent = new Intent(context, cls);intent.setAction(action);PendingIntent pendingIntent = PendingIntent.getService(context, 0,intent, PendingIntent.FLAG_UPDATE_CURRENT);//取消正在執行的服務manager.cancel(pendingIntent);}}
public class PollingService extends Service {public static final String ACTION = "com.ryantang.service.PollingService";private Notification mNotification;private NotificationManager mManager;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {initNotifiManager();}@Overridepublic void onStart(Intent intent, int startId) {new PollingThread().start();}//初始化通知欄配置private void initNotifiManager() {mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);int icon = R.drawable.ic_launcher;mNotification = new Notification();mNotification.icon = icon;mNotification.tickerText = "New Message";mNotification.defaults |= Notification.DEFAULT_SOUND;mNotification.flags = Notification.FLAG_AUTO_CANCEL;}//彈出Notificationprivate void showNotification() {mNotification.when = System.currentTimeMillis();//Navigator to the new activity when click the notification titleIntent i = new Intent(this, MessageActivity.class);PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i,Intent.FLAG_ACTIVITY_NEW_TASK);mNotification.setLatestEventInfo(this,getResources().getString(R.string.app_name), "You have new message!", pendingIntent);mManager.notify(0, mNotification);}/** * Polling thread * 類比向Server輪詢的非同步線程 * @Author Ryan * @Create 2013-7-13 上午10:18:34 */int count = 0;class PollingThread extends Thread {@Overridepublic void run() {System.out.println("Polling...");count ++;//當計數能被5整除時彈出通知if (count % 5 == 0) {showNotification();System.out.println("New message!");}}}@Overridepublic void onDestroy() {super.onDestroy();System.out.println("Service:onDestroy");}}
public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//Start polling serviceSystem.out.println("Start polling service...");PollingUtils.startPollingService(this, 5, PollingService.class, PollingService.ACTION);}@Overrideprotected void onDestroy() {super.onDestroy();//Stop polling serviceSystem.out.println("Stop polling service...");PollingUtils.stopPollingService(this, PollingService.class, PollingService.ACTION);}}