1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
package it.niedermann.nextcloud.deck.remote;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import androidx.preference.PreferenceManager;
import androidx.work.Constraints;
import androidx.work.ExistingPeriodicWorkPolicy;
import androidx.work.ListenableWorker;
import androidx.work.NetworkType;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import it.niedermann.nextcloud.deck.DeckLog;
import it.niedermann.nextcloud.deck.R;
import it.niedermann.nextcloud.deck.model.Account;
import it.niedermann.nextcloud.deck.remote.api.ResponseCallback;
import it.niedermann.nextcloud.deck.repository.BaseRepository;
import it.niedermann.nextcloud.deck.repository.SyncRepository;
public class SyncWorker extends Worker {
private static final String WORKER_TAG = "it.niedermann.nextcloud.deck.background_synchronization";
private static final Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
private final BaseRepository baseRepository;
private final SharedPreferences.Editor editor;
public SyncWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
this.baseRepository = new BaseRepository(context);
this.editor = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit();
}
@NonNull
@Override
public Result doWork() {
DeckLog.info("Starting background synchronization");
editor.putLong(getApplicationContext().getString(R.string.shared_preference_last_background_sync), System.currentTimeMillis());
editor.apply();
try {
return synchronizeEverything(getApplicationContext(), baseRepository.readAccountsDirectly());
} catch (NextcloudFilesAppAccountNotFoundException e) {
return Result.failure();
} finally {
DeckLog.info("Finishing background synchronization.");
}
}
@WorkerThread
private ListenableWorker.Result synchronizeEverything(@NonNull Context context, @NonNull List<Account> accounts) throws NextcloudFilesAppAccountNotFoundException {
if (accounts.isEmpty()) {
return Result.success();
}
final var success = new AtomicBoolean(true);
final var latch = new CountDownLatch(accounts.size());
try {
for (Account account : accounts) {
new SyncRepository(context, account).synchronize(new ResponseCallback<>(account) {
@Override
public void onResponse(Boolean response) {
success.set(success.get() && Boolean.TRUE.equals(response));
latch.countDown();
}
@Override
public void onError(Throwable throwable) {
success.set(false);
super.onError(throwable);
latch.countDown();
}
});
}
latch.await();
return success.get() ? Result.success() : Result.failure();
} catch (InterruptedException e) {
DeckLog.logError(e);
return Result.failure();
}
}
public static void update(@NonNull Context context) {
final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
update(context, sharedPreferences.getString(context.getString(R.string.pref_key_background_sync), context.getString(R.string.pref_value_background_15_minutes)));
}
public static void update(@NonNull Context context, String preferenceValue) {
deregister(context);
int repeatInterval = -1;
TimeUnit unit = null;
if (context.getString(R.string.pref_value_background_15_minutes).equals(preferenceValue)) {
repeatInterval = 15;
unit = TimeUnit.MINUTES;
} else if (context.getString(R.string.pref_value_background_1_hour).equals(preferenceValue)) {
repeatInterval = 1;
unit = TimeUnit.HOURS;
} else if (context.getString(R.string.pref_value_background_6_hours).equals(preferenceValue)) {
repeatInterval = 6;
unit = TimeUnit.HOURS;
}
if (unit == null) {
DeckLog.info("Do not register a new", SyncWorker.class.getSimpleName(), "because setting", preferenceValue, "is not a valid time frame");
} else {
final PeriodicWorkRequest work = new PeriodicWorkRequest.Builder(SyncWorker.class, repeatInterval, unit)
.setConstraints(constraints).build();
DeckLog.info("Registering", SyncWorker.class.getSimpleName(), "running each", repeatInterval, unit);
WorkManager.getInstance(context.getApplicationContext()).enqueueUniquePeriodicWork(SyncWorker.WORKER_TAG, ExistingPeriodicWorkPolicy.REPLACE, work);
}
}
private static void deregister(@NonNull Context context) {
DeckLog.info("Deregistering all", SyncWorker.class.getSimpleName(), "with tag", WORKER_TAG);
WorkManager.getInstance(context.getApplicationContext()).cancelAllWorkByTag(WORKER_TAG);
}
}
|