Android AlarmManager實現不間斷輪詢服務

在消息的獲取上是選擇輪詢還是推送得根據實際的業務需要來技術選型,例如對消息實時性比較高的需求,比如微博新通知或新聞等那就最好是用推送了。但如果只是一般的消息檢測比如更新檢查,可能是半個小時或一個小時一次,那用輪詢也是一個不錯的選擇,因爲不需要額外搭建推送服務器,不用額外配置推送服務。另外推送現在一般以維持長連接的方式實現,在手機客戶端也會耗費一定的電量。今天就介紹一個在Android上實現輪詢機制的方法——使用AlarmManager

AlarmManager在Android中主要用來定時處理一個事件或是定期處理一個事件,比如鬧鐘應用就是使用AlarmManager來實現的,我們今天要使用AlarmManager的定期執行功能來實現輪詢的功能。對於定期執行任務也可以用Timer和TimerTask來實現,也可以開一個Service在Thread裏面以while循環來實現。但最好的方案還是選用AlarmManager,這裏涉及一個Android系統鎖的機制,即系統在檢測到一段時間沒有活躍以後,會關閉一些不必要的服務來減少資源和電量消耗。使用Timer和Service來實現的話很可能出現的情況就是屏幕熄滅後一段時間,服務就被停止了,當然輪詢也就被停止了。這個大家可以實驗一下,之前我寫過一篇文章也介紹了一種保持後臺喚醒的機制《使用WakeLock使Android應用程序保持後臺喚醒》,感興趣的可以看看。那麼接下來就開始使用AlarmManager+Service+Thread來實現我們的輪詢服務吧!


一、新建輪詢工具類PollingUtils.java


  1. publicclass PollingUtils {  

  2. //開啓輪詢服務

  3. publicstaticvoid startPollingService(Context context, int seconds, Class<?> cls,String action) {  

  4. //獲取AlarmManager系統服務

  5.        AlarmManager manager = (AlarmManager) context  

  6.                .getSystemService(Context.ALARM_SERVICE);  

  7. //包裝需要執行Service的Intent

  8.        Intent intent = new Intent(context, cls);  

  9.        intent.setAction(action);  

  10.        PendingIntent pendingIntent = PendingIntent.getService(context, 0,  

  11.                intent, PendingIntent.FLAG_UPDATE_CURRENT);  

  12. //觸發服務的起始時間

  13. long triggerAtTime = SystemClock.elapsedRealtime();  

  14. //使用AlarmManger的setRepeating方法設置定期執行的時間間隔(seconds秒)和需要執行的Service

  15.        manager.setRepeating(AlarmManager.ELAPSED_REALTIME, triggerAtTime,  

  16.                seconds * 1000, pendingIntent);  

  17.    }  

  18. //停止輪詢服務

  19. publicstaticvoid stopPollingService(Context context, Class<?> cls,String action) {  

  20.        AlarmManager manager = (AlarmManager) context  

  21.                .getSystemService(Context.ALARM_SERVICE);  

  22.        Intent intent = new Intent(context, cls);  

  23.        intent.setAction(action);  

  24.        PendingIntent pendingIntent = PendingIntent.getService(context, 0,  

  25.                intent, PendingIntent.FLAG_UPDATE_CURRENT);  

  26. //取消正在執行的服務

  27.        manager.cancel(pendingIntent);  

  28.    }  

  29. }  




二、構建輪詢任務執行PollingService.java


  1. publicclass PollingService extends Service {  

  2. publicstaticfinal String ACTION = "com.ryantang.service.PollingService";  

  3. private Notification mNotification;  

  4. private NotificationManager mManager;  

  5. @Override

  6. public IBinder onBind(Intent intent) {  

  7. returnnull;  

  8.    }  

  9. @Override

  10. publicvoid onCreate() {  

  11.        initNotifiManager();  

  12.    }  

  13. @Override

  14. publicvoid onStart(Intent intent, int startId) {  

  15. new PollingThread().start();  

  16.    }  

  17. //初始化通知欄配置

  18. privatevoid initNotifiManager() {  

  19.        mManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  

  20. int icon = R.drawable.ic_launcher;  

  21.        mNotification = new Notification();  

  22.        mNotification.icon = icon;  

  23.        mNotification.tickerText = "New Message";  

  24.        mNotification.defaults |= Notification.DEFAULT_SOUND;  

  25.        mNotification.flags = Notification.FLAG_AUTO_CANCEL;  

  26.    }  

  27. //彈出Notification

  28. privatevoid showNotification() {  

  29.        mNotification.when = System.currentTimeMillis();  

  30. //Navigator to the new activity when click the notification title

  31.        Intent i = new Intent(this, MessageActivity.class);  

  32.        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, i,  

  33.                Intent.FLAG_ACTIVITY_NEW_TASK);  

  34.        mNotification.setLatestEventInfo(this,  

  35.                getResources().getString(R.string.app_name), "You have new message!", pendingIntent);  

  36.        mManager.notify(0, mNotification);  

  37.    }  

  38. /**

  39.     * Polling thread

  40.     * 模擬向Server輪詢的異步線程

  41.     * @Author Ryan

  42.     * @Create 2013-7-13 上午10:18:34

  43.     */

  44. int count = 0;  

  45. class PollingThread extends Thread {  

  46. @Override

  47. publicvoid run() {  

  48.            System.out.println("Polling...");  

  49.            count ++;  

  50. //當計數能被5整除時彈出通知

  51. if (count % 5 == 0) {  

  52.                showNotification();  

  53.                System.out.println("New message!");  

  54.            }  

  55.        }  

  56.    }  

  57. @Override

  58. publicvoid onDestroy() {  

  59. super.onDestroy();  

  60.        System.out.println("Service:onDestroy");  

  61.    }  

  62. }  


三、在MainActivity.java中開啓和停止PollingService



  1. publicclass MainActivity extends Activity {  

  2. @Override

  3. protectedvoid onCreate(Bundle savedInstanceState) {  

  4. super.onCreate(savedInstanceState);  

  5.        setContentView(R.layout.activity_main);  

  6. //Start polling service

  7.        System.out.println("Start polling service...");  

  8.        PollingUtils.startPollingService(this, 5, PollingService.class, PollingService.ACTION);  

  9.    }  

  10. @Override

  11. protectedvoid onDestroy() {  

  12. super.onDestroy();  

  13. //Stop polling service

  14.        System.out.println("Stop polling service...");  

  15.        PollingUtils.stopPollingService(this, PollingService.class, PollingService.ACTION);  

  16.    }  

  17. }  


四、運行效果

運行工程後可以在控制檯輸出看到,每隔5s就發出一個通知,退出Activity時,輪詢服務就停止了,達到了我們事先期望的效果,並且鎖屏後很長一段時間也不會停止服務,因爲AlarmManager是系統及服務。Demo效果如下圖:


SouthEast


在手機上我們可以看到彈出的通知信息,點擊通知則進到消息界面:

SouthEastSouthEastSouthEast


當進入消息詳情Activity時,頂部狀態欄的消息通知就會取消,使用如下方式也可以取消狀態欄頂部的消息通知顯示:


  1. NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);  

  2.        manager.cancelAll();  


以上就實現了使用AlarmManger實現輪詢的一種方式,有不足或缺陷的地方歡迎大家留言補充,以上代碼只是部分,需要工程源碼的同學可以到Github上Clone:https://github.com/tangren03/RTPollingDemo

轉自:http://blog.csdn.net/thinkingdoer/article/details/17102241

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章