add WorkManager extension

This commit is contained in:
Philippe Simons 2019-03-11 13:22:33 +01:00
parent f35dbeb567
commit 0ea023047d
5 changed files with 256 additions and 0 deletions

View File

@ -38,6 +38,7 @@ include modulePrefix + 'extension-vp9'
include modulePrefix + 'extension-rtmp'
include modulePrefix + 'extension-leanback'
include modulePrefix + 'extension-jobdispatcher'
include modulePrefix + 'extension-workmanager'
project(modulePrefix + 'library').projectDir = new File(rootDir, 'library/all')
project(modulePrefix + 'library-core').projectDir = new File(rootDir, 'library/core')
@ -60,3 +61,4 @@ project(modulePrefix + 'extension-vp9').projectDir = new File(rootDir, 'extensio
project(modulePrefix + 'extension-rtmp').projectDir = new File(rootDir, 'extensions/rtmp')
project(modulePrefix + 'extension-leanback').projectDir = new File(rootDir, 'extensions/leanback')
project(modulePrefix + 'extension-jobdispatcher').projectDir = new File(rootDir, 'extensions/jobdispatcher')
project(modulePrefix + 'extension-workmanager').projectDir = new File(rootDir, 'extensions/workmanager')

View File

@ -0,0 +1,23 @@
# ExoPlayer WorkManager extension #
This extension provides a Scheduler implementation which uses [Android Arch WorkManager][].
[Android Arch WorkManager]: https://developer.android.com/topic/libraries/architecture/workmanager.html
## Getting the extension ##
The easiest way to use the extension is to add it as a gradle dependency:
```gradle
implementation 'com.google.android.exoplayer:extension-workmanager:2.X.X'
```
where `2.X.X` is the version, which must match the version of the ExoPlayer
library being used.
Alternatively, you can clone the ExoPlayer repository and depend on the module
locally. Instructions for doing this can be found in ExoPlayer's
[top level README][].
[top level README]: https://github.com/google/ExoPlayer/blob/release-v2/README.md

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
apply from: '../../constants.gradle'
apply plugin: 'com.android.library'
android {
compileSdkVersion project.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion project.ext.minSdkVersion
targetSdkVersion project.ext.targetSdkVersion
}
testOptions.unitTests.includeAndroidResources = true
}
dependencies {
implementation project(modulePrefix + 'library-core')
implementation 'android.arch.work:work-runtime:1.0.0'
}
ext {
javadocTitle = 'Android Arch WorkManager extension'
}
apply from: '../../javadoc_library.gradle'
ext {
releaseArtifact = 'extension-workmanager'
releaseDescription = 'Android Arch WorkManager extension for ExoPlayer.'
}
apply from: '../../publish.gradle'

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2018 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<manifest package="com.google.android.exoplayer2.ext.workmanager"/>

View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.ext.workmanager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.scheduler.Scheduler;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.Util;
import androidx.annotation.NonNull;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.ExistingWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
/***
* A {@link Scheduler} that uses {@link WorkManager}.
*/
public final class WorkManagerScheduler implements Scheduler {
private static final String TAG = "WorkManagerScheduler";
private static final String KEY_SERVICE_ACTION = "service_action";
private static final String KEY_SERVICE_PACKAGE = "service_package";
private static final String KEY_REQUIREMENTS = "requirements";
private final String workName;
/**
* @param workName A name for work scheduled by this instance. If the same name was used by a previous
* instance, anything scheduled by the previous instance will be canceled by this instance if
* {@link #schedule(Requirements, String, String)} or {@link #cancel()} are called.
*/
public WorkManagerScheduler(String workName) {
this.workName = workName;
}
@Override
public boolean schedule(Requirements requirements, String servicePackage, String serviceAction) {
Constraints constraints = buildConstraints(requirements);
Data inputData = buildInputData(requirements, servicePackage, serviceAction);
OneTimeWorkRequest workRequest = buildWorkRequest(constraints, inputData);
logd("Scheduling work: " + workName);
WorkManager.getInstance().enqueueUniqueWork(workName, ExistingWorkPolicy.KEEP, workRequest);
return true;
}
@Override
public boolean cancel() {
logd("Canceling work: " + workName);
WorkManager.getInstance().cancelUniqueWork(workName);
return true;
}
private static Constraints buildConstraints(Requirements requirements) {
Constraints.Builder builder = new Constraints.Builder();
switch (requirements.getRequiredNetworkType()) {
case Requirements.NETWORK_TYPE_NONE:
builder.setRequiredNetworkType(NetworkType.NOT_REQUIRED);
break;
case Requirements.NETWORK_TYPE_ANY:
builder.setRequiredNetworkType(NetworkType.CONNECTED);
break;
case Requirements.NETWORK_TYPE_UNMETERED:
builder.setRequiredNetworkType(NetworkType.UNMETERED);
break;
default:
throw new UnsupportedOperationException();
}
if (requirements.isChargingRequired()) {
builder.setRequiresCharging(true);
}
if (requirements.isIdleRequired() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
builder.setRequiresDeviceIdle(true);
}
return builder.build();
}
private static Data buildInputData(Requirements requirements, String servicePackage, String serviceAction) {
Data.Builder builder = new Data.Builder();
builder.putInt(KEY_REQUIREMENTS, requirements.getRequirements());
builder.putString(KEY_SERVICE_PACKAGE, servicePackage);
builder.putString(KEY_SERVICE_ACTION, serviceAction);
return builder.build();
}
private static OneTimeWorkRequest buildWorkRequest(Constraints constraints, Data inputData) {
OneTimeWorkRequest.Builder builder = new OneTimeWorkRequest.Builder(SchedulerWorker.class);
builder.setConstraints(constraints);
builder.setInputData(inputData);
return builder.build();
}
private static void logd(String message) {
if (DEBUG) {
Log.d(TAG, message);
}
}
/** A {@link Worker} that starts the target service if the requirements are met. */
public static final class SchedulerWorker extends Worker {
private final WorkerParameters workerParams;
private final Context context;
public SchedulerWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
this.workerParams = workerParams;
this.context = context;
}
@NonNull
@Override
public Result doWork() {
logd("SchedulerWorker is started");
Data inputData = workerParams.getInputData();
Assertions.checkNotNull(inputData, "Work started without input data.");
Requirements requirements = new Requirements(inputData.getInt(KEY_REQUIREMENTS, 0));
if (requirements.checkRequirements(context)) {
logd("Requirements are met");
String serviceAction = inputData.getString(KEY_SERVICE_ACTION);
String servicePackage = inputData.getString(KEY_SERVICE_PACKAGE);
Assertions.checkNotNull(serviceAction, "Service action missing.");
Assertions.checkNotNull(servicePackage, "Service package missing.");
Intent intent = new Intent(serviceAction).setPackage(servicePackage);
logd("Starting service action: " + serviceAction + " package: " + servicePackage);
Util.startForegroundService(context, intent);
return Result.success();
} else {
logd("Requirements are not met");
return Result.retry();
}
}
}
}