Distribuidor de trabajo de Firebase
En esta guía se describe cómo programar el trabajo en segundo plano mediante la biblioteca Firebase Job Dispatcher de Google.
Información general
Una de las mejores maneras de mantener una aplicación Android con capacidad de respuesta para el usuario es asegurarse de que el trabajo complejo o de larga duración se realiza en segundo plano. Sin embargo, es importante que el trabajo en segundo plano no afectará negativamente a la experiencia del usuario con el dispositivo.
Por ejemplo, un trabajo en segundo plano podría sondear un sitio web cada tres o cuatro minutos para consultar los cambios en un conjunto de datos determinado. Esto parece benigno, pero tendría un impacto desastroso en la duración de la batería. La aplicación reactivará repetidamente el dispositivo, elevará la CPU a un estado de energía superior, encenderá las radios, realizará las solicitudes de red y, a continuación, procesará los resultados. Se pone peor porque el dispositivo no se encenderá inmediatamente y volverá al estado de inactividad de bajo consumo. Un trabajo en segundo plano mal programado puede mantener accidentalmente el dispositivo en un estado con requisitos de energía innecesarios y excesivos. Esta actividad aparentemente insoportable (sondear un sitio web) hará que el dispositivo sea inutilizable en un período de tiempo relativamente corto.
Android proporciona las siguientes API para ayudar a realizar el trabajo en segundo plano, pero por sí solos no son suficientes para la programación inteligente de trabajos.
- Intent Services: los servicios de intención son excelentes para realizar el trabajo, pero no proporcionan ninguna manera de programar el trabajo.
- AlarmManager: estas API solo permiten programar el trabajo, pero no proporcionan ninguna manera de realizar realmente el trabajo. Además, AlarmManager solo permite restricciones basadas en el tiempo, lo que significa que se genera una alarma en un momento determinado o después de que haya transcurrido un determinado período de tiempo.
- JobScheduler: JobSchedule es una excelente API que funciona con el sistema operativo para programar trabajos. Sin embargo, solo está disponible para las aplicaciones Android que tienen como destino el nivel de API 21 o superior.
- Receptores de difusión: una aplicación Android puede configurar receptores de difusión para realizar el trabajo en respuesta a eventos o intenciones de todo el sistema. Sin embargo, los receptores de difusión no proporcionan ningún control sobre cuándo se debe ejecutar el trabajo. Además, los cambios en el sistema operativo Android restringirán cuándo funcionarán los receptores de difusión o los tipos de trabajo a los que pueden responder.
Hay dos características clave para realizar eficazmente el trabajo en segundo plano (a veces denominado trabajo en segundo plano otrabajo):
- Programación inteligente del trabajo: es importante que, cuando una aplicación está realizando trabajo en segundo plano, lo haga como un buen ciudadano. Lo ideal es que la aplicación no exija que se ejecute un trabajo. En su lugar, la aplicación debe especificar las condiciones que se deben cumplir para cuando se puede ejecutar el trabajo y, a continuación, programar ese trabajo para que se ejecute cuando se cumplen las condiciones. Esto permite que Android realice el trabajo de forma inteligente. Por ejemplo, las solicitudes de red se pueden procesar por lotes para que se ejecuten todas al mismo tiempo con el fin de aprovechar al máximo la sobrecarga que implica la red.
- Encapsular el trabajo: el código para realizar el trabajo en segundo plano debe encapsularse en un componente discreto que se pueda ejecutar independientemente de la interfaz de usuario y será relativamente fácil de volver a programar si el trabajo no se completa por algún motivo.
Firebase Job Dispatcher es una biblioteca de Google que proporciona una API fluida para simplificar la programación del trabajo en segundo plano. Está pensado para sustituir a Google Cloud Manager. Firebase Job Dispatcher consta de las siguientes API:
- es
Firebase.JobDispatcher.JobServiceuna clase abstracta que se debe extender con la lógica que se ejecutará en el trabajo en segundo plano. - Declara
Firebase.JobDispatcher.JobTriggercuándo se debe iniciar el trabajo. Esto se suele expresar como una ventana de tiempo, por ejemplo, esperar al menos 30 segundos antes de iniciar el trabajo, pero ejecutar el trabajo en un plazo de 5 minutos. - contiene
Firebase.JobDispatcher.RetryStrategyinformación sobre lo que se debe hacer cuando un trabajo no se ejecuta correctamente. La estrategia de reintento especifica cuánto tiempo se debe esperar antes de intentar ejecutar el trabajo de nuevo. - Un es un valor opcional que describe una condición que debe cumplirse antes de que se pueda ejecutar el trabajo, como que el dispositivo se encuentra en una red sin medidor o
Firebase.JobDispatcher.Constraintcobrando. - es
Firebase.JobDispatcher.Jobuna API que unifica las API anteriores en una unidad de trabajo que puede programarJobDispatcher. LaJob.Builderclase se usa para crear una instancia deJob. - usa las tres API anteriores para programar el trabajo con el sistema operativo y para proporcionar una manera de
Firebase.JobDispatcher.JobDispatchercancelar trabajos, si es necesario.
Para programar el trabajo con firebase Job Dispatcher, una aplicación de Xamarin.Android debe encapsular el código en un tipo que extienda la JobService clase . JobService tiene tres métodos de ciclo de vida a los que se puede llamar durante la vigencia del trabajo:
bool OnStartJob(IJobParameters parameters): este método es donde se producirá el trabajo y siempre se debe implementar. Se ejecuta en el subproceso principal. Este método devolverátruesi queda trabajo o si el trabajo se hafalserealizado.bool OnStopJob(IJobParameters parameters): se llama a este método cuando el trabajo se detiene por algún motivo. Debe devolver sitrueel trabajo se debe volver a programar para más adelante.JobFinished(IJobParameters parameters, bool needsReschedule): se llama a este método cuando haJobServicefinalizado cualquier trabajo asincrónico.
Para programar un trabajo, la aplicación crea una instancia de un JobDispatcher objeto . A continuación, se usa para crear un objeto , que se proporciona a que Job.BuilderJob intentará y JobDispatcher programe la ejecución del trabajo.
En esta guía se explica cómo agregar Firebase Job Dispatcher a una aplicación de Xamarin.Android y cómo usarlo para programar el trabajo en segundo plano.
Requisitos
Firebase Job Dispatcher requiere el nivel de API de Android 9 o superior. La biblioteca Firebase Job Dispatcher se basa en algunos componentes proporcionados por Google Play Services; el dispositivo debe tener Google Play Services instalado.
Uso de la biblioteca Firebase Job Dispatcher en Xamarin.Android
Para empezar a trabajar con Firebase Job Dispatcher, primero agregue el paquete de NuGet Xamarin.Firebase.JobDispatcher al proyecto de Xamarin.Android. Busque en NuGet Administrador de paquetes el paquete Xamarin.Firebase.JobDispatcher (que todavía está en versión anterior).
Después de agregar la biblioteca Firebase Job Dispatcher, cree una clase y, a continuación, programe su ejecución JobService con una instancia de FirebaseJobDispatcher .
Creación de un jobService
Todo el trabajo realizado por la biblioteca Firebase Job Dispatcher debe realizarse en un tipo que extienda la Firebase.JobDispatcher.JobService clase abstracta. La creación JobService de un es muy similar a la creación de un con android Service framework:
- Extensión de la
JobServiceclase - Decore la subclase con
ServiceAttribute. Aunque no es estrictamente necesario, se recomienda establecer explícitamente elNameparámetro para ayudar a depurarJobService. - Agregue un
IntentFilterpara declarar en elJobServiceIntentFilter. Esto también ayudará a la biblioteca Firebase Job Dispatcher a buscar e invocarJobService.
El código siguiente es un ejemplo del más sencillo para una aplicación, mediante TPL para realizar de forma asincrónica JobService algún trabajo:
[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;
}
}
Creación de un FirebaseJobDispatcher
Antes de que se pueda programar cualquier trabajo, es necesario crear un Firebase.JobDispatcher.FirebaseJobDispatcher objeto . es FirebaseJobDispatcher responsable de programar un JobService . El siguiente fragmento de código es una manera de crear una instancia de FirebaseJobDispatcher :
// This is the "Java" way to create a FirebaseJobDispatcher object
IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
En el fragmento de código anterior, es la clase que ayuda a interactuar con algunas de las API de programación GooglePlayDriverFirebaseJobDispatcher Google Play Services en el dispositivo. El parámetro context es cualquier Context Android, como una actividad. Actualmente, GooglePlayDriver es la única implementación de la biblioteca IDriver Firebase Job Dispatcher.
El enlace de Xamarin.Android para firebase Job Dispatcher proporciona un método de extensión para crear a FirebaseJobDispatcher partir de Context :
FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();
Una vez FirebaseJobDispatcher que se ha creado una instancia de , es posible crear y ejecutar el código en la Job clase JobService . El Job objeto se crea mediante un objeto y se describe en la sección Job.Builder siguiente.
Creación de un archivo Firebase.JobDispatcher.Job con Job.Builder
La Firebase.JobDispatcher.Job clase es responsable de encapsular los metadatos necesarios para ejecutar JobService . contiene información como cualquier restricción que se debe cumplir antes de que se pueda ejecutar el trabajo, si es recurrente o cualquier desencadenador que haga que se ejecute JobJob el trabajo. Como mínimo, debe tener una etiqueta (una cadena única que identifique el trabajo a ) y el tipo de que Job se debe JobFirebaseJobDispatcherJobService ejecutar. Firebase Job Dispatcher crea una instancia de JobService cuando llegue el momento de ejecutar el trabajo. Se Job crea mediante una instancia de la clase Firebase.JobDispatcher.Job.JobBuilder .
El siguiente fragmento de código es el ejemplo más sencillo de cómo crear un mediante Job el enlace de Xamarin.Android:
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.Build();
realizará Job.Builder algunas comprobaciones de validación básicas en los valores de entrada del trabajo. Se producirá una excepción si no es posible que cree Job.Builder . Job creará Job.Builder un con los valores predeterminados Job siguientes:
- La
JobduraciónJob(cuánto tiempo se programará para ejecutarse) es solo hasta que se reinicia el dispositivo, una vez que el dispositivo reinicia seJobpierde. - Un
Jobno es periódico: solo se ejecutará una vez. - Se
Jobprogramará una ejecución lo antes posible. - La estrategia de reintento predeterminada para un elemento es usar un retroceso exponencial (se describe con más detalle a continuación en la sección Establecimiento de
Jobun retrystrategy)Job
Programación de un trabajo
Después de crear Job , debe programarse con antes FirebaseJobDispatcher de ejecutarse. Hay dos métodos para programar un 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);
El valor devuelto por FirebaseJobDispatcher.Schedule será uno de los siguientes valores enteros:
FirebaseJobDispatcher.ScheduleResultSuccess: seJobha programado correctamente.FirebaseJobDispatcher.ScheduleResultUnknownError: se produjo algún problema desconocido queJobimpedía la programación de .FirebaseJobDispatcher.ScheduleResultNoDriverAvailable: se usóIDriverun no válido o, de algúnIDrivermodo, no estaba disponible.FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger: noTriggerse admite .FirebaseJobDispatcher.ScheduleResultBadService: el servicio no está configurado correctamente o no está disponible.
Configuración de un trabajo
Es posible personalizar un trabajo. Entre los ejemplos de cómo se puede personalizar un trabajo se incluyen los siguientes:
- Pasar parámetros a un trabajo: A puede requerir valores adicionales para realizar su trabajo, por ejemplo, descargar un archivo.
- Establecer restricciones: puede ser necesario ejecutar solo un trabajo cuando se cumplen ciertas condiciones. Por ejemplo, ejecute solo cuando
Jobel dispositivo se esté cobrando. - Especificar cuándo debe ejecutarse: Firebase Job Dispatcher permite a las aplicaciones especificar una hora en la que se debe ejecutar el trabajo.
- Declarar una estrategia de reintento para trabajos con errores: una estrategia de reintentos proporciona instrucciones sobre qué hacer con ese error.
Cada uno de estos temas se analizará más en las secciones siguientes.
Pasar parámetros a un trabajo
Los parámetros se pasan a un trabajo mediante la creación Bundle de un que se pasa junto con el método Job.Builder.SetExtras :
Bundle jobParameters = new Bundle();
jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetExtras(jobParameters)
.Build();
Se Bundle tiene acceso a desde la propiedad en el método IJobParameters.ExtrasOnStartJob :
public override bool OnStartJob(IJobParameters jobParameters)
{
int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);
// rest of code omitted
}
Establecer restricciones
Las restricciones pueden ayudar a reducir los costos o el consumo de batería en el dispositivo. La Firebase.JobDispatcher.Constraint clase define estas restricciones como valores enteros:
Constraint.OnUnmeteredNetwork: ejecute solo el trabajo cuando el dispositivo esté conectado a una red sin medidor. Esto es útil para evitar que el usuario incurr en cargos de datos.Constraint.OnAnyNetwork: ejecute el trabajo en cualquier red a la que esté conectado el dispositivo. Si se especifica junto conConstraint.OnUnmeteredNetwork, este valor tendrá prioridad.Constraint.DeviceCharging: ejecute el trabajo solo cuando el dispositivo se esté cobrando.
Las restricciones se establecen con el Job.Builder.SetConstraint método :
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetConstraint(Constraint.DeviceCharging)
.Build();
proporciona JobTrigger instrucciones al sistema operativo sobre cuándo debe iniciarse el trabajo. tiene JobTrigger una ventana en ejecución JobTrigger define una hora programada para cuando se debe Job ejecutar . La ventana de ejecución tiene un valor de ventana de inicio y un valor de ventana final. La ventana de inicio es el número de segundos que el dispositivo debe esperar antes de ejecutar el trabajo y el valor de la ventana final es el número máximo de segundos que hay que esperar antes de ejecutar Job .
Se JobTrigger puede crear un objeto con el método Firebase.Jobdispatcher.Trigger.ExecutionWindow . Por Trigger.ExecutionWindow(15,60) ejemplo, significa que el trabajo debe ejecutarse entre 15 y 60 segundos a partir de cuando está programado. El Job.Builder.SetTrigger método se usa para
JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);
Job myJob = dispatcher.NewJobBuilder()
.SetService<DemoJob>("demo-job-tag")
.SetTrigger(myTrigger)
.Build();
El valor predeterminado de un trabajo se representa mediante el valor , que especifica que un trabajo se ejecute lo antes posible JobTriggerTrigger.Now después de la programación.
Establecer un retrystrategy
se usa para especificar la cantidad de retraso que debe usar un dispositivo antes Firebase.JobDispatcher.RetryStrategy de intentar volver a ejecutar un trabajo con errores. tiene una directiva , que define qué algoritmo de base de tiempo se usará para volver a programar el trabajo con errores y una ventana de ejecución que especifica una ventana en la que se debe programar RetryStrategy el trabajo. RetryStrategy Esta ventana de reprogramación se define mediante dos valores. El primer valor es el número de segundos que hay que esperar antes de reprogramar el trabajo (el valor de reestraimiento inicial) y el segundo número es el número máximo de segundos antes de que se ejecute el trabajo (el valor de backoff máximo).
Estos valores int identifican los dos tipos de directivas de reintento:
RetryStrategy.RetryPolicyExponential: unaRetryStrategy.RetryPolicyExponentialexponencial aumentará exponencialmente el valor de retroceso inicial después de cada error. La primera vez que se produce un error en un trabajo, la biblioteca esperará el intervalo _initial que se especifica antes de reprogramar el trabajo: ejemplo 30 segundos. La segunda vez que se produce un error en el trabajo, la biblioteca esperará al menos 60 segundos antes de intentar ejecutar el trabajo. Después del tercer intento con error, la biblioteca esperará 120 segundos, y así sucesivamente. El objeto representa el valor predeterminado de la bibliotecaRetryStrategyFirebase JobRetryStrategy.DefaultExponentialDispatcher. Tiene un respaldo inicial de 30 segundos y un máximo de 3600 segundos.RetryStrategy.RetryPolicyLinear: esta estrategia es un respaldoRetryStrategy.RetryPolicyLinearel trabajo se debe volver a programar para ejecutarse a intervalos establecidos (hasta que se realiza correctamente). El respaldo lineal es más adecuado para el trabajo que se debe completar lo antes posible o para los problemas que se resolverán rápidamente. La biblioteca Firebase Job Dispatcher define un objeto que tiene una ventana de reprogramación de al menos 30 segundos y hastaRetryStrategy.DefaultLinear3600 segundos.
Es posible definir un personalizado RetryStrategy con el FirebaseJobDispatcher.NewRetryStrategy método . Toma tres parámetros:
int policy:int policyes uno de los valoresRetryStrategyanteriores,RetryStrategy.RetryPolicyLinearoRetryStrategy.RetryPolicyExponential.int initialBackoffSeconds: elint initialBackoffSecondses un retraso, en segundos, necesario antes de intentar volver a ejecutar el trabajo. El valor predeterminado para esto es 30 segundos.int maximumBackoffSeconds: elint maximumBackoffSecondsmáximo declara el número máximo de segundos que se retrasarán antes de intentar volver a ejecutar el trabajo. El valor predeterminado es 3600 segundos.
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();
Cancelación de un trabajo
Es posible cancelar todos los trabajos que se han programado, o simplemente un único trabajo mediante el FirebaseJobDispatcher.CancelAll() método o el método FirebaseJobDispatcher.Cancel(string) :
int cancelResult = dispatcher.CancelAll();
// to cancel a single job:
int cancelResult = dispatcher.Cancel("unique-tag-for-job");
Cualquiera de los métodos devolverá un valor entero:
FirebaseJobDispatcher.CancelResultSuccess: el trabajo se canceló correctamente.FirebaseJobDispatcher.CancelResultUnknownError: se produjo un error que impedía cancelar el trabajo.FirebaseJobDispatcher.CancelResult.NoDriverAvailable:FirebaseJobDispatcherno puede cancelar el trabajo porque no hay disponible ningúnIDriverválido.
Resumen
En esta guía se ha analizado cómo usar Firebase Job Dispatcher para realizar el trabajo de forma inteligente en segundo plano. Se ha analizado cómo encapsular el trabajo que se va a realizar como y cómo usar para programar ese trabajo, especificando los criterios con y cómo se deben controlar los errores con JobServiceFirebaseJobDispatcherJobTriggerRetryStrategy .