kopia lustrzana https://github.com/ryukoposting/Signal-Android
Only schedule one job per constraint set.
rodzic
893749fcab
commit
b077c9b4f3
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.jobmanager;
|
||||||
import android.app.job.JobInfo;
|
import android.app.job.JobInfo;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
public interface Constraint {
|
public interface Constraint {
|
||||||
|
@ -14,6 +15,15 @@ public interface Constraint {
|
||||||
@RequiresApi(26)
|
@RequiresApi(26)
|
||||||
void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder);
|
void applyToJobInfo(@NonNull JobInfo.Builder jobInfoBuilder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If you do something in {@link #applyToJobInfo} you should return something here.
|
||||||
|
* <p>
|
||||||
|
* It is sorted and concatenated with other constraints key parts to form a unique job id.
|
||||||
|
*/
|
||||||
|
default @Nullable String getJobSchedulerKeyPart() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
interface Factory<T extends Constraint> {
|
interface Factory<T extends Constraint> {
|
||||||
T create();
|
T create();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,26 +6,23 @@ import android.app.job.JobParameters;
|
||||||
import android.app.job.JobScheduler;
|
import android.app.job.JobScheduler;
|
||||||
import android.app.job.JobService;
|
import android.app.job.JobService;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
|
import com.annimon.stream.Collectors;
|
||||||
|
import com.annimon.stream.Stream;
|
||||||
|
|
||||||
import org.signal.core.util.logging.Log;
|
import org.signal.core.util.logging.Log;
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
@RequiresApi(26)
|
@RequiresApi(26)
|
||||||
public class JobSchedulerScheduler implements Scheduler {
|
public final class JobSchedulerScheduler implements Scheduler {
|
||||||
|
|
||||||
private static final String TAG = JobSchedulerScheduler.class.getSimpleName();
|
private static final String TAG = Log.tag(JobSchedulerScheduler.class);
|
||||||
|
|
||||||
private static final String PREF_NAME = "JobSchedulerScheduler_prefs";
|
|
||||||
private static final String PREF_NEXT_ID = "pref_next_id";
|
|
||||||
|
|
||||||
private static final int MAX_ID = 20;
|
|
||||||
|
|
||||||
private final Application application;
|
private final Application application;
|
||||||
|
|
||||||
|
@ -37,14 +34,23 @@ public class JobSchedulerScheduler implements Scheduler {
|
||||||
@Override
|
@Override
|
||||||
public void schedule(long delay, @NonNull List<Constraint> constraints) {
|
public void schedule(long delay, @NonNull List<Constraint> constraints) {
|
||||||
JobScheduler jobScheduler = application.getSystemService(JobScheduler.class);
|
JobScheduler jobScheduler = application.getSystemService(JobScheduler.class);
|
||||||
int currentId = getCurrentId();
|
|
||||||
|
|
||||||
if (constraints.isEmpty() && jobScheduler.getPendingJob(currentId) != null) {
|
String constraintNames = constraints.isEmpty() ? ""
|
||||||
Log.d(TAG, "Skipping JobScheduler enqueue because we have no constraints and there's already one pending.");
|
: Stream.of(constraints)
|
||||||
|
.map(Constraint::getJobSchedulerKeyPart)
|
||||||
|
.withoutNulls()
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.joining("-"));
|
||||||
|
|
||||||
|
int jobId = constraintNames.hashCode();
|
||||||
|
|
||||||
|
if (jobScheduler.getPendingJob(jobId) != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(getAndUpdateNextId(), new ComponentName(application, SystemService.class))
|
Log.i(TAG, String.format(Locale.US, "JobScheduler enqueue of %s (%d)", constraintNames, jobId));
|
||||||
|
|
||||||
|
JobInfo.Builder jobInfoBuilder = new JobInfo.Builder(jobId, new ComponentName(application, SystemService.class))
|
||||||
.setMinimumLatency(delay)
|
.setMinimumLatency(delay)
|
||||||
.setPersisted(true);
|
.setPersisted(true);
|
||||||
|
|
||||||
|
@ -55,21 +61,6 @@ public class JobSchedulerScheduler implements Scheduler {
|
||||||
jobScheduler.schedule(jobInfoBuilder.build());
|
jobScheduler.schedule(jobInfoBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getCurrentId() {
|
|
||||||
SharedPreferences prefs = application.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
|
||||||
return prefs.getInt(PREF_NEXT_ID, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getAndUpdateNextId() {
|
|
||||||
SharedPreferences prefs = application.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
|
||||||
int returnedId = prefs.getInt(PREF_NEXT_ID, 0);
|
|
||||||
int nextId = returnedId + 1 > MAX_ID ? 0 : returnedId + 1;
|
|
||||||
|
|
||||||
prefs.edit().putInt(PREF_NEXT_ID, nextId).apply();
|
|
||||||
|
|
||||||
return returnedId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(api = 26)
|
@RequiresApi(api = 26)
|
||||||
public static class SystemService extends JobService {
|
public static class SystemService extends JobService {
|
||||||
|
|
||||||
|
@ -77,6 +68,8 @@ public class JobSchedulerScheduler implements Scheduler {
|
||||||
public boolean onStartJob(JobParameters params) {
|
public boolean onStartJob(JobParameters params) {
|
||||||
JobManager jobManager = ApplicationDependencies.getJobManager();
|
JobManager jobManager = ApplicationDependencies.getJobManager();
|
||||||
|
|
||||||
|
Log.i(TAG, "Waking due to job: " + params.getJobId());
|
||||||
|
|
||||||
jobManager.addOnEmptyQueueListener(new JobManager.EmptyQueueListener() {
|
jobManager.addOnEmptyQueueListener(new JobManager.EmptyQueueListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onQueueEmpty() {
|
public void onQueueEmpty() {
|
||||||
|
|
|
@ -33,6 +33,11 @@ public class ChargingConstraint implements Constraint {
|
||||||
jobInfoBuilder.setRequiresCharging(true);
|
jobInfoBuilder.setRequiresCharging(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJobSchedulerKeyPart() {
|
||||||
|
return "CHARGING";
|
||||||
|
}
|
||||||
|
|
||||||
public static final class Factory implements Constraint.Factory<ChargingConstraint> {
|
public static final class Factory implements Constraint.Factory<ChargingConstraint> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.net.ConnectivityManager;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.jobmanager.Constraint;
|
import org.thoughtcrime.securesms.jobmanager.Constraint;
|
||||||
|
@ -37,6 +38,11 @@ public class NetworkConstraint implements Constraint {
|
||||||
jobInfoBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
|
jobInfoBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getJobSchedulerKeyPart() {
|
||||||
|
return "NETWORK";
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isMet(@NonNull Context context) {
|
public static boolean isMet(@NonNull Context context) {
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
|
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
|
||||||
|
|
Ładowanie…
Reference in New Issue