apps-android-commons/src/org/wikimedia/commons/UploadService.java
YuviPanda 11685e5ec1 (Bug 41703) Validate user tokens & re-login if necessary
Now we send out a request before every upload to check if
the user is logged in. If not, we re-login.

Need to study this more - this adds a little bit of extra latency
to every upload. But if the upload fails because of a login failure,
it will mean we'll have to re-upload the entire thing. Choices.

Also added a debug method to convert XML object to a String. Was
amazed at the power of Java being able to make such a complex task
accomplishable by a single line </s>
2012-11-02 23:22:29 +05:30

171 lines
7.5 KiB
Java

package org.wikimedia.commons;
import java.io.*;
import org.mediawiki.api.*;
import de.mastacode.http.ProgressListener;
import android.app.*;
import android.content.*;
import android.os.*;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.Toast;
import android.net.*;
public class UploadService extends IntentService {
private static final String EXTRA_PREFIX = "org.wikimedia.commons.uploader";
public static final String EXTRA_MEDIA_URI = EXTRA_PREFIX + ".media_uri";
public static final String EXTRA_TARGET_FILENAME = EXTRA_PREFIX + ".filename";
public static final String EXTRA_PAGE_CONTENT = EXTRA_PREFIX + ".content";
public static final String EXTRA_EDIT_SUMMARY = EXTRA_PREFIX + ".summary";
private NotificationManager notificationManager;
private CommonsApplication app;
public UploadService(String name) {
super(name);
}
public UploadService() {
super("UploadService");
}
public static final int NOTIFICATION_DOWNLOAD_IN_PROGRESS = 0;
public static final int NOTIFICATION_DOWNLOAD_COMPLETE = 1;
private class NotificationUpdateProgressListener implements ProgressListener {
Notification curNotification;
String notificationTag;
boolean notificationTitleChanged;
String notificationProgressTitle;
String notificationFinishingTitle;
private int lastPercent = 0;
public NotificationUpdateProgressListener(Notification curNotification, String notificationTag, String notificationProgressTitle, String notificationFinishingTitle) {
this.curNotification = curNotification;
this.notificationTag = notificationTag;
this.notificationProgressTitle = notificationProgressTitle;
this.notificationFinishingTitle = notificationFinishingTitle;
}
@Override
public void onProgress(long transferred, long total) {
RemoteViews curView = curNotification.contentView;
if(!notificationTitleChanged) {
curView.setTextViewText(R.id.uploadNotificationTitle, notificationProgressTitle);
notificationTitleChanged = false;
notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS, curNotification);
}
int percent =(int) ((double)transferred / (double)total * 100);
if(percent > lastPercent) {
curNotification.contentView.setProgressBar(R.id.uploadNotificationProgress, 100, percent, false);
notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS, curNotification);
lastPercent = percent;
}
if(percent == 100) {
// Completed!
curView.setTextViewText(R.id.uploadNotificationTitle, notificationFinishingTitle);
notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS, curNotification);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("Commons", "ZOMG I AM BEING KILLED HALP!");
}
@Override
public void onCreate() {
super.onCreate();
notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
app = (CommonsApplication)this.getApplicationContext();
}
@Override
protected void onHandleIntent(Intent intent) {
MWApi api = app.getApi();
InputStream file;
long length;
ApiResult result;
RemoteViews notificationView;
Bundle extras = intent.getExtras();
Uri mediaUri = (Uri)extras.getParcelable(EXTRA_MEDIA_URI);
String filename = intent.getStringExtra(EXTRA_TARGET_FILENAME);
String pageContents = intent.getStringExtra(EXTRA_PAGE_CONTENT);
String editSummary = intent.getStringExtra(EXTRA_EDIT_SUMMARY);
String notificationTag = mediaUri.toString();
try {
file = this.getContentResolver().openInputStream(mediaUri);
length = this.getContentResolver().openAssetFileDescriptor(mediaUri, "r").getLength();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
notificationView = new RemoteViews(getPackageName(), R.layout.layout_upload_progress);
notificationView.setTextViewText(R.id.uploadNotificationTitle, String.format(getString(R.string.upload_progress_notification_title_start), filename));
notificationView.setProgressBar(R.id.uploadNotificationProgress, 100, 0, false);
Log.d("Commons", "Before execution!");
Notification progressNotification = new NotificationCompat.Builder(this).setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.setAutoCancel(true)
.setContent(notificationView)
.setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), 0))
.getNotification();
notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS, progressNotification);
Log.d("Commons", "Just before");
NotificationUpdateProgressListener notificationUpdater = new NotificationUpdateProgressListener(progressNotification, notificationTag,
String.format(getString(R.string.upload_progress_notification_title_in_progress), filename),
String.format(getString(R.string.upload_progress_notification_title_finishing), filename)
);
try {
if(!api.validateLogin()) {
// Need to revalidate!
if(app.revalidateAuthToken()) {
Log.d("Commons", "Successfully revalidated token!");
} else {
Log.d("Commons", "Unable to revalidate :(");
// TODO: Put up a new notification, ask them to re-login
notificationManager.cancel(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS);
Toast failureToast = Toast.makeText(this, R.string.authentication_failed, Toast.LENGTH_LONG);
failureToast.show();
return;
}
}
result = api.upload(filename, file, length, pageContents, editSummary, notificationUpdater);
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
notificationManager.cancel(notificationTag, NOTIFICATION_DOWNLOAD_IN_PROGRESS);
String descUrl = result.getString("/api/upload/imageinfo/@descriptionurl");
Intent openUploadedPageIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(descUrl));
Notification doneNotification = new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(String.format(getString(R.string.upload_completed_notification_title), filename))
.setContentText(getString(R.string.upload_completed_notification_text))
.setContentIntent(PendingIntent.getActivity(this, 0, openUploadedPageIntent, 0))
.getNotification();
notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_COMPLETE, doneNotification);
}
}