mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
Added progress updater in UploadService to show upload progress in no… (#3156)
* added progress updater in UploadService to show upload progress in notification * formatting changes
This commit is contained in:
parent
41789980c7
commit
f13a4d4da7
3 changed files with 116 additions and 43 deletions
|
|
@ -0,0 +1,86 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.RequestBody;
|
||||
import okio.Buffer;
|
||||
import okio.BufferedSink;
|
||||
import okio.ForwardingSink;
|
||||
import okio.Okio;
|
||||
import okio.Sink;
|
||||
|
||||
/**
|
||||
* Decorates an OkHttp request body to count the number of bytes written when writing it. Can
|
||||
* decorate any request body, but is most useful for tracking the upload progress of large multipart
|
||||
* requests.
|
||||
*
|
||||
* @author Ashish Kumar
|
||||
*/
|
||||
public class CountingRequestBody extends RequestBody {
|
||||
|
||||
protected RequestBody delegate;
|
||||
protected Listener listener;
|
||||
|
||||
protected CountingSink countingSink;
|
||||
|
||||
public CountingRequestBody(RequestBody delegate, Listener listener) {
|
||||
this.delegate = delegate;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaType contentType() {
|
||||
return delegate.contentType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() {
|
||||
try {
|
||||
return delegate.contentLength();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(BufferedSink sink) throws IOException {
|
||||
|
||||
countingSink = new CountingSink(sink);
|
||||
BufferedSink bufferedSink = Okio.buffer(countingSink);
|
||||
|
||||
delegate.writeTo(bufferedSink);
|
||||
|
||||
bufferedSink.flush();
|
||||
}
|
||||
|
||||
protected final class CountingSink extends ForwardingSink {
|
||||
|
||||
private long bytesWritten = 0;
|
||||
|
||||
public CountingSink(Sink delegate) {
|
||||
super(delegate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Buffer source, long byteCount) throws IOException {
|
||||
super.write(source, byteCount);
|
||||
|
||||
bytesWritten += byteCount;
|
||||
listener.onRequestProgress(bytesWritten, contentLength());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
* Will be triggered when write progresses
|
||||
* @param bytesWritten
|
||||
* @param contentLength
|
||||
*/
|
||||
void onRequestProgress(long bytesWritten, long contentLength);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,23 +1,20 @@
|
|||
package fr.free.nrw.commons.upload;
|
||||
|
||||
import static fr.free.nrw.commons.di.NetworkingModule.NAMED_COMMONS_CSRF;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.wikipedia.csrf.CsrfTokenClient;
|
||||
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.upload.UploadService.NotificationUpdateProgressListener;
|
||||
import io.reactivex.Observable;
|
||||
import java.io.File;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import io.reactivex.Observable;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.MultipartBody;
|
||||
import okhttp3.RequestBody;
|
||||
|
||||
import static fr.free.nrw.commons.di.NetworkingModule.NAMED_COMMONS_CSRF;
|
||||
import org.wikipedia.csrf.CsrfTokenClient;
|
||||
|
||||
@Singleton
|
||||
public class UploadClient {
|
||||
|
|
@ -31,11 +28,16 @@ public class UploadClient {
|
|||
this.csrfTokenClient = csrfTokenClient;
|
||||
}
|
||||
|
||||
Observable<UploadResult> uploadFileToStash(Context context, String filename, File file) {
|
||||
RequestBody requestFile = RequestBody
|
||||
Observable<UploadResult> uploadFileToStash(Context context, String filename, File file,
|
||||
NotificationUpdateProgressListener notificationUpdater) {
|
||||
RequestBody requestBody = RequestBody
|
||||
.create(MediaType.parse(FileUtils.getMimeType(context, Uri.parse(file.getPath()))), file);
|
||||
|
||||
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", filename, requestFile);
|
||||
CountingRequestBody countingRequestBody = new CountingRequestBody(requestBody,
|
||||
(bytesWritten, contentLength) -> notificationUpdater
|
||||
.onProgress(bytesWritten, contentLength));
|
||||
|
||||
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", filename, countingRequestBody);
|
||||
RequestBody fileNameRequestBody = RequestBody.create(okhttp3.MultipartBody.FORM, filename);
|
||||
RequestBody tokenRequestBody;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -8,23 +8,8 @@ import android.content.Intent;
|
|||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import fr.free.nrw.commons.BuildConfig;
|
||||
import fr.free.nrw.commons.CommonsApplication;
|
||||
import fr.free.nrw.commons.HandlerService;
|
||||
|
|
@ -40,6 +25,13 @@ import fr.free.nrw.commons.utils.CommonsDateUtil;
|
|||
import fr.free.nrw.commons.wikidata.WikidataEditService;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.inject.Inject;
|
||||
import timber.log.Timber;
|
||||
|
||||
public class UploadService extends HandlerService<Contribution> {
|
||||
|
|
@ -80,7 +72,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
super("UploadService");
|
||||
}
|
||||
|
||||
private class NotificationUpdateProgressListener implements MediaWikiApi.ProgressListener {
|
||||
protected class NotificationUpdateProgressListener implements MediaWikiApi.ProgressListener {
|
||||
|
||||
String notificationTag;
|
||||
boolean notificationTitleChanged;
|
||||
|
|
@ -202,29 +194,20 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
|
||||
@SuppressLint("CheckResult")
|
||||
private void uploadContribution(Contribution contribution) {
|
||||
InputStream fileInputStream;
|
||||
Uri localUri = contribution.getLocalUri();
|
||||
if (localUri == null || localUri.getPath() == null) {
|
||||
Timber.d("localUri/path is null");
|
||||
return;
|
||||
}
|
||||
String notificationTag = localUri.toString();
|
||||
File file1;
|
||||
try {
|
||||
file1 = new File(localUri.getPath());
|
||||
fileInputStream = new FileInputStream(file1);
|
||||
} catch (FileNotFoundException e) {
|
||||
Timber.d("File not found");
|
||||
Toast fileNotFound = Toast.makeText(this, R.string.upload_failed, Toast.LENGTH_LONG);
|
||||
fileNotFound.show();
|
||||
return;
|
||||
}
|
||||
File localFile = new File(localUri.getPath());
|
||||
|
||||
Timber.d("Before execution!");
|
||||
curNotification.setContentTitle(getString(R.string.upload_progress_notification_title_start, contribution.getDisplayTitle()))
|
||||
.setContentText(getResources().getQuantityString(R.plurals.uploads_pending_notification_indicator, toUpload, toUpload))
|
||||
.setTicker(getString(R.string.upload_progress_notification_title_in_progress, contribution.getDisplayTitle()));
|
||||
notificationManager.notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
|
||||
notificationManager
|
||||
.notify(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS, curNotification.build());
|
||||
|
||||
String filename = contribution.getFilename();
|
||||
|
||||
|
|
@ -235,7 +218,9 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
);
|
||||
|
||||
Observable.fromCallable(() -> "Temp_" + contribution.hashCode() + filename)
|
||||
.flatMap(stashFilename -> uploadClient.uploadFileToStash(getApplicationContext(), stashFilename, file1))
|
||||
.flatMap(stashFilename -> uploadClient
|
||||
.uploadFileToStash(getApplicationContext(), stashFilename, localFile,
|
||||
notificationUpdater))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.doFinally(() -> {
|
||||
|
|
@ -250,7 +235,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
}
|
||||
})
|
||||
.flatMap(uploadStash -> {
|
||||
notificationManager.cancel(NOTIFICATION_UPLOAD_IN_PROGRESS);
|
||||
notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
|
||||
|
||||
Timber.d("Stash upload response 1 is %s", uploadStash.toString());
|
||||
|
||||
|
|
@ -293,7 +278,7 @@ public class UploadService extends HandlerService<Contribution> {
|
|||
}
|
||||
}, throwable -> {
|
||||
Timber.w(throwable, "Exception during upload");
|
||||
notificationManager.cancel(NOTIFICATION_UPLOAD_IN_PROGRESS);
|
||||
notificationManager.cancel(notificationTag, NOTIFICATION_UPLOAD_IN_PROGRESS);
|
||||
showFailedNotification(contribution);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue