Skip to content

Commit 013e1a5

Browse files
dbrantneslihanturan
authored andcommitted
Fix crash(es) upon upload failure. (commons-app#2699)
* Fix crash(es) upon upload failure. * Further improve Rx structure.
1 parent a32ba45 commit 013e1a5

File tree

3 files changed

+75
-79
lines changed

3 files changed

+75
-79
lines changed

app/src/main/java/fr/free/nrw/commons/mwapi/ApacheHttpClientMediaWikiApi.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ public Single<UploadStash> uploadFile(
944944
long dataLength,
945945
Uri fileUri,
946946
Uri contentProviderUri,
947-
ProgressListener progressListener) throws IOException {
947+
ProgressListener progressListener) {
948948
return Single.fromCallable(() -> {
949949
CustomApiResult result = api.uploadToStash(filename, file, dataLength, getEditToken(), progressListener::onProgress);
950950

app/src/main/java/fr/free/nrw/commons/mwapi/MediaWikiApi.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import java.util.List;
1010

1111
import fr.free.nrw.commons.Media;
12-
import fr.free.nrw.commons.campaigns.CampaignResponseDTO;
1312
import fr.free.nrw.commons.notification.Notification;
1413
import io.reactivex.Observable;
1514
import io.reactivex.Single;
@@ -53,7 +52,7 @@ public interface MediaWikiApi {
5352
@NonNull
5453
Single<UploadStash> uploadFile(String filename, InputStream file,
5554
long dataLength, Uri fileUri, Uri contentProviderUri,
56-
final ProgressListener progressListener) throws IOException;
55+
final ProgressListener progressListener);
5756

5857
@NonNull
5958
Single<UploadResult> uploadFileFinalize(String filename, String filekey,

app/src/main/java/fr/free/nrw/commons/upload/UploadService.java

+73-76
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ private NotificationCompat.Builder getNotificationBuilder(String channelId) {
195195
.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0));
196196
}
197197

198+
@SuppressLint("CheckResult")
198199
private void uploadContribution(Contribution contribution) {
199200
InputStream fileInputStream;
200201
Uri localUri = contribution.getLocalUri();
@@ -222,93 +223,89 @@ private void uploadContribution(Contribution contribution) {
222223

223224
String filename = contribution.getFilename();
224225

225-
try {
226+
NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(notificationTag,
227+
getString(R.string.upload_progress_notification_title_in_progress, contribution.getDisplayTitle()),
228+
getString(R.string.upload_progress_notification_title_finishing, contribution.getDisplayTitle()),
229+
contribution
230+
);
226231

232+
Single.fromCallable(() -> {
227233
if (!mwApi.validateLogin()) {
228234
// Need to revalidate!
229235
if (sessionManager.revalidateAuthToken()) {
230236
Timber.d("Successfully revalidated token!");
231237
} else {
232238
Timber.d("Unable to revalidate :(");
233239
stopForeground(true);
234-
Toast failureToast = Toast.makeText(this, R.string.authentication_failed, Toast.LENGTH_LONG);
235-
failureToast.show();
236-
sessionManager.forceLogin(this);
237-
return;
240+
sessionManager.forceLogin(UploadService.this);
241+
throw new RuntimeException(getString(R.string.authentication_failed));
238242
}
239243
}
240-
NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(notificationTag,
241-
getString(R.string.upload_progress_notification_title_in_progress, contribution.getDisplayTitle()),
242-
getString(R.string.upload_progress_notification_title_finishing, contribution.getDisplayTitle()),
243-
contribution
244-
);
245-
String stashFilename = "Temp_" + contribution.hashCode() + filename;
246-
mwApi.uploadFile(
247-
stashFilename, fileInputStream, contribution.getDataLength(),
248-
localUri, contribution.getContentProviderUri(), notificationUpdater)
249-
.subscribeOn(Schedulers.io())
250-
.observeOn(Schedulers.io())
251-
.flatMap(uploadStash -> {
252-
notificationManager.cancel(NOTIFICATION_UPLOAD_IN_PROGRESS);
253-
254-
Timber.d("Stash upload response 1 is %s", uploadStash.toString());
255-
256-
String resultStatus = uploadStash.getResultStatus();
257-
if (!resultStatus.equals("Success")) {
258-
Timber.d("Contribution upload failed. Wikidata entity won't be edited");
259-
showFailedNotification(contribution);
260-
return Single.never();
261-
} else {
262-
synchronized (unfinishedUploads) {
263-
Timber.d("making sure of uniqueness of name: %s", filename);
264-
String uniqueFilename = findUniqueFilename(filename);
265-
unfinishedUploads.add(uniqueFilename);
266-
return mwApi.uploadFileFinalize(
267-
uniqueFilename,
268-
uploadStash.getFilekey(),
269-
contribution.getPageContents(getApplicationContext()),
270-
contribution.getEditSummary());
271-
}
272-
}
273-
})
274-
.subscribe(uploadResult -> {
275-
Timber.d("Stash upload response 2 is %s", uploadResult.toString());
276-
277-
notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
278-
279-
String resultStatus = uploadResult.getResultStatus();
280-
if (!resultStatus.equals("Success")) {
281-
Timber.d("Contribution upload failed. Wikidata entity won't be edited");
282-
showFailedNotification(contribution);
283-
} else {
284-
String canonicalFilename = uploadResult.getCanonicalFilename();
285-
Timber.d("Contribution upload success. Initiating Wikidata edit for entity id %s",
286-
contribution.getWikiDataEntityId());
287-
wikidataEditService.createClaimWithLogging(contribution.getWikiDataEntityId(), canonicalFilename);
288-
contribution.setFilename(canonicalFilename);
289-
contribution.setImageUrl(uploadResult.getImageUrl());
290-
contribution.setState(Contribution.STATE_COMPLETED);
291-
contribution.setDateUploaded(uploadResult.getDateUploaded());
292-
contributionDao.save(contribution);
244+
return "Temp_" + contribution.hashCode() + filename;
245+
}).flatMap(stashFilename -> mwApi.uploadFile(
246+
stashFilename, fileInputStream, contribution.getDataLength(),
247+
localUri, contribution.getContentProviderUri(), notificationUpdater))
248+
.subscribeOn(Schedulers.io())
249+
.observeOn(Schedulers.io())
250+
.doFinally(() -> {
251+
if (filename != null) {
252+
unfinishedUploads.remove(filename);
253+
}
254+
toUpload--;
255+
if (toUpload == 0) {
256+
// Sync modifications right after all uploads are processed
257+
ContentResolver.requestSync(sessionManager.getCurrentAccount(), BuildConfig.MODIFICATION_AUTHORITY, new Bundle());
258+
stopForeground(true);
259+
}
260+
})
261+
.flatMap(uploadStash -> {
262+
notificationManager.cancel(NOTIFICATION_UPLOAD_IN_PROGRESS);
263+
264+
Timber.d("Stash upload response 1 is %s", uploadStash.toString());
265+
266+
String resultStatus = uploadStash.getResultStatus();
267+
if (!resultStatus.equals("Success")) {
268+
Timber.d("Contribution upload failed. Wikidata entity won't be edited");
269+
showFailedNotification(contribution);
270+
return Single.never();
271+
} else {
272+
synchronized (unfinishedUploads) {
273+
Timber.d("making sure of uniqueness of name: %s", filename);
274+
String uniqueFilename = findUniqueFilename(filename);
275+
unfinishedUploads.add(uniqueFilename);
276+
return mwApi.uploadFileFinalize(
277+
uniqueFilename,
278+
uploadStash.getFilekey(),
279+
contribution.getPageContents(getApplicationContext()),
280+
contribution.getEditSummary());
293281
}
294-
}, throwable -> {
295-
throw new RuntimeException(throwable);
296-
});
297-
} catch (IOException e) {
298-
Timber.w(e,"IOException during upload");
299-
notificationManager.cancel(NOTIFICATION_UPLOAD_IN_PROGRESS);
300-
showFailedNotification(contribution);
301-
} finally {
302-
if (filename != null) {
303-
unfinishedUploads.remove(filename);
304-
}
305-
toUpload--;
306-
if (toUpload == 0) {
307-
// Sync modifications right after all uplaods are processed
308-
ContentResolver.requestSync(sessionManager.getCurrentAccount(), BuildConfig.MODIFICATION_AUTHORITY, new Bundle());
309-
stopForeground(true);
310-
}
311-
}
282+
}
283+
})
284+
.subscribe(uploadResult -> {
285+
Timber.d("Stash upload response 2 is %s", uploadResult.toString());
286+
287+
notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
288+
289+
String resultStatus = uploadResult.getResultStatus();
290+
if (!resultStatus.equals("Success")) {
291+
Timber.d("Contribution upload failed. Wikidata entity won't be edited");
292+
showFailedNotification(contribution);
293+
} else {
294+
String canonicalFilename = uploadResult.getCanonicalFilename();
295+
Timber.d("Contribution upload success. Initiating Wikidata edit for entity id %s",
296+
contribution.getWikiDataEntityId());
297+
wikidataEditService.createClaimWithLogging(contribution.getWikiDataEntityId(), canonicalFilename);
298+
contribution.setFilename(canonicalFilename);
299+
contribution.setImageUrl(uploadResult.getImageUrl());
300+
contribution.setState(Contribution.STATE_COMPLETED);
301+
contribution.setDateUploaded(uploadResult.getDateUploaded());
302+
contributionDao.save(contribution);
303+
}
304+
}, throwable -> {
305+
Timber.w(throwable, "Exception during upload");
306+
notificationManager.cancel(NOTIFICATION_UPLOAD_IN_PROGRESS);
307+
showFailedNotification(contribution);
308+
});
312309
}
313310

314311
@SuppressLint("StringFormatInvalid")

0 commit comments

Comments
 (0)