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.
This commit is contained in:
YuviPanda 2013-02-01 02:23:29 +05:30
parent d1b088581f
commit 2260078fa7
7 changed files with 177 additions and 84 deletions

View file

@ -40,7 +40,7 @@
</intent-filter>
</activity>
<activity
android:name=".ContributionsActivity"
android:name=".contributions.ContributionsActivity"
android:icon="@drawable/ic_launcher"
android:label="@string/title_activity_share"
>

View file

@ -4,5 +4,8 @@
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView android:id="@+id/contributionsList"
android:layout_height="fill_parent"
android:layout_width="fill_parent" />
</LinearLayout>

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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 + " ("

View file

@ -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<Cursor> {
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<Cursor> onCreateLoader(int i, Bundle bundle) {
return new CursorLoader(this, ContributionsContentProvider.BASE_URI, CONTRIBUTIONS_PROJECTION, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT);
}
public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
contributionsAdapter.swapCursor(cursor);
}
public void onLoaderReset(Loader<Cursor> cursorLoader) {
contributionsAdapter.swapCursor(null);
}
}

View file

@ -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;
}
}