Firebase 工作發送器

本指南討論如何使用Google的Firebase工作發送器連結庫排程背景工作。

概觀

讓Android應用程式對使用者保持回應的最佳方式之一,是確保背景中執行複雜或長時間執行的工作。 不過,背景工作不會對使用者使用裝置的體驗造成負面影響。

例如,背景作業可能會每隔三到四分鐘輪詢網站,以查詢特定數據集的變更。 這似乎是良性的,但它會對電池使用時間產生災難性的影響。 應用程式會重複喚醒裝置、將CPU提升至較高的電源狀態、啟動無線電、提出網路要求,然後處理結果。 情況變得更糟,因為裝置不會立即關閉電源,並返回低功率閑置狀態。 排程不佳的背景工作可能會不小心讓裝置處於不必要和過度電源需求的狀態。 這種看似無辜的活動(輪詢網站)將使裝置在相對短時間內無法使用。

Android 提供下列 API 來協助在背景中執行工作,但本身不足以進行智慧型手機工作排程。

  • 意圖服務 – 意圖服務 非常適合執行工作,但無法排程工作。
  • AlarmManager – 這些 API 只允許排程工作,但無法實際執行工作。 此外,AlarmManager 只允許以時間為基礎的條件約束,這表示在特定時間或經過一段時間之後引發警示。
  • JobScheduler – JobSchedule 是一個絕佳的 API,可搭配操作系統排程作業。 不過,它僅適用於以 API 層級 21 或更新版本為目標的 Android 應用程式。
  • 廣播接收者 – Android 應用程式可以設定廣播接收者,以執行工作以回應全系統事件或意圖。 不過,廣播接收器不會提供應該執行作業時的任何控制權。 Android 作業系統中的變更也會限制廣播接收者何時能夠運作,或可回應的工作種類。

有兩個主要功能可以有效率地執行背景工作(有時稱為背景工作或工作):

  1. 以智慧方式排程工作 – 當應用程式在背景中執行做為良好公民的工作時,這一點很重要。 在理想情況下,應用程式不應該要求執行作業。 相反地,應用程式應該指定在作業可以執行時必須符合的條件,然後排程該工作在符合條件時執行。 這可讓Android以智慧方式執行工作。 例如,網路要求可能會批處理以同時執行,以充分利用與網路相關的額外負荷。
  2. 封裝工作 – 執行背景工作 的程式代碼應該封裝在獨立於使用者介面獨立執行的離散元件中,如果工作因為某些原因而無法完成,則比較容易重新排程。

Firebase 作業發送器是 Google 的連結庫,可提供 Fluent API 來簡化排程背景工作。 它打算取代Google Cloud Manager。 Firebase 作業發送器包含下列 API:

  • Firebase.JobDispatcher.JobService是一個抽象類,必須使用將在背景作業中執行的邏輯來擴充。
  • 宣告 Firebase.JobDispatcher.JobTrigger 何時應該啟動作業。 這通常以時間範圍表示,例如,在啟動作業之前至少等候 30 秒,但在 5 分鐘內執行作業。
  • Firebase.JobDispatcher.RetryStrategy包含當作業無法正確執行時應該執行的動作相關信息。 重試策略會指定在嘗試再次執行作業之前要等候的時間長度。
  • Firebase.JobDispatcher.Constraint是選擇性值,描述作業執行之前必須符合的條件,例如裝置位於未計量的網路或充電上。
  • Firebase.JobDispatcher.Job是一種 API,可將 先前的 API 統一到 可由 排程JobDispatcher的工作單位。 類別 Job.Builder 是用來具現化 Job
  • Firebase.JobDispatcher.JobDispatcher會使用前三個 API 來排程作業系統的工作,並在必要時提供取消作業的方式。

若要排程使用 Firebase 作業發送器,Xamarin.Android 應用程式必須將程式代碼封裝在擴充 JobService 類別的類型中。 JobService 有三種生命週期方法,可在作業存留期期間呼叫:

  • bool OnStartJob(IJobParameters parameters) – 此方法是工作會發生的地方,而且應該一律實作。 它會在主線程上執行。 如果剩餘工時,或false工作完成,這個方法會傳回 true
  • bool OnStopJob(IJobParameters parameters) – 當作業因為某些原因而停止時,就會呼叫此作業。 如果應該重新排程工作以供稍後使用,則應該傳回 true
  • JobFinished(IJobParameters parameters, bool needsReschedule) – 當 完成任何異步工作時 JobService ,就會呼叫這個方法。

若要排程作業,應用程式會具現化 JobDispatcher 物件。 然後, Job.Builder 會用來建立 Job 物件,此物件會提供給 JobDispatcher ,以嘗試並排程要執行的作業。

本指南將討論如何將 Firebase 作業發送器新增至 Xamarin.Android 應用程式,並用它來排程背景工作。

需求

Firebase 作業發送器需要 Android API 層級 9 或更高版本。 Firebase 作業發送器連結庫依賴 Google Play Services 所提供的一些元件;裝置必須已安裝Google Play服務。

在 Xamarin.Android 中使用 Firebase 作業發送器連結庫

若要開始使用 Firebase 作業發送器,請先將 Xamarin.Firebase.JobDispatcher NuGet 套件新增至 Xamarin.Android 專案。 搜尋 NuGet 封裝管理員 以取得 Xamarin.Firebase.JobDispatcher 套件(仍在發行前版本)。

新增 Firebase 作業發送器連結庫之後,請建立類別 JobService ,然後排程它以 實例 FirebaseJobDispatcher執行。

建立 JobService

Firebase 作業發送器連結庫所執行的所有工作,都必須在擴充 Firebase.JobDispatcher.JobService 抽象類的類型中完成。 JobService建立 與使用 Android 架構建立 Service 非常類似:

  1. 擴充 類別JobService
  2. 使用 ServiceAttribute裝飾子類別。 雖然並非絕對必要,但建議明確設定 Name 參數,以協助偵錯 JobService
  3. 新增 以IntentFilter在 AndroidManifest.xml宣告 JobService 。 這也有助於 Firebase 作業發送器連結庫找出並叫 JobService用 。

下列程式代碼是應用程式最簡單的 JobService 範例,使用 TPL 以異步方式執行某些工作:

[Service(Name = "com.xamarin.fjdtestapp.DemoJob")]
[IntentFilter(new[] {FirebaseJobServiceIntent.Action})]
public class DemoJob : JobService
{
    static readonly string TAG = "X:DemoService";

    public override bool OnStartJob(IJobParameters jobParameters)
    {
        Task.Run(() =>
        {
            // Work is happening asynchronously (code omitted)
                       
        });

        // Return true because of the asynchronous work
        return true;  
    }

    public override bool OnStopJob(IJobParameters jobParameters)
    {
        Log.Debug(TAG, "DemoJob::OnStartJob");
        // nothing to do.
        return false;
    }
}

建立 FirebaseJobDispatcher

在排程任何工作之前,必須先建立 Firebase.JobDispatcher.FirebaseJobDispatcher 物件。 FirebaseJobDispatcher負責排程 JobService。 下列代碼段是建立 實例的 FirebaseJobDispatcher其中一種方式:

// This is the "Java" way to create a FirebaseJobDispatcher object
IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);

在先前的代碼段中, GooglePlayDriver is 類別可協助 FirebaseJobDispatcher 與裝置上 Google Play Services 中的某些排程 API 互動。 參數 context 是任何 Android Context,例如 Activity。 GooglePlayDriver目前是 Firebase 作業發送器連結庫中唯一IDriver的實作。

Firebase 作業發送器 Xamarin.Android 系結提供擴充方法,從 Context建立 FirebaseJobDispatcher

FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();

FirebaseJobDispatcher具現化之後,就可以在 類別中JobService建立Job並執行程序代碼。 Job是由 Job.Builder 物件所建立,將在下一節中討論。

使用 Job.Builder 建立 Firebase.JobDispatcher.Job

類別 Firebase.JobDispatcher.Job 負責封裝執行 JobService所需的元數據。 Job包含的資訊,例如作業在執行之前必須符合的任何條件約束、如果 Job 為週期性,或會導致作業執行的任何觸發程式。 至少,Job必須有標記(唯一的字串,可識別作業至 FirebaseJobDispatcher的 ),以及應該執行的 型JobService別。 Firebase 作業傳送器會在作業執行時具現化 JobServiceJob使用 類別的Firebase.JobDispatcher.Job.JobBuilder實體建立 。

下列代碼段是如何使用 Xamarin.Android 系結建立 Job 的最簡單範例:

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .Build();

Job.Builder將會對作業的輸入值執行一些基本驗證檢查。 如果 無法 Job.Builder 建立 ,將會擲回例外狀況 JobJob.Builder使用下列預設值建立 Job

  • Job存留期(將排程執行的時間)只有在裝置重新啟動後才會重新啟動, 一旦裝置重新啟動,就會Job遺失。
  • Job不是週期性, 只會執行一次。
  • Job將排定儘快執行 。
  • 的預設重試策略Job是使用指數輪詢(在設定 RetryStrategy 一節中討論更多詳細數據)

排程工作

建立 Job之後,必須先使用 FirebaseJobDispatcher 排程,才能執行。 排程 Job有兩種方法:

// This will throw an exception if there was a problem scheduling the job
dispatcher.MustSchedule(myJob);

// This method will not throw an exception; an integer result value is returned
int scheduleResult = dispatcher.Schedule(myJob);

FirebaseJobDispatcher.Schedule 傳回的值將是下列其中一個整數值:

  • FirebaseJobDispatcher.ScheduleResultSuccessJob– 已成功排程 。
  • FirebaseJobDispatcher.ScheduleResultUnknownError – 發生未知的問題,導致 Job 無法排程 。
  • FirebaseJobDispatcher.ScheduleResultNoDriverAvailable – 已使用無效 IDriver ,或 IDriver 以某種方式無法使用 。
  • FirebaseJobDispatcher.ScheduleResultUnsupportedTriggerTrigger– 不支援 。
  • FirebaseJobDispatcher.ScheduleResultBadService – 服務未正確設定或無法使用。

設定作業

您可以自訂作業。 如何自訂作業的範例包括:

  • 將參數傳遞至作業 – A Job 可能需要額外的值來執行其工作,例如下載檔案。
  • 設定條件約束 – 只有在符合特定條件時,才可能需要執行作業。 例如,只有在裝置充電時才會執行 Job
  • Job指定何時應該執行 – Firebase 作業發送器可讓應用程式指定作業應該執行的時間。
  • 宣告失敗作業 的重試策略 – 重試策略 會針對失敗的作業提供 FirebaseJobDispatcher 相關指引 Jobs

下列各節將進一步討論這些主題。

將參數傳遞至作業

參數會藉由建立 BundleJob.Builder.SetExtras 方法一起傳遞的 來傳遞至作業:

Bundle jobParameters = new Bundle();
jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetExtras(jobParameters)
                      .Build();

BundleIJobParameters.Extras 方法上的 OnStartJob 屬性存取 :

public override bool OnStartJob(IJobParameters jobParameters)
{
    int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);
    
    // rest of code omitted
} 

設定條件約束

限制有助於降低裝置的成本或電池耗盡。 類別會將 Firebase.JobDispatcher.Constraint 這些條件約束定義為整數值:

  • Constraint.OnUnmeteredNetwork – 只有在裝置連線到未計量的網路時,才執行作業。 這對於防止用戶產生數據費用很有用。
  • Constraint.OnAnyNetwork – 在裝置所連線的任何網路上執行作業。 如果與 一起 Constraint.OnUnmeteredNetwork指定,這個值會優先使用。
  • Constraint.DeviceCharging – 只有在裝置充電時,才執行作業。

條件約束是使用 方法設定的 Job.Builder.SetConstraint

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetConstraint(Constraint.DeviceCharging)
                      .Build();

提供 JobTrigger 操作系統的指引,說明作業何時應該啟動。 JobTrigger有一個執行視窗,定義應該執行的排程時間Job。 執行視窗具有 開始視窗 值和 結束視窗 值。 開始視窗是裝置在執行作業之前應該等候的秒數,而結束視窗值是執行 Job之前等待的最大秒數。

JobTrigger可以使用 方法建立 Firebase.Jobdispatcher.Trigger.ExecutionWindow 。 例如 Trigger.ExecutionWindow(15,60) ,表示作業應該在排程時執行 15 到 60 秒。 方法 Job.Builder.SetTrigger 用於

JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);
Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetTrigger(myTrigger)
                      .Build();

作業的預設值 JobTrigger 會以 值表示,這個值 Trigger.Now會指定排程后儘快執行作業。

設定 RetryStrategy

Firebase.JobDispatcher.RetryStrategy用來指定裝置在嘗試重新執行失敗作業之前,應該使用多少延遲。 RetryStrategy有一個原則,定義將用來重新排程失敗作業的時間基底演算法,以及指定應該排程作業的視窗的執行視窗。 這個 重新排程視窗 是由兩個值所定義。 第一個值是重新排程作業之前要等候的秒數( 初始輪詢 值),而第二個值是作業必須執行前的秒數上限( 最大輪詢 值)。

下列 int 值會識別兩種類型的重試原則:

  • RetryStrategy.RetryPolicyExponential – 指數 輪詢 原則會在每次失敗后以指數方式增加初始輪詢值。 作業第一次失敗時,連結庫會等候指定的_initial間隔,再重新排程作業 – 範例 30 秒。 作業第二次失敗時,連結庫會等候至少 60 秒,再嘗試執行作業。 第三次嘗試失敗之後,連結庫會等候 120 秒,依此等。 Firebase 作業發送器連結庫的預設值 RetryStrategy 是由 RetryStrategy.DefaultExponential 物件表示。 其初始輪詢為 30 秒,最大輪詢為 3600 秒。
  • RetryStrategy.RetryPolicyLinear – 此策略是 線性輪詢 ,工作應重新排程為在設定間隔執行(直到成功為止)。 線性輪詢最適合必須儘快完成的工作,或快速解決自己的問題。 Firebase 作業發送器連結庫會 RetryStrategy.DefaultLinear 定義 ,其重新排程視窗至少為 30 秒,最多 3600 秒。

使用方法可以定義自定義RetryStrategyFirebaseJobDispatcher.NewRetryStrategy。 它採用三個參數:

  1. int policy – 此 原則 是上述 RetryStrategy 其中一個值, RetryStrategy.RetryPolicyLinearRetryStrategy.RetryPolicyExponential
  2. int initialBackoffSeconds – 初始 輪詢 是嘗試再次執行作業之前所需的延遲,以秒為單位。 預設值為30秒。
  3. int maximumBackoffSeconds – 最大 輪詢 值會宣告延遲的秒數上限,然後再嘗試再次執行作業。 預設值為3600秒。
RetryStrategy retry = dispatcher.NewRetryStrategy(RetryStrategy.RetryPolicyLinear, initialBackoffSeconds, maximumBackoffSet);

// Create a Job and set the RetryStrategy via the Job.Builder
Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetRetryStrategy(retry)
                      .Build();

取消作業

您可以使用 方法或 FirebaseJobDispatcher.Cancel(string) 方法,取消所有已排程的作業,或只取消FirebaseJobDispatcher.CancelAll()單一作業:

int cancelResult = dispatcher.CancelAll(); 

// to cancel a single job:

int cancelResult = dispatcher.Cancel("unique-tag-for-job");

任一種方法都會傳回整數值:

  • FirebaseJobDispatcher.CancelResultSuccess – 作業已成功取消。
  • FirebaseJobDispatcher.CancelResultUnknownError – 錯誤導致作業無法取消。
  • FirebaseJobDispatcher.CancelResult.NoDriverAvailableFirebaseJobDispatcher– 無法取消作業,因為沒有有效的IDriver可用作業。

摘要

本指南已討論如何使用 Firebase 作業發送器在背景中智慧地執行工作。 它討論了如何將要執行的工作封裝為 , JobService 以及如何使用 FirebaseJobDispatcher 來排程該工作、使用 指定準則 JobTrigger 以及應該 RetryStrategy如何處理失敗。