2
2
3
3
import android .content .Context ;
4
4
import android .os .Bundle ;
5
-
6
5
import androidx .annotation .NonNull ;
7
6
import androidx .work .BackoffPolicy ;
8
7
import androidx .work .Constraints ;
23
22
import java .io .FileInputStream ;
24
23
import java .io .IOException ;
25
24
import java .io .ObjectInputStream ;
25
+ import java .lang .ref .WeakReference ;
26
26
import java .util .List ;
27
+ import java .util .Map ;
28
+ import java .util .concurrent .ConcurrentHashMap ;
27
29
import java .util .concurrent .TimeUnit ;
28
30
29
31
public class AndroidJobStrategy implements BackgroundRequestStrategy {
30
32
31
33
private static final String JOB_TAG = "CLD" ;
32
34
35
+ private static final Map <String , WeakReference <Thread >> threads = new ConcurrentHashMap <>();
36
+ private static final Object threadsMapLockObject = new Object ();
37
+
33
38
private Context context ;
34
39
35
40
public static OneTimeWorkRequest adapt (UploadRequest <?> request , File payloadFile ) {
@@ -43,7 +48,7 @@ public static OneTimeWorkRequest adapt(UploadRequest<?> request, File payloadFil
43
48
44
49
Data inputData = request .buildPayload (payloadFile );
45
50
46
- return new OneTimeWorkRequest .Builder (UploadJob .class ).setBackoffCriteria (adaptBackoffPolicy (policy .getBackoffPolicy ()), policy .getBackoffMillis (), TimeUnit .MILLISECONDS ).setInputData (inputData ).setConstraints (constraints ).addTag (JOB_TAG ).build ();
51
+ return new OneTimeWorkRequest .Builder (UploadJob .class ).setBackoffCriteria (adaptBackoffPolicy (policy .getBackoffPolicy ()), policy .getBackoffMillis (), TimeUnit .MILLISECONDS ).setInputData (inputData ).setConstraints (constraints ).addTag (request . getRequestId () ).build ();
47
52
}
48
53
49
54
private static BackoffPolicy adaptBackoffPolicy (UploadPolicy .BackoffPolicy backoffPolicy ) {
@@ -99,15 +104,48 @@ public void executeRequestsNow(int howMany) {
99
104
@ Override
100
105
public boolean cancelRequest (String requestId ) {
101
106
Operation operation = WorkManager .getInstance (context ).cancelAllWorkByTag (requestId );
107
+ killThread (requestId );
102
108
return operation .getResult ().isCancelled ();
103
109
}
104
110
105
111
@ Override
106
112
public int cancelAllRequests () {
107
113
WorkManager .getInstance (context ).cancelAllWork ();
114
+ killAllThreads ();
108
115
return 0 ;
109
116
}
110
117
118
+ private void killThread (String requestId ) {
119
+ synchronized (threadsMapLockObject ) {
120
+ WeakReference <Thread > ref = threads .remove (requestId );
121
+ if (ref != null ) {
122
+ Thread thread = ref .get ();
123
+ if (thread != null ) {
124
+ thread .interrupt ();
125
+ }
126
+
127
+ ref .clear ();
128
+ }
129
+ }
130
+ }
131
+
132
+ private void killAllThreads () {
133
+ synchronized (threadsMapLockObject ) {
134
+ for (String requestId : threads .keySet ()) {
135
+ WeakReference <Thread > ref = threads .get (requestId );
136
+ Thread thread = ref .get ();
137
+
138
+ if (thread != null ) {
139
+ thread .interrupt ();
140
+ }
141
+
142
+ ref .clear ();
143
+ }
144
+
145
+ threads .clear ();
146
+ }
147
+ }
148
+
111
149
@ Override
112
150
public int getPendingImmediateJobsCount () {
113
151
return getJobCountByState (WorkInfo .State .ENQUEUED );
@@ -137,36 +175,62 @@ public static final class UploadJob extends Worker {
137
175
private final Context context ;
138
176
private final WorkerParameters workParams ;
139
177
178
+ private String requestId ;
179
+
140
180
public UploadJob (@ NonNull Context context , @ NonNull WorkerParameters workerParams ) {
141
181
super (context , workerParams );
142
182
this .context = context ;
143
183
this .workParams = workerParams ;
144
184
}
145
185
186
+ @ Override
187
+ public void onStopped () {
188
+ super .onStopped ();
189
+ unregisterThread (requestId );
190
+ }
191
+
192
+ private void registerThread (String requestId , Thread thread ) {
193
+ synchronized (threadsMapLockObject ) {
194
+ threads .put (requestId , new WeakReference <>(thread ));
195
+ }
196
+ }
197
+
198
+ private void unregisterThread (String requestId ) {
199
+ synchronized (threadsMapLockObject ) {
200
+ if (requestId != null ) {
201
+ WeakReference <Thread > removed = threads .remove (requestId );
202
+ if (removed != null ) {
203
+ removed .clear ();
204
+ }
205
+ }
206
+ }
207
+ }
208
+
146
209
@ NonNull
147
210
@ Override
148
211
public Result doWork () {
149
- // Removed Wakelock logic as it causes RuntimeException ("WakeLock under-locked")
150
212
151
213
// Prepare extract payload data from temporary file.
152
214
String payloadFilePath = workParams .getInputData ().getString (UploadRequest .PayloadData .KEY );
153
215
if (payloadFilePath == null ) {
154
216
// NO Payload input file created prior to request.
155
217
return Result .failure ();
156
218
}
219
+
157
220
File payloadFile = new File (payloadFilePath );
158
221
try (ObjectInputStream ois = new ObjectInputStream (new FileInputStream (payloadFile ))) {
159
222
UploadRequest .PayloadData payloadData = (UploadRequest .PayloadData ) ois .readObject ();
160
223
AndroidJobStrategy .AndroidJobRequestParams jobInputData = new AndroidJobStrategy .AndroidJobRequestParams (payloadData );
161
-
162
- // call the generic processor:
163
- UploadStatus result = MediaManager .get ().processRequest (context , jobInputData );
224
+ requestId = payloadData . getRequestId ();
225
+ registerThread ( requestId , Thread . currentThread ());
226
+ UploadStatus result = MediaManager .get ().processRequest (context , jobInputData ); // Replace this with your actual upload logic
164
227
return adaptResult (result );
165
-
166
- } catch (NullPointerException | IOException | ClassNotFoundException e ) {
228
+ } catch (NullPointerException | IOException | ClassNotFoundException e ) {
167
229
// Unable to deserialize payload data from file.
168
230
e .printStackTrace ();
169
231
return Result .failure ();
232
+ } finally {
233
+ unregisterThread (requestId );
170
234
}
171
235
}
172
236
0 commit comments