From 2260078fa7a31405369f4d54e284f1a5bbe0c2fd Mon Sep 17 00:00:00 2001 From: YuviPanda Date: Fri, 1 Feb 2013 02:23:29 +0530 Subject: [PATCH] Added working (sortof) My Contributions screen Uses CursorLoader to appropriately load and update stuff as things change. Need to update UI to show things properly. Also refactored things a fair bit. --- commons/AndroidManifest.xml | 2 +- commons/res/layout/activity_contributions.xml | 3 + .../commons/ContributionsActivity.java | 52 ----------- .../org/wikimedia/commons/UploadService.java | 42 ++++----- .../commons/contributions/Contribution.java | 32 +++++-- .../contributions/ContributionsActivity.java | 87 +++++++++++++++++++ .../ContributionsContentProvider.java | 43 ++++++++- 7 files changed, 177 insertions(+), 84 deletions(-) delete mode 100644 commons/src/main/java/org/wikimedia/commons/ContributionsActivity.java create mode 100644 commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java diff --git a/commons/AndroidManifest.xml b/commons/AndroidManifest.xml index 971e9238d..9662e0cd8 100644 --- a/commons/AndroidManifest.xml +++ b/commons/AndroidManifest.xml @@ -40,7 +40,7 @@ diff --git a/commons/res/layout/activity_contributions.xml b/commons/res/layout/activity_contributions.xml index fbd3daaad..01292f219 100644 --- a/commons/res/layout/activity_contributions.xml +++ b/commons/res/layout/activity_contributions.xml @@ -4,5 +4,8 @@ android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> + \ No newline at end of file diff --git a/commons/src/main/java/org/wikimedia/commons/ContributionsActivity.java b/commons/src/main/java/org/wikimedia/commons/ContributionsActivity.java deleted file mode 100644 index 7f2a8d2ff..000000000 --- a/commons/src/main/java/org/wikimedia/commons/ContributionsActivity.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.wikimedia.commons; - -import android.content.BroadcastReceiver; -import android.content.*; -import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import com.actionbarsherlock.app.SherlockActivity; -import org.wikimedia.commons.contributions.Contribution; - -public class ContributionsActivity extends SherlockActivity { - - private LocalBroadcastManager localBroadcastManager; - - private String[] broadcastsToReceive = { - UploadService.INTENT_UPLOAD_STARTED, - UploadService.INTENT_UPLOAD_QUEUED, - UploadService.INTENT_UPLOAD_PROGRESS, - UploadService.INTENT_UPLOAD_COMPLETE - }; - - private BroadcastReceiver messageReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - Contribution contribution = (Contribution)intent.getParcelableExtra(UploadService.EXTRA_MEDIA); - Log.d("Commons", "Completed " + intent.getAction() +" of " + contribution.getFilename()); - } - }; - - @Override - protected void onResume() { - super.onResume(); - for(int i=0; i < broadcastsToReceive.length; i++) { - localBroadcastManager.registerReceiver(messageReceiver, new IntentFilter(broadcastsToReceive[i])); - } - } - - @Override - protected void onPause() { - super.onPause(); - for(int i=0; i < broadcastsToReceive.length; i++) { - localBroadcastManager.unregisterReceiver(messageReceiver); - } - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - localBroadcastManager = LocalBroadcastManager.getInstance(this); - setContentView(R.layout.activity_contributions); - } -} diff --git a/commons/src/main/java/org/wikimedia/commons/UploadService.java b/commons/src/main/java/org/wikimedia/commons/UploadService.java index 3f500677c..e56ff9e13 100644 --- a/commons/src/main/java/org/wikimedia/commons/UploadService.java +++ b/commons/src/main/java/org/wikimedia/commons/UploadService.java @@ -24,12 +24,9 @@ import android.net.*; public class UploadService extends IntentService { private static final String EXTRA_PREFIX = "org.wikimedia.commons.upload"; - public static final String INTENT_UPLOAD_COMPLETE = EXTRA_PREFIX + ".completed"; - public static final String INTENT_UPLOAD_STARTED = EXTRA_PREFIX + ".started"; - public static final String INTENT_UPLOAD_QUEUED = EXTRA_PREFIX + ".queued"; - public static final String INTENT_UPLOAD_PROGRESS = EXTRA_PREFIX + ".progress"; - public static final String EXTRA_MEDIA = ".media"; - public static final String EXTRA_TRANSFERRED_BYTES = ".progress.transferred"; + public static final String INTENT_CONTRIBUTION_STATE_CHANGED = EXTRA_PREFIX + ".progress"; + public static final String EXTRA_CONTRIBUTION_ID = EXTRA_PREFIX + ".filename"; + public static final String EXTRA_TRANSFERRED_BYTES = EXTRA_PREFIX + ".progress.transferred"; public static final String EXTRA_MEDIA_URI = EXTRA_PREFIX + ".uri"; @@ -89,9 +86,8 @@ public class UploadService extends IntentService { Log.d("Commons", String.format("%d uploads left", toUpload)); } notificationTitleChanged = true; - Intent mediaUploadStartedEvent = new Intent(INTENT_UPLOAD_STARTED); - // mediaUploadStartedEvent.putExtra(EXTRA_MEDIA, contribution); - localBroadcastManager.sendBroadcast(mediaUploadStartedEvent); + contribution.setState(Contribution.STATE_IN_PROGRESS); + contribution.save(); } if(transferred == total) { // Completed! @@ -100,8 +96,9 @@ public class UploadService extends IntentService { } else { curNotification.contentView.setProgressBar(R.id.uploadNotificationProgress, 100, (int)(((double)transferred / (double)total) * 100), false); notificationManager.notify(NOTIFICATION_DOWNLOAD_IN_PROGRESS, curNotification); - Intent mediaUploadProgressIntent = new Intent(INTENT_UPLOAD_PROGRESS); - // mediaUploadProgressIntent.putExtra(EXTRA_MEDIA, contribution); + + Intent mediaUploadProgressIntent = new Intent(INTENT_CONTRIBUTION_STATE_CHANGED); + // mediaUploadProgressIntent.putExtra(EXTRA_MEDIA contribution); mediaUploadProgressIntent.putExtra(EXTRA_TRANSFERRED_BYTES, transferred); localBroadcastManager.sendBroadcast(mediaUploadProgressIntent); } @@ -174,15 +171,13 @@ public class UploadService extends IntentService { } Contribution contribution = mediaFromIntent(intent); + contribution.setState(Contribution.STATE_QUEUED); + contribution.setContentProviderClient(contributionsProviderClient); - try { - contributionsProviderClient.insert(ContributionsContentProvider.BASE_URI, contribution.toContentValues()); - } catch (RemoteException e) { - throw new RuntimeException(e); - } + contribution.save(); - Intent mediaUploadQueuedIntent = new Intent(INTENT_UPLOAD_QUEUED); - mediaUploadQueuedIntent.putExtra(EXTRA_MEDIA, contribution); + Intent mediaUploadQueuedIntent = new Intent(); + mediaUploadQueuedIntent.putExtra("dummy-data", contribution); // FIXME: Move to separate handler, do not inherit from IntentService localBroadcastManager.sendBroadcast(mediaUploadQueuedIntent); return super.onStartCommand(mediaUploadQueuedIntent, flags, startId); } @@ -195,7 +190,7 @@ public class UploadService extends IntentService { RemoteViews notificationView; Contribution contribution; InputStream file = null; - contribution = (Contribution)intent.getSerializableExtra(EXTRA_MEDIA); + contribution = (Contribution)intent.getSerializableExtra("dummy-data"); String notificationTag = contribution.getLocalUri().toString(); @@ -256,6 +251,9 @@ public class UploadService extends IntentService { .setContentText(getString(R.string.upload_failed_notification_subtitle)) .getNotification(); notificationManager.notify(NOTIFICATION_UPLOAD_FAILED, failureNotification); + + contribution.setState(Contribution.STATE_QUEUED); + contribution.save(); return; } finally { toUpload--; @@ -278,9 +276,7 @@ public class UploadService extends IntentService { .getNotification(); notificationManager.notify(notificationTag, NOTIFICATION_DOWNLOAD_COMPLETE, doneNotification); - - Intent mediaUploadedIntent = new Intent(INTENT_UPLOAD_COMPLETE); - //mediaUploadedIntent.putExtra(EXTRA_MEDIA, contribution); - localBroadcastManager.sendBroadcast(mediaUploadedIntent); + contribution.setState(Contribution.STATE_COMPLETED); + contribution.save(); } } 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 9a58bdc98..7707e2a6f 100644 --- a/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java +++ b/commons/src/main/java/org/wikimedia/commons/contributions/Contribution.java @@ -3,13 +3,22 @@ package org.wikimedia.commons.contributions; import java.text.SimpleDateFormat; import java.util.*; +import android.content.ContentProviderClient; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; import android.net.*; +import android.os.RemoteException; import org.wikimedia.commons.Media; public class Contribution extends Media { + // No need to be bitwise - they're mutually exclusive + public static final int STATE_COMPLETED = 0; + public static final int STATE_QUEUED = 1; + public static final int STATE_IN_PROGRESS = 2; + + private ContentProviderClient client; + private Uri contentUri; public String getEditSummary() { return editSummary; @@ -59,7 +68,23 @@ public class Contribution extends Media { return buffer.toString(); } - public ContentValues toContentValues() { + public void setContentProviderClient(ContentProviderClient client) { + this.client = client; + } + + public void save() { + try { + if(contentUri == null) { + contentUri = client.insert(ContributionsContentProvider.BASE_URI, this.toContentValues()); + } else { + client.update(contentUri, toContentValues(), null, null); + } + } catch(RemoteException e) { + throw new RuntimeException(e); + } + } + + private ContentValues toContentValues() { ContentValues cv = new ContentValues(); cv.put(Table.COLUMN_FILENAME, getFilename()); if(getLocalUri() != null) { @@ -86,10 +111,7 @@ public class Contribution extends Media { public static final String COLUMN_STATE = "state"; public static final String COLUMN_LENGTH = "length"; - // No need to be bitwise - they're mutually exclusive - public static final int STATE_COMPLETED = 0; - public static final int STATE_QUEUED = 1; - public static final int STATE_IN_PROGRESS = 2; + private static final String CREATE_TABLE_STATEMENT = "CREATE TABLE " + TABLE_NAME + " (" diff --git a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java new file mode 100644 index 000000000..65e695624 --- /dev/null +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsActivity.java @@ -0,0 +1,87 @@ +package org.wikimedia.commons.contributions; + +import android.support.v4.app.LoaderManager; +import android.support.v4.content.CursorLoader; +import android.support.v4.content.Loader; +import android.content.BroadcastReceiver; +import android.content.*; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v4.content.*; +import android.support.v4.widget.SimpleCursorAdapter; +import android.util.Log; +import android.widget.ListView; +import com.actionbarsherlock.app.SherlockFragmentActivity; +import org.wikimedia.commons.R; +import org.wikimedia.commons.UploadService; + +// Inherit from SherlockFragmentActivity but not use Fragments. Because Loaders are available only from FragmentActivities +public class ContributionsActivity extends SherlockFragmentActivity implements LoaderManager.LoaderCallbacks { + + private LocalBroadcastManager localBroadcastManager; + + private ListView contributionsList; + private SimpleCursorAdapter contributionsAdapter; + + private String[] broadcastsToReceive = { + UploadService.INTENT_CONTRIBUTION_STATE_CHANGED + }; + + private String[] CONTRIBUTIONS_PROJECTION = { + Contribution.Table.COLUMN_ID, + Contribution.Table.COLUMN_FILENAME, + Contribution.Table.COLUMN_LOCAL_URI, + Contribution.Table.COLUMN_STATE + }; + + private String CONTRIBUTION_SELECTION = ""; + private String CONTRIBUTION_SORT = Contribution.Table.COLUMN_TIMESTAMP + " DESC"; + + private BroadcastReceiver messageReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + } + }; + + @Override + protected void onResume() { + super.onResume(); + for(int i=0; i < broadcastsToReceive.length; i++) { + localBroadcastManager.registerReceiver(messageReceiver, new IntentFilter(broadcastsToReceive[i])); + } + } + + @Override + protected void onPause() { + super.onPause(); + for(int i=0; i < broadcastsToReceive.length; i++) { + localBroadcastManager.unregisterReceiver(messageReceiver); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + localBroadcastManager = LocalBroadcastManager.getInstance(this); + setContentView(R.layout.activity_contributions); + contributionsList = (ListView)findViewById(R.id.contributionsList); + + contributionsAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, null, new String[] { Contribution.Table.COLUMN_FILENAME, Contribution.Table.COLUMN_STATE }, new int[] { android.R.id.text1, android.R.id.text2 }, SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); + contributionsList.setAdapter(contributionsAdapter); + + getSupportLoaderManager().initLoader(0, null, this); + } + + public Loader onCreateLoader(int i, Bundle bundle) { + return new CursorLoader(this, ContributionsContentProvider.BASE_URI, CONTRIBUTIONS_PROJECTION, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT); + } + + public void onLoadFinished(Loader cursorLoader, Cursor cursor) { + contributionsAdapter.swapCursor(cursor); + } + + public void onLoaderReset(Loader cursorLoader) { + contributionsAdapter.swapCursor(null); + } + +} 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 2d6c09f69..02dfe1f88 100644 --- a/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsContentProvider.java +++ b/commons/src/main/java/org/wikimedia/commons/contributions/ContributionsContentProvider.java @@ -7,12 +7,15 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; +import android.text.TextUtils; +import android.util.Log; import org.wikimedia.commons.CommonsApplication; import org.wikimedia.commons.data.DBOpenHelper; public class ContributionsContentProvider extends ContentProvider{ private static final int CONTRIBUTIONS = 1; + private static final int CONTRIBUtiONS_ID = 2; public static final String AUTHORITY = "org.wikimedia.commons.contributions.contentprovider"; private static final String BASE_PATH = "contributions"; @@ -22,6 +25,7 @@ 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); } @@ -37,6 +41,7 @@ public class ContributionsContentProvider extends ContentProvider{ SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); queryBuilder.setTables(Contribution.Table.TABLE_NAME); + Log.d("Commons", "Insert URI is " + uri); int uriType = uriMatcher.match(uri); switch(uriType) { @@ -73,7 +78,7 @@ public class ContributionsContentProvider extends ContentProvider{ throw new IllegalArgumentException("Unknown URI: " + uri); } getContext().getContentResolver().notifyChange(uri, null); - return Uri.parse(BASE_PATH + "/" + contentValues.get(Contribution.Table.COLUMN_FILENAME)); + return Uri.parse(BASE_URI + "/" + id); } @Override @@ -82,7 +87,39 @@ public class ContributionsContentProvider extends ContentProvider{ } @Override - public int update(Uri uri, ContentValues contentValues, String s, String[] strings) { - return 0; + public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) { + int uriType = uriMatcher.match(uri); + SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase(); + int rowsUpdated = 0; + switch (uriType) { + case CONTRIBUTIONS: + rowsUpdated = sqlDB.update(Contribution.Table.TABLE_NAME, + contentValues, + selection, + selectionArgs); + break; + case CONTRIBUtiONS_ID: + String id = uri.getLastPathSegment(); + + if (TextUtils.isEmpty(selection)) { + rowsUpdated = sqlDB.update(Contribution.Table.TABLE_NAME, + contentValues, + Contribution.Table.COLUMN_ID + "= " + id, + null); + } else { + // Doesn't make sense, since FILENAME has to be unique. Implementing for sake of completeness + rowsUpdated = sqlDB.update(Contribution.Table.TABLE_NAME, + contentValues, + Contribution.Table.COLUMN_ID + "= " + id + + " and " + + selection, + selectionArgs); + } + break; + default: + throw new IllegalArgumentException("Unknown URI: " + uri + " with type " + uriType); + } + getContext().getContentResolver().notifyChange(uri, null); + return rowsUpdated; } }