mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 12:23:58 +01:00
Added Sync Provider for syncing previous contributions
This commit is contained in:
parent
4abf3156e7
commit
eac6807fe3
12 changed files with 287 additions and 77 deletions
|
|
@ -70,6 +70,18 @@
|
|||
android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/authenticator" />
|
||||
</service>
|
||||
<service
|
||||
android:name=".contributions.ContributionsSyncService"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action
|
||||
android:name="android.content.SyncAdapter" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.content.SyncAdapter"
|
||||
android:resource="@xml/syncadapter" />
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name=".contributions.ContributionsContentProvider"
|
||||
android:authorities="org.wikimedia.commons.contributions.contentprovider"
|
||||
|
|
|
|||
9
commons/res/xml/syncadapter.xml
Normal file
9
commons/res/xml/syncadapter.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:contentAuthority="org.wikimedia.commons.contributions.contentprovider"
|
||||
android:accountType="org.wikimedia.commons"
|
||||
android:supportsUploading="false"
|
||||
android:userVisible="true"
|
||||
android:isAlwaysSyncable="true"
|
||||
/>
|
||||
|
|
@ -4,6 +4,9 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.net.URI;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.xml.transform.*;
|
||||
|
||||
|
|
@ -13,12 +16,17 @@ import android.net.Uri;
|
|||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
|
||||
import com.nostra13.universalimageloader.cache.disc.impl.TotalSizeLimitedDiscCache;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
|
||||
import com.nostra13.universalimageloader.core.download.HttpClientImageDownloader;
|
||||
import com.nostra13.universalimageloader.core.download.ImageDownloader;
|
||||
import com.nostra13.universalimageloader.core.download.URLConnectionImageDownloader;
|
||||
import com.nostra13.universalimageloader.utils.StorageUtils;
|
||||
import org.acra.ACRA;
|
||||
import org.acra.ReportingInteractionMode;
|
||||
import org.acra.annotation.ReportsCrashes;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.mediawiki.api.*;
|
||||
import org.w3c.dom.Node;
|
||||
import org.wikimedia.commons.auth.WikiAccountAuthenticator;
|
||||
|
|
@ -43,13 +51,16 @@ public class CommonsApplication extends Application {
|
|||
|
||||
private MWApi api;
|
||||
private Account currentAccount = null; // Unlike a savings account...
|
||||
public static final String API_URL = "http://test.wikipedia.org/w/api.php";
|
||||
|
||||
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 MWApi createMWApi() {
|
||||
DefaultHttpClient client = new DefaultHttpClient();
|
||||
return new MWApi(API_URL, client);
|
||||
}
|
||||
|
||||
|
||||
public DBOpenHelper getDbOpenHelper() {
|
||||
if(dbOpenHelper == null) {
|
||||
dbOpenHelper = new DBOpenHelper(this);
|
||||
|
|
@ -57,13 +68,7 @@ public class CommonsApplication extends Application {
|
|||
return dbOpenHelper;
|
||||
}
|
||||
|
||||
public class ContentUriImageDownloader extends ImageDownloader {
|
||||
|
||||
@Override
|
||||
protected InputStream getStreamFromNetwork(URI uri) throws IOException {
|
||||
return super.getStream(uri); // Pass back to parent code, which handles http, https, etc
|
||||
}
|
||||
|
||||
public class ContentUriImageDownloader extends URLConnectionImageDownloader {
|
||||
@Override
|
||||
protected InputStream getStreamFromOtherSource(URI imageUri) throws IOException {
|
||||
if(imageUri.getScheme().equals("content")) {
|
||||
|
|
@ -83,6 +88,7 @@ public class CommonsApplication extends Application {
|
|||
|
||||
|
||||
ImageLoaderConfiguration imageLoaderConfiguration = new ImageLoaderConfiguration.Builder(getApplicationContext())
|
||||
.discCache(new TotalSizeLimitedDiscCache(StorageUtils.getCacheDirectory(this), 128 * 1024 * 1024))
|
||||
.imageDownloader(new ContentUriImageDownloader()).build();
|
||||
ImageLoader.getInstance().init(imageLoaderConfiguration);
|
||||
}
|
||||
|
|
@ -127,38 +133,5 @@ public class CommonsApplication extends Application {
|
|||
}
|
||||
}
|
||||
|
||||
public static String getStringFromDOM(Node dom) {
|
||||
javax.xml.transform.Transformer transformer = null;
|
||||
try {
|
||||
transformer = TransformerFactory.newInstance().newTransformer();
|
||||
} catch (TransformerConfigurationException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (TransformerFactoryConfigurationError e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
StringWriter outputStream = new StringWriter();
|
||||
javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(dom);
|
||||
javax.xml.transform.stream.StreamResult strResult = new javax.xml.transform.stream.StreamResult(outputStream);
|
||||
|
||||
try {
|
||||
transformer.transform(domSource, strResult);
|
||||
} catch (TransformerException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return outputStream.toString();
|
||||
}
|
||||
|
||||
static public <T> void executeAsyncTask(AsyncTask<T, ?, ?> task,
|
||||
T... params) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
|
||||
}
|
||||
else {
|
||||
task.execute(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ public class Media implements Serializable {
|
|||
return localUri;
|
||||
}
|
||||
|
||||
public Uri getRemoteUri() {
|
||||
return remoteUri;
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
|
|
@ -23,10 +23,6 @@ public class Media implements Serializable {
|
|||
return description;
|
||||
}
|
||||
|
||||
public String getCommonsURL() {
|
||||
return commonsURL;
|
||||
}
|
||||
|
||||
public long getDataLength() {
|
||||
return dataLength;
|
||||
}
|
||||
|
|
@ -43,12 +39,15 @@ public class Media implements Serializable {
|
|||
return creator;
|
||||
}
|
||||
|
||||
public String getThumbnailUrl(int width) {
|
||||
return String.format("%s/%dpx-%s", imageUrl, width, filename);
|
||||
}
|
||||
|
||||
|
||||
protected Uri localUri;
|
||||
protected Uri remoteUri;
|
||||
protected String imageUrl;
|
||||
protected String filename;
|
||||
protected String description;
|
||||
protected String commonsURL;
|
||||
protected long dataLength;
|
||||
protected Date dateCreated;
|
||||
protected Date dateUploaded;
|
||||
|
|
@ -57,12 +56,11 @@ public class Media implements Serializable {
|
|||
protected String creator;
|
||||
|
||||
|
||||
public Media(Uri localUri, Uri remoteUri, String filename, String description, String commonsURL, long dataLength, Date dateCreated, Date dateUploaded, String creator) {
|
||||
public Media(Uri localUri, String imageUrl, String filename, String description, long dataLength, Date dateCreated, Date dateUploaded, String creator) {
|
||||
this.localUri = localUri;
|
||||
this.remoteUri = remoteUri;
|
||||
this.imageUrl = imageUrl;
|
||||
this.filename = filename;
|
||||
this.description = description;
|
||||
this.commonsURL = commonsURL;
|
||||
this.dataLength = dataLength;
|
||||
this.dateCreated = dateCreated;
|
||||
this.dateUploaded = dateUploaded;
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ public class UploadService extends IntentService {
|
|||
} /* else if (mimeType.startsWith("audio/")) {
|
||||
Removed Audio implementationf or now
|
||||
} */
|
||||
Contribution contribution = new Contribution(mediaUri, null, filename, description, null, length, dateCreated, null, app.getCurrentAccount().name, editSummary);
|
||||
Contribution contribution = new Contribution(mediaUri, null, filename, description, length, dateCreated, null, app.getCurrentAccount().name, editSummary);
|
||||
return contribution;
|
||||
}
|
||||
|
||||
|
|
@ -254,22 +254,17 @@ public class UploadService extends IntentService {
|
|||
toUpload--;
|
||||
}
|
||||
|
||||
Log.d("Commons", "Response is" + CommonsApplication.getStringFromDOM(result.getDocument()));
|
||||
Log.d("Commons", "Response is" + Utils.getStringFromDOM(result.getDocument()));
|
||||
stopForeground(true);
|
||||
curProgressNotification = null;
|
||||
|
||||
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // Assuming MW always gives me UTC
|
||||
|
||||
String resultStatus = result.getString("/api/upload/@result");
|
||||
if(!resultStatus.equals("Success")) {
|
||||
showFailedNotification(contribution);
|
||||
} else {
|
||||
Date dateUploaded = null;
|
||||
try {
|
||||
dateUploaded = isoFormat.parse(result.getString("/api/upload/imageinfo/@timestamp"));
|
||||
} catch(java.text.ParseException e) {
|
||||
throw new RuntimeException(e); // Hopefully mediawiki doesn't give me bogus stuff?
|
||||
}
|
||||
dateUploaded = Utils.parseMWDate(result.getString("/api/upload/imageinfo/@timestamp"));
|
||||
contribution.setState(Contribution.STATE_COMPLETED);
|
||||
contribution.setDateUploaded(dateUploaded);
|
||||
contribution.save();
|
||||
|
|
|
|||
76
commons/src/main/java/org/wikimedia/commons/Utils.java
Normal file
76
commons/src/main/java/org/wikimedia/commons/Utils.java
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package org.wikimedia.commons;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import org.apache.commons.codec.binary.Hex;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import java.io.StringWriter;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class Utils {
|
||||
public static Date parseMWDate(String mwDate) {
|
||||
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // Assuming MW always gives me UTC
|
||||
try {
|
||||
return isoFormat.parse(mwDate);
|
||||
} catch (ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String toMWDate(Date date) {
|
||||
SimpleDateFormat isoFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); // Assuming MW always gives me UTC
|
||||
isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
return isoFormat.format(date);
|
||||
}
|
||||
|
||||
public static String makeThumbBaseUrl(String filename) {
|
||||
String name = filename.replaceFirst("File:", "").replace(" ", "_");
|
||||
String sha = new String(Hex.encodeHex(DigestUtils.md5(name)));
|
||||
return String.format("%s/%s/%s/%s", CommonsApplication.IMAGE_URL_BASE, sha.substring(0, 1), sha.substring(0, 2), name);
|
||||
}
|
||||
|
||||
|
||||
public static String getStringFromDOM(Node dom) {
|
||||
javax.xml.transform.Transformer transformer = null;
|
||||
try {
|
||||
transformer = TransformerFactory.newInstance().newTransformer();
|
||||
} catch (TransformerConfigurationException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (TransformerFactoryConfigurationError e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
StringWriter outputStream = new StringWriter();
|
||||
javax.xml.transform.dom.DOMSource domSource = new javax.xml.transform.dom.DOMSource(dom);
|
||||
javax.xml.transform.stream.StreamResult strResult = new javax.xml.transform.stream.StreamResult(outputStream);
|
||||
|
||||
try {
|
||||
transformer.transform(domSource, strResult);
|
||||
} catch (TransformerException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return outputStream.toString();
|
||||
}
|
||||
|
||||
static public <T> void executeAsyncTask(AsyncTask<T, ?, ?> task,
|
||||
T... params) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
|
||||
}
|
||||
else {
|
||||
task.execute(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,7 @@ import com.actionbarsherlock.app.*;
|
|||
import android.accounts.*;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import org.wikimedia.commons.Utils;
|
||||
|
||||
public class AuthenticatedActivity extends SherlockFragmentActivity {
|
||||
|
||||
|
|
@ -113,7 +114,7 @@ public class AuthenticatedActivity extends SherlockFragmentActivity {
|
|||
// returns, we have a deadlock!
|
||||
// Fixed by explicitly asking this to be executed in parallel
|
||||
// See: https://groups.google.com/forum/?fromgroups=#!topic/android-developers/8M0RTFfO7-M
|
||||
CommonsApplication.executeAsyncTask(addAccountTask);
|
||||
Utils.executeAsyncTask(addAccountTask);
|
||||
} else {
|
||||
GetAuthCookieTask task = new GetAuthCookieTask(curAccount, accountManager);
|
||||
task.execute();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.content.ContentValues;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.net.*;
|
||||
import android.os.RemoteException;
|
||||
import android.text.TextUtils;
|
||||
import org.wikimedia.commons.Media;
|
||||
|
||||
public class Contribution extends Media {
|
||||
|
|
@ -47,8 +48,8 @@ public class Contribution extends Media {
|
|||
private Date timestamp;
|
||||
private int state;
|
||||
|
||||
public Contribution(Uri localUri, Uri remoteUri, String filename, String description, String commonsURL, long dataLength, Date dateCreated, Date dateUploaded, String creator, String editSummary) {
|
||||
super(localUri, remoteUri, filename, description, commonsURL, dataLength, dateCreated, dateUploaded, creator);
|
||||
public Contribution(Uri localUri, String remoteUri, String filename, String description, long dataLength, Date dateCreated, Date dateUploaded, String creator, String editSummary) {
|
||||
super(localUri, remoteUri, filename, description, dataLength, dateCreated, dateUploaded, creator);
|
||||
this.editSummary = editSummary;
|
||||
timestamp = new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
|
@ -102,14 +103,24 @@ public class Contribution extends Media {
|
|||
}
|
||||
}
|
||||
|
||||
private ContentValues toContentValues() {
|
||||
public static String makeThumbUrl(String imageUrl, String filename, int width) {
|
||||
// Ugly Hack!
|
||||
// Update: OH DEAR GOD WHAT A HORRIBLE HACK I AM SO SORRY
|
||||
String thumbUrl = imageUrl.replaceFirst("test/", "test/thumb/").replace("commons/", "commons/thumb/") + "/" + width + "px-" + filename.replaceAll("File:", "").replaceAll(" ", "_");
|
||||
if(thumbUrl.endsWith("jpg") || thumbUrl.endsWith("png") || thumbUrl.endsWith("jpeg")) {
|
||||
return thumbUrl;
|
||||
} else {
|
||||
return thumbUrl + ".png";
|
||||
}
|
||||
}
|
||||
public ContentValues toContentValues() {
|
||||
ContentValues cv = new ContentValues();
|
||||
cv.put(Table.COLUMN_FILENAME, getFilename());
|
||||
if(getLocalUri() != null) {
|
||||
cv.put(Table.COLUMN_LOCAL_URI, getLocalUri().toString());
|
||||
}
|
||||
if(getRemoteUri() != null) {
|
||||
cv.put(Table.COLUMN_REMOTE_URI, getRemoteUri().toString());
|
||||
if(getImageUrl() != null) {
|
||||
cv.put(Table.COLUMN_IMAGE_URL, getImageUrl().toString());
|
||||
}
|
||||
if(getDateUploaded() != null) {
|
||||
cv.put(Table.COLUMN_UPLOADED, getDateUploaded().getTime());
|
||||
|
|
@ -128,7 +139,7 @@ public class Contribution extends Media {
|
|||
public static final String COLUMN_ID = "_id";
|
||||
public static final String COLUMN_FILENAME = "filename";
|
||||
public static final String COLUMN_LOCAL_URI = "local_uri";
|
||||
public static final String COLUMN_REMOTE_URI = "remote_uri";
|
||||
public static final String COLUMN_IMAGE_URL = "image_url";
|
||||
public static final String COLUMN_TIMESTAMP = "timestamp";
|
||||
public static final String COLUMN_STATE = "state";
|
||||
public static final String COLUMN_LENGTH = "length";
|
||||
|
|
@ -140,7 +151,7 @@ public class Contribution extends Media {
|
|||
+ "_id INTEGER PRIMARY KEY,"
|
||||
+ "filename STRING,"
|
||||
+ "local_uri STRING,"
|
||||
+ "remote_uri STRING,"
|
||||
+ "image_url STRING,"
|
||||
+ "uploaded INTEGER,"
|
||||
+ "timestamp INTEGER,"
|
||||
+ "state INTEGER,"
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import android.os.Bundle;
|
|||
import android.support.v4.content.*;
|
||||
import android.support.v4.widget.CursorAdapter;
|
||||
import android.support.v4.widget.SimpleCursorAdapter;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
|
@ -63,6 +64,7 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load
|
|||
private final int COLUMN_UPLOADED;
|
||||
private final int COLUMN_TRANSFERRED;
|
||||
private final int COLUMN_LENGTH;
|
||||
private final int COLUMN_IMAGE_URL;
|
||||
|
||||
public ContributionAdapter(Context context, Cursor c, int flags) {
|
||||
super(context, c, flags);
|
||||
|
|
@ -72,6 +74,7 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load
|
|||
COLUMN_UPLOADED = c.getColumnIndex(Contribution.Table.COLUMN_UPLOADED);
|
||||
COLUMN_LENGTH = c.getColumnIndex(Contribution.Table.COLUMN_LENGTH);
|
||||
COLUMN_TRANSFERRED = c.getColumnIndex(Contribution.Table.COLUMN_TRANSFERRED);
|
||||
COLUMN_IMAGE_URL = c.getColumnIndex(Contribution.Table.COLUMN_IMAGE_URL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -85,15 +88,20 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load
|
|||
TextView titleView = (TextView)view.findViewById(R.id.contributionTitle);
|
||||
TextView stateView = (TextView)view.findViewById(R.id.contributionState);
|
||||
|
||||
Uri imageUri = Uri.parse(cursor.getString(COLUMN_LOCALURI));
|
||||
String localUri = cursor.getString(COLUMN_LOCALURI);
|
||||
String imageUrl = cursor.getString(COLUMN_IMAGE_URL);
|
||||
String title = cursor.getString(COLUMN_FILENAME);
|
||||
int state = cursor.getInt(COLUMN_STATE);
|
||||
|
||||
if(imageView.getTag() == null || !imageView.getTag().equals(imageUri.toString())) {
|
||||
ImageLoader.getInstance().displayImage(imageUri.toString(), imageView, contributionDisplayOptions);
|
||||
imageView.setTag(imageUri.toString());
|
||||
String actualUrl = TextUtils.isEmpty(imageUrl) ? localUri : Contribution.makeThumbUrl(imageUrl, title, 320);
|
||||
Log.d("Commons", "Trying URL " + actualUrl);
|
||||
|
||||
if(imageView.getTag() == null || !imageView.getTag().equals(actualUrl)) {
|
||||
ImageLoader.getInstance().displayImage(actualUrl, imageView, contributionDisplayOptions);
|
||||
imageView.setTag(actualUrl);
|
||||
}
|
||||
|
||||
titleView.setText(cursor.getString(COLUMN_FILENAME));
|
||||
titleView.setText(title);
|
||||
switch(state) {
|
||||
case Contribution.STATE_COMPLETED:
|
||||
Date uploaded = new Date(cursor.getLong(COLUMN_UPLOADED));
|
||||
|
|
@ -129,7 +137,8 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load
|
|||
Contribution.Table.COLUMN_STATE,
|
||||
Contribution.Table.COLUMN_UPLOADED,
|
||||
Contribution.Table.COLUMN_LENGTH,
|
||||
Contribution.Table.COLUMN_TRANSFERRED
|
||||
Contribution.Table.COLUMN_TRANSFERRED,
|
||||
Contribution.Table.COLUMN_IMAGE_URL
|
||||
};
|
||||
|
||||
private String CONTRIBUTION_SELECTION = "";
|
||||
|
|
@ -142,7 +151,7 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load
|
|||
|
||||
This is why Contribution.STATE_COMPLETED is -1.
|
||||
*/
|
||||
private String CONTRIBUTION_SORT = Contribution.Table.COLUMN_STATE + " DESC, (" + Contribution.Table.COLUMN_TIMESTAMP + " * " + Contribution.Table.COLUMN_STATE + ")";
|
||||
private String CONTRIBUTION_SORT = Contribution.Table.COLUMN_STATE + " DESC, (" + Contribution.Table.COLUMN_TIMESTAMP + " * " + Contribution.Table.COLUMN_STATE + "), " + Contribution.Table.COLUMN_UPLOADED + " DESC";
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
|
|
@ -159,6 +168,8 @@ public class ContributionsActivity extends AuthenticatedActivity implements Load
|
|||
contributionDisplayOptions = new DisplayImageOptions.Builder().cacheInMemory()
|
||||
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
|
||||
.displayer(new FadeInBitmapDisplayer(300))
|
||||
.cacheInMemory()
|
||||
.cacheOnDisc()
|
||||
.resetViewBeforeLoading().build();
|
||||
|
||||
Cursor allContributions = getContentResolver().query(ContributionsContentProvider.BASE_URI, CONTRIBUTIONS_PROJECTION, CONTRIBUTION_SELECTION, null, CONTRIBUTION_SORT);
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ public class ContributionsContentProvider extends ContentProvider{
|
|||
public Uri insert(Uri uri, ContentValues contentValues) {
|
||||
int uriType = uriMatcher.match(uri);
|
||||
SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
|
||||
int rowsDeleted = 0;
|
||||
long id = 0;
|
||||
switch (uriType) {
|
||||
case CONTRIBUTIONS:
|
||||
|
|
@ -86,6 +85,28 @@ public class ContributionsContentProvider extends ContentProvider{
|
|||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bulkInsert(Uri uri, ContentValues[] values) {
|
||||
Log.d("Commons", "Hello, bulk insert!");
|
||||
int uriType = uriMatcher.match(uri);
|
||||
SQLiteDatabase sqlDB = dbOpenHelper.getWritableDatabase();
|
||||
sqlDB.beginTransaction();
|
||||
switch (uriType) {
|
||||
case CONTRIBUTIONS:
|
||||
for(ContentValues value: values) {
|
||||
Log.d("Commons", "Inserting! " + value.toString());
|
||||
sqlDB.insert(Contribution.Table.TABLE_NAME, null, value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown URI: " + uri);
|
||||
}
|
||||
sqlDB.setTransactionSuccessful();
|
||||
sqlDB.endTransaction();
|
||||
getContext().getContentResolver().notifyChange(uri, null);
|
||||
return values.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues contentValues, String selection, String[] selectionArgs) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
package org.wikimedia.commons.contributions;
|
||||
|
||||
import android.content.*;
|
||||
import android.database.Cursor;
|
||||
import android.os.RemoteException;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.accounts.Account;
|
||||
import android.os.Bundle;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.wikimedia.commons.CommonsApplication;
|
||||
import org.mediawiki.api.*;
|
||||
import org.wikimedia.commons.Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public class ContributionsSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
public ContributionsSyncAdapter(Context context, boolean autoInitialize) {
|
||||
super(context, autoInitialize);
|
||||
}
|
||||
|
||||
private int getLimit() {
|
||||
return 500; // FIXME: Parameterize!
|
||||
}
|
||||
@Override
|
||||
public void onPerformSync(Account account, Bundle bundle, String s, ContentProviderClient contentProviderClient, SyncResult syncResult) {
|
||||
// This code is fraught with possibilities of race conditions, but lalalalala I can't hear you!
|
||||
String user = account.name;
|
||||
MWApi api = CommonsApplication.createMWApi();
|
||||
SharedPreferences prefs = this.getContext().getSharedPreferences("prefs", Context.MODE_PRIVATE);
|
||||
String lastModified = prefs.getString("lastSyncTimestamp", "");
|
||||
Date curTime = new Date();
|
||||
ApiResult result;
|
||||
try {
|
||||
MWApi.RequestBuilder builder = api.action("query")
|
||||
.param("list", "logevents")
|
||||
.param("leaction", "upload/upload")
|
||||
.param("leprop", "title|timestamp")
|
||||
.param("leuser", user)
|
||||
.param("lelimit", getLimit());
|
||||
if(!TextUtils.isEmpty(lastModified)) {
|
||||
builder.param("leend", lastModified);
|
||||
}
|
||||
result = builder.get();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e); // FIXME: Maybe something else?
|
||||
}
|
||||
Log.d("Commons", "Last modified at " + lastModified);
|
||||
|
||||
ArrayList<ApiResult> uploads = result.getNodes("/api/query/logevents/item");
|
||||
Log.d("Commons", uploads.size() + " results!");
|
||||
ContentValues[] imageValues = new ContentValues[uploads.size()];
|
||||
for(int i=0; i < uploads.size(); i++) {
|
||||
ApiResult image = uploads.get(i);
|
||||
String filename = image.getString("@title");
|
||||
String thumbUrl = Utils.makeThumbBaseUrl(filename);
|
||||
Date dateUpdated = Utils.parseMWDate(image.getString("@timestamp"));
|
||||
Contribution contrib = new Contribution(null, thumbUrl, filename, "", -1, dateUpdated, dateUpdated, user, "");
|
||||
contrib.setState(Contribution.STATE_COMPLETED);
|
||||
imageValues[i] = contrib.toContentValues();
|
||||
Log.d("Commons", "For " + imageValues[i].toString());
|
||||
}
|
||||
|
||||
try {
|
||||
contentProviderClient.bulkInsert(ContributionsContentProvider.BASE_URI, imageValues);
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
prefs.edit().putString("lastSyncTimestamp", Utils.toMWDate(curTime)).apply();
|
||||
Log.d("Commons", "Oh hai, everyone! Look, a kitty!");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package org.wikimedia.commons.contributions;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class ContributionsSyncService extends Service {
|
||||
|
||||
private static final Object sSyncAdapterLock = new Object();
|
||||
|
||||
private static ContributionsSyncAdapter sSyncAdapter = null;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
synchronized (sSyncAdapterLock) {
|
||||
if (sSyncAdapter == null) {
|
||||
sSyncAdapter = new ContributionsSyncAdapter(getApplicationContext(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return sSyncAdapter.getSyncAdapterBinder();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue