Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 用android的GCM 網絡管理來優化電池使用時間

用android的GCM 網絡管理來優化電池使用時間

編輯:關於Android編程

?GCM網絡管理器能讓app注冊能執行面向網絡的服務,每個任務只是完成一個工作。它的API能處理這些任務,允許Google Play Services通過系統集中處理這些網絡操作。
?它的API有助於簡化通用的網絡模式,比如說等待網絡連接,網絡重聯和回退等。實事上,GCM網絡管理器通過直觀的API允許開發者更加有精力關注具體的功能實現,少一點精力去關心網絡的問題。

電池使用與網絡訪問的關系

?在介紹GCM網絡管理器之前,我們花點精力來認識一下電池與網絡請求的利害關系,這樣我們才能明白為什麼批處理網絡這麼重要。
?這裡有張Android無線電狀態機的圖表
這裡寫圖片描述
?這已經很直觀了,我用這張圖表來加固對處理網絡連接的時候喚醒radio是一個巨大消耗的過程的這個概念。本身嘛,調用網絡就是一個對電量的有巨大消耗的操作。
?即使沒有單一的網絡任務可以消耗完電量,但是大量的個別的可以喚醒radio的網絡請求就可以。如果網絡請求彼此分開,然後設備伴隨著radio的打開被喚醒,因為電池的消耗被喚醒的設備不能休眠(就像睡不戳的人一樣)。
?下面的這圖表展示網絡請求來處一個獲取圖片的app,這個app叫PhotoGallery
這裡寫圖片描述
?好吧,單個請求看起來不是太壞,radio是打開了,但也只是一個請求,是吧?
?下面這張圖顯示的多個網絡調用:
這裡寫圖片描述
?突然我們有了大量的網絡請求,radio會被每個請求快速喚醒,這樣會很消耗掉電量,而導致極其不好的用戶體驗。
?我們可以批處理網絡請求來節約電量,主要是優化喚醒radio的消耗。如果在radio的生命同期中最消耗的是初始化喚醒階段,那麼我們就只需要通過批處理來只喚醒一次就好了。這個方法適合不立即需要數據的情況,預加載吧。
?下面這個圖表就是反批處理網絡請求的:
這裡寫圖片描述
?現在這個radio就只被喚醒一次,節約了電量。
?但是有的時候你確實馬上就需要網絡請求,比如你正在打游戲或者發送一個消息。對於這些情況來說,你應該做一個普通的網絡請求,但是,請注意這種類型的網絡請求並不能優化電量。

GcmTaskService

?既然我們已經看到了用批處理網絡來有效的優化電量的實用性,那現在就讓我們來探索GCM網絡管理在app中的使用。

dependencies {
    compile 'com.google.android.gms:play-services-gcm:8.1.0'
}

?確定僅僅依賴Google Play Services 的GCM的子集,否則你將會引進許多不必要的方法到你的app中。
?接下來。我們必需在AndroidManifest中聲明一個新的Service。


   
       
   

?CustomSerice是一個繼承自GcmTaskService的類,它是處理GCM網絡管理器的核心類。這個Sergice處理任務,這些任務是我們想要完成的任務,用 action ?SERVICE_ACTION_EXECUTE_TASK 來接收GCM網絡管理器的准備執行的通知。
? 接下來,我們創建一個CustomService.java的類來繼承GcmTaskService:

public class CustomService extends GcmTaskService {
        ...
}

? 這個類只要運行可以隨時執行任務,因為我們實現GcmTaskService ,我們必需在CustomService中實現OnRunTask方法:

@Override
public int onRunTask(TaskParams taskParams) {
        Log.i(TAG, "onRunTask");
        switch (taskParams.getTag()) {
                case TAG_TASK_ONEOFF_LOG:
                        Log.i(TAG, TAG_TASK_ONEOFF_LOG);
                        // This is where useful work would go
                        return GcmNetworkManager.RESULT_SUCCESS;
                case TAG_TASK_PERIODIC_LOG:
                        Log.i(TAG, TAG_TASK_PERIODIC_LOG);
                        // This is where useful work would go
                        return GcmNetworkManager.RESULT_SUCCESS;
                default:
                        return GcmNetworkManager.RESULT_FAILURE;
        }
}

?我們檢查給的參數來對比TaskParams的tag 來執行相應的代碼,在對應的分支裡面我們可以做復雜的邏輯操作,在demo裡面只是用Log打印了些信息。

GcmNetworkManager

?即使我們初始化了GcmTaskService,我們也必需要拿到GcmNetworkManager的引用對象,這個引用會作為剛剛Services執行任務時的hook。

private GcmNetworkManager mGcmNetworkManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        mGcmNetworkManager = GcmNetworkManager.getInstance(this);
}

?這個GcmNetworkManager對象將被用來執行任務,其中一個方法就是在onCreate中初始化這個成員變量,還有就是當你需要GcmNetworkManager的實例來執行任務時再獲取實例。

Scheduling Tasks

?一個單一任務是執行一個任務,這裡有兩種類型:一次性的和定期的。
?我們通過任務窗口提供一個任務,然後調度器決定實際執行時間,因為任務並不是需要立即執行的,所以調度器會幾個網絡請求作為批處理來節約電量。
?調度器會考慮到網絡的可用性,網絡活動和網絡加載。如果都沒有這些問題,調度器通常會處於等待狀態直到指定窗口的結束。
?下面是我怎麼樣執行一次性任務:

Task task = new OneoffTask.Builder()
              .setService(CustomService.class)
              .setExecutionWindow(0, 30)
              .setTag(LogService.TAG_TASK_ONEOFF_LOG)
              .setUpdateCurrent(false)
              .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED)
              .setRequiresCharging(false)
              .build();

mGcmNetworkManager.schedule(task);

這裡用的是Builder 模式,我們定義所有的參數在我們的任務中:
1. Service 可以控制任務的明確的GcmTaskService,允許我們可以取消
2. Execution window 任務執行的時間段,第一個是下邊界,第二個是上邊界,單位都是s,這個是強制的
3. Tag 用來標記onRunTask 方法中哪個任務是當前執行的。每個tag都應該是唯一的,最大的長度是100.
4. Update Current 這個決定是否應該替換前面一個擁有同一個tag的任務,默認是false,所以新的任務不會覆蓋已經存在的任務
5. Required Network 設置一個指定的網絡狀態支運行,如果網絡狀態是不可用,那麼一直等到網絡可用再執行。
6. Requires Charging 是否應該在設備連接電源的情況下執行任務。
? 全部都設置完成,由GcmNetworkManager的實例來執行。
? 定時任務如下 :

Task task = new PeriodicTask.Builder()
                        .setService(CustomService.class)
                        .setPeriod(30)
                        .setFlex(10)
                        .setTag(LogService.TAG_TASK_PERIODIC_LOG)
                        .setPersisted(true)
                        .build();

mGcmNetworkManager.schedule(task);

? 看起來很像,但是有幾次不一樣
1. Period 指定任務最多每間隔多長時間執行一次,單位是s,默認地,我們不能控制在這個時間段具體哪個時間執行,這個設置是強制要設置的。
2. Flex 指定在靠近結束時間(上個參數設置)內執行任務,如果時間段是30s,flex是10,調度器會在20-30之間執行。
3. Persisted 決定任務是不是應該在重啟之後繼續存在,默認是true,這個對一次性任務不支持,要求獲得”Receive Boot Completed”權限,否則這個設置會被忽略。
? 我們看到了使用GCM網絡管理器api的強大,調度器創建的即簡單又靈活。
看起來很像,但是有幾次不一樣
Period 指定任務最多每間隔多長時間執行一次,單位是s,默認地,我們不能控制在這個時間段具體哪個時間執行,這個設置是強制要設置的。
Flex 指定在靠近結束時間(上個參數設置)內執行任務,如果時間段是30s,flex是10,調度器會在20-30之間執行。
Persisted 決定任務是不是應該在重啟之後繼續存在,默認是true,這個對一次性任務不支持,要求獲得”Receive Boot Completed”
權限,否則這個設置會被忽略。
我們看到了使用GCM網絡管理器api的強大,調度器創建的即簡單又靈活。

取消任務

? 我們知道了怎麼執行任務,所以我們現在來看看怎麼取消任務,我們不取消正在執行的任務,不過我們可以取消還沒有執行的任務。
? 我們可以用給定的GcmTaskService來取消所有的任務:

mGcmNetworkManager.cancelAllTasks(CustomService.class);

? 我們也可以取消特定tag的任務:

mGcmNetworkManager.cancelTask(
        CustomService.TAG_TASK_PERIODIC_LOG,
        CustomService.class
);

? 還有一種情況,記住我們不能取消飛行中的任務。

Google Play Services

? 我們需要Google Play Services 才能在調度方法中用GCM網絡管理器來處理任務,為了安全的使用Google Play Services,我們需要檢查它是否存在。如下所示:

int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode == ConnectionResult.SUCCESS) {
        mGcmNetworkManager.schedule(task);
} else {
        // Deal with this networking task some other way
}

? 如果沒有Google Play Services,GcmNetworkManager將會靜默失敗,所以你需要檢查。
? 同樣的,當Google Play Services 或者app更新了,所有的執行任務都會被移除,為了避免失去你當前的執行任務,?GcmNetworkManager將會調用我們GcmTaskService(也就是CustomService)的onInitializeTasks()方法,這個方法可以重新調度所有的任務,這個通常用來執行定時任務:

 @Override
public void onInitializeTasks() {
    super.onInitializeTasks();
    // Reschedule removed tasks here
}

?簡單地重寫了這個方法,在裡面重新執行必要的任務。

總結

?我們一起深入了解了GCM 網絡管理器和如何使用來保護電源,好了,就到這裡吧。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved