From 297f3277de705785592ffd6035be649c1a15dbd4 Mon Sep 17 00:00:00 2001 From: YuviPanda Date: Fri, 8 Feb 2013 16:34:41 +0530 Subject: [PATCH] Tap to retry failed uploads implemented UploadService can now be bound to as a local service. Yay! --- .../wikimedia/commons/CommonsApplication.java | 2 + .../java/org/wikimedia/commons/Media.java | 3 ++ .../org/wikimedia/commons/UploadService.java | 44 +++++++++++------ .../commons/contributions/Contribution.java | 36 +++++++++++++- .../contributions/ContributionsActivity.java | 47 ++++++++++++------- .../ContributionsContentProvider.java | 6 ++- 6 files changed, 104 insertions(+), 34 deletions(-) diff --git a/commons/src/main/java/org/wikimedia/commons/CommonsApplication.java b/commons/src/main/java/org/wikimedia/commons/CommonsApplication.java index bfee65b38..53352bab1 100644 --- a/commons/src/main/java/org/wikimedia/commons/CommonsApplication.java +++ b/commons/src/main/java/org/wikimedia/commons/CommonsApplication.java @@ -57,6 +57,8 @@ public class CommonsApplication extends Application { public static final String API_URL = "https://test.wikipedia.org/w/api.php"; public static final String IMAGE_URL_BASE = "https://upload.wikimedia.org/wikipedia/test"; + public static final String DEFAULT_EDIT_SUMMARY = "Uploaded using Android Commons app"; + public static MWApi createMWApi() { DefaultHttpClient client = new DefaultHttpClient(); diff --git a/commons/src/main/java/org/wikimedia/commons/Media.java b/commons/src/main/java/org/wikimedia/commons/Media.java index 0a75d30f0..28126936a 100644 --- a/commons/src/main/java/org/wikimedia/commons/Media.java +++ b/commons/src/main/java/org/wikimedia/commons/Media.java @@ -7,6 +7,9 @@ import java.util.Date; public class Media implements Serializable { + protected Media() { + } + public Uri getLocalUri() { return localUri; } diff --git a/commons/src/main/java/org/wikimedia/commons/UploadService.java b/commons/src/main/java/org/wikimedia/commons/UploadService.java index 37235e05c..d57686d51 100644 --- a/commons/src/main/java/org/wikimedia/commons/UploadService.java +++ b/commons/src/main/java/org/wikimedia/commons/UploadService.java @@ -41,10 +41,8 @@ public class UploadService extends Service { private int toUpload; - private volatile Looper mServiceLooper; - private volatile ServiceHandler mServiceHandler; - private String mName; - private boolean mRedelivery; + private volatile Looper uploadThreadLooper; + private volatile ServiceHandler uploadThreadHandler; private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { @@ -119,14 +117,22 @@ public class UploadService extends Service { @Override public void onDestroy() { super.onDestroy(); - mServiceLooper.quit(); + uploadThreadLooper.quit(); contributionsProviderClient.release(); Log.d("Commons", "ZOMG I AM BEING KILLED HALP!"); } + public class UploadServiceLocalBinder extends Binder { + public UploadService getService() { + return UploadService.this; + } + + } + + private final IBinder localBinder = new UploadServiceLocalBinder(); @Override public IBinder onBind(Intent intent) { - return null; + return localBinder; } @Override @@ -135,8 +141,8 @@ public class UploadService extends Service { HandlerThread thread = new HandlerThread("UploadService"); thread.start(); - mServiceLooper = thread.getLooper(); - mServiceHandler = new ServiceHandler(mServiceLooper); + uploadThreadLooper = thread.getLooper(); + uploadThreadHandler = new ServiceHandler(uploadThreadLooper); notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); app = (CommonsApplication) this.getApplicationContext(); contributionsProviderClient = this.getContentResolver().acquireContentProviderClient(ContributionsContentProvider.AUTHORITY); @@ -179,9 +185,20 @@ public class UploadService extends Service { } private void postMessage(int type, Object obj) { - Message msg = mServiceHandler.obtainMessage(type); + Message msg = uploadThreadHandler.obtainMessage(type); msg.obj = obj; - mServiceHandler.sendMessage(msg); + uploadThreadHandler.sendMessage(msg); + } + + + public void queueContribution(Contribution contribution) { + contribution.setState(Contribution.STATE_QUEUED); + contribution.setTransferred(0); + contribution.setContentProviderClient(contributionsProviderClient); + + contribution.save(); + + postMessage(ACTION_UPLOAD_FILE, contribution); } @Override @@ -193,13 +210,10 @@ public class UploadService extends Service { notificationManager.notify(NOTIFICATION_UPLOAD_IN_PROGRESS, curProgressNotification); } + Log.d("Commons", "Received startcommand"); Contribution contribution = mediaFromIntent(intent); - contribution.setState(Contribution.STATE_QUEUED); - contribution.setContentProviderClient(contributionsProviderClient); + queueContribution(contribution); - contribution.save(); - - postMessage(ACTION_UPLOAD_FILE, contribution); return START_REDELIVER_INTENT; } diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java b/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java index 8c7b080d0..40aae4ebe 100644 --- a/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java +++ b/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java @@ -5,6 +5,7 @@ import java.util.*; import android.content.ContentProviderClient; import android.content.ContentValues; +import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.*; import android.os.RemoteException; @@ -34,7 +35,7 @@ public class Contribution extends Media { private long transferred; public String getEditSummary() { - return editSummary; + return editSummary != null ? editSummary : CommonsApplication.DEFAULT_EDIT_SUMMARY; } public Uri getContentUri() { @@ -142,6 +143,26 @@ public class Contribution extends Media { this.imageUrl = imageUrl; } + private Contribution() { + // Empty constructor for being constructed by our static methods + } + + public static Contribution fromCursor(Cursor cursor) { + // Hardcoding column positions! + Contribution c = new Contribution(); + c.contentUri = ContributionsContentProvider.uriForId(cursor.getInt(0)); + c.filename = cursor.getString(1); + c.localUri = TextUtils.isEmpty(cursor.getString(2)) ? null : Uri.parse(cursor.getString(2)); + c.imageUrl = cursor.getString(3); + c.timestamp = cursor.getLong(4) == 0 ? null : new Date(cursor.getLong(4)); + c.state = cursor.getInt(5); + c.dataLength = cursor.getLong(6); + c.dateUploaded = cursor.getLong(7) == 0 ? null : new Date(cursor.getLong(7)); + c.transferred = cursor.getLong(8); + return c; + } + + public static class Table { public static final String TABLE_NAME = "contributions"; @@ -156,6 +177,19 @@ public class Contribution extends Media { public static final String COLUMN_UPLOADED = "uploaded"; public static final String COLUMN_TRANSFERRED = "transferred"; // Currently transferred number of bytes + // NOTE! KEEP IN SAME ORDER AS THEY ARE DEFINED UP THERE. HELPS HARD CODE COLUMN INDICES. + public static final String[] ALL_FIELDS = { + COLUMN_ID, + COLUMN_FILENAME, + COLUMN_LOCAL_URI, + COLUMN_IMAGE_URL, + COLUMN_TIMESTAMP, + COLUMN_STATE, + COLUMN_LENGTH, + COLUMN_UPLOADED, + COLUMN_TRANSFERRED + }; + private static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " (" + "_id INTEGER PRIMARY KEY," diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java index 5d263bfe5..89157d847 100644 --- a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java @@ -3,6 +3,7 @@ package org.wikimedia.commons.contributions; import android.graphics.Bitmap; import android.net.Uri; import android.os.Environment; +import android.os.IBinder; import android.provider.MediaStore; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; @@ -17,10 +18,7 @@ import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.ViewGroup; -import android.widget.GridView; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.TextView; +import android.widget.*; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.ActionMode; import com.actionbarsherlock.view.Menu; @@ -53,6 +51,18 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load super(WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE); } + private UploadService uploadService; + private ServiceConnection uploadServiceConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName componentName, IBinder binder) { + uploadService = ((UploadService.UploadServiceLocalBinder)binder).getService(); + } + + public void onServiceDisconnected(ComponentName componentName) { + // this should never happen + throw new RuntimeException("UploadService died but the rest of the process did not!"); + } + }; + private class ContributionAdapter extends CursorAdapter { private final int COLUMN_FILENAME; @@ -127,17 +137,6 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load private DisplayImageOptions contributionDisplayOptions; - private String[] CONTRIBUTIONS_PROJECTION = { - Contribution.Table.COLUMN_ID, - Contribution.Table.COLUMN_FILENAME, - Contribution.Table.COLUMN_LOCAL_URI, - Contribution.Table.COLUMN_STATE, - Contribution.Table.COLUMN_UPLOADED, - Contribution.Table.COLUMN_LENGTH, - Contribution.Table.COLUMN_TRANSFERRED, - Contribution.Table.COLUMN_IMAGE_URL - }; - private String CONTRIBUTION_SELECTION = ""; /* This sorts in the following order: @@ -171,11 +170,25 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load .cacheOnDisc() .resetViewBeforeLoading().build(); - Cursor allContributions = getContentResolver().query(ContributionsContentProvider.BASE_URI, CONTRIBUTIONS_PROJECTION, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT); + bindService(new Intent(this, UploadService.class), uploadServiceConnection, Context.BIND_AUTO_CREATE); + + Cursor allContributions = getContentResolver().query(ContributionsContentProvider.BASE_URI, Contribution.Table.ALL_FIELDS, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT); contributionsAdapter = new ContributionAdapter(this, allContributions, 0); contributionsList.setAdapter(contributionsAdapter); getSupportLoaderManager().initLoader(0, null, this); + + contributionsList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + public void onItemClick(AdapterView adapterView, View view, int position, long item) { + Cursor cursor = (Cursor)adapterView.getItemAtPosition(position); + Contribution c = Contribution.fromCursor(cursor); + if(c.getState() == Contribution.STATE_FAILED) { + uploadService.queueContribution(c); + Log.d("Commons", "Restarting for" + c.toContentValues().toString()); + } + Log.d("Commons", "You clicked on:" + c.toContentValues().toString()); + } + }); } @Override @@ -283,7 +296,7 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load } public Loader onCreateLoader(int i, Bundle bundle) { - return new CursorLoader(this, ContributionsContentProvider.BASE_URI, CONTRIBUTIONS_PROJECTION, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT); + return new CursorLoader(this, ContributionsContentProvider.BASE_URI, Contribution.Table.ALL_FIELDS, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT); } public void onLoadFinished(Loader cursorLoader, Cursor cursor) { diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsContentProvider.java b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsContentProvider.java index f4a7e21dc..2a01de386 100644 --- a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsContentProvider.java +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsContentProvider.java @@ -25,10 +25,14 @@ public class ContributionsContentProvider extends ContentProvider{ private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); static { uriMatcher.addURI(AUTHORITY, BASE_PATH, CONTRIBUTIONS); - uriMatcher.addURI(AUTHORITY, BASE_PATH + "/*", CONTRIBUTIONS_ID); + uriMatcher.addURI(AUTHORITY, BASE_PATH + "/#", CONTRIBUTIONS_ID); } + public static Uri uriForId(int id) { + return Uri.parse(BASE_URI.toString() + "/" + id); + } + private DBOpenHelper dbOpenHelper; @Override public boolean onCreate() {