Merge pull request #37 from misaochan/caching

Caching
This commit is contained in:
Stephen Niedzielski 2016-01-11 22:11:48 -06:00
commit 4290fdf4c3
8 changed files with 179 additions and 25 deletions

View file

@ -1,6 +1,10 @@
# Wikimedia Commons for Android
## v1.5
- Caches area and associated categories
- Increased search radius for nearby categories
## v1.4
- New feature: Suggests nearby Commons categories
## v1.3

View file

@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fr.free.nrw.commons"
android:versionCode="20"
android:versionName="1.4" >
android:versionCode="21"
android:versionName="1.5" >
<uses-sdk
android:minSdkVersion="9"

View file

@ -28,6 +28,8 @@ import org.apache.http.params.BasicHttpParams;
import org.mediawiki.api.*;
import org.apache.http.impl.client.*;
import org.apache.http.params.CoreProtocolPNames;
import fr.free.nrw.commons.caching.CacheController;
import fr.free.nrw.commons.data.*;
import com.android.volley.toolbox.*;
@ -67,6 +69,8 @@ public class CommonsApplication extends Application {
public RequestQueue volleyQueue;
public CacheController cacheData;
public static AbstractHttpClient createHttpClient() {
BasicHttpParams params = new BasicHttpParams();
SchemeRegistry schemeRegistry = new SchemeRegistry();
@ -145,6 +149,9 @@ public class CommonsApplication extends Application {
};
}
//For caching area -> categories
cacheData = new CacheController();
DiskBasedCache cache = new DiskBasedCache(getCacheDir(), 16 * 1024 * 1024);
volleyQueue = new RequestQueue(cache, new BasicNetwork(new HurlStack()));
volleyQueue.start();

View file

@ -0,0 +1,88 @@
package fr.free.nrw.commons.caching;
import android.util.Log;
import com.github.varunpant.quadtree.Point;
import com.github.varunpant.quadtree.QuadTree;
import java.util.ArrayList;
import java.util.List;
import fr.free.nrw.commons.upload.MwVolleyApi;
public class CacheController {
private double x, y;
private QuadTree quadTree;
private Point[] pointsFound;
private double xMinus, xPlus, yMinus, yPlus;
private static final String TAG = CacheController.class.getName();
private static final int EARTH_RADIUS = 6378137;
public CacheController() {
quadTree = new QuadTree(-180, -90, +180, +90);
}
public void setQtPoint(double decLongitude, double decLatitude) {
x = decLongitude;
y = decLatitude;
Log.d(TAG, "New QuadTree created");
Log.d(TAG, "X (longitude) value: " + x + ", Y (latitude) value: " + y);
}
public void cacheCategory() {
List<String> pointCatList = new ArrayList<String>();
if (MwVolleyApi.GpsCatExists.getGpsCatExists() == true) {
pointCatList.addAll(MwVolleyApi.getGpsCat());
Log.d(TAG, "Categories being cached: " + pointCatList);
} else {
Log.d(TAG, "No categories found, so no categories cached");
}
quadTree.set(x, y, pointCatList);
}
public List findCategory() {
//Convert decLatitude and decLongitude to a coordinate offset range
convertCoordRange();
pointsFound = quadTree.searchWithin(xMinus, yMinus, xPlus, yPlus);
List<String> displayCatList = new ArrayList<String>();
Log.d(TAG, "Points found in quadtree: " + pointsFound);
if (pointsFound.length != 0) {
Log.d(TAG, "Entering for loop");
for (Point point : pointsFound) {
Log.d(TAG, "Nearby point: " + point.toString());
displayCatList = (List<String>)point.getValue();
Log.d(TAG, "Nearby cat: " + point.getValue());
}
Log.d(TAG, "Categories found in cache: " + displayCatList.toString());
} else {
Log.d(TAG, "No categories found in cache");
}
return displayCatList;
}
//Based on algorithm at http://gis.stackexchange.com/questions/2951/algorithm-for-offsetting-a-latitude-longitude-by-some-amount-of-meters
public void convertCoordRange() {
//Position, decimal degrees
double lat = y;
double lon = x;
//offsets in meters
double offset = 100;
//Coordinate offsets in radians
double dLat = offset/EARTH_RADIUS;
double dLon = offset/(EARTH_RADIUS*Math.cos(Math.PI*lat/180));
//OffsetPosition, decimal degrees
yPlus = lat + dLat * 180/Math.PI;
yMinus = lat - dLat * 180/Math.PI;
xPlus = lon + dLon * 180/Math.PI;
xMinus = lon - dLon * 180/Math.PI;
Log.d(TAG, "Search within: xMinus=" + xMinus + ", yMinus=" + yMinus + ", xPlus=" + xPlus + ", yPlus=" + yPlus);
}
}

View file

@ -51,6 +51,7 @@ public class CategorizationFragment extends SherlockFragment{
private ContentProviderClient client;
private final int SEARCH_CATS_LIMIT = 25;
private static final String TAG = CategorizationFragment.class.getName();
public static class CategoryItem implements Parcelable {
public String name;
@ -152,9 +153,9 @@ public class CategorizationFragment extends SherlockFragment{
}
if (MwVolleyApi.GpsCatExists.getGpsCatExists() == true){
Log.d("Cat", "GPS cats found in CategorizationFragment.java" + MwVolleyApi.getGpsCat().toString());
Log.d(TAG, "GPS cats found in CategorizationFragment.java" + MwVolleyApi.getGpsCat().toString());
List<String> gpsItems = new ArrayList<String>(MwVolleyApi.getGpsCat());
Log.d("Cat", "GPS items: " + gpsItems.toString());
Log.d(TAG, "GPS items: " + gpsItems.toString());
mergedItems.addAll(gpsItems);
}
@ -165,7 +166,7 @@ public class CategorizationFragment extends SherlockFragment{
// faaaail
throw new RuntimeException(e);
}
Log.d("Cat", "Merged items: " + mergedItems.toString());
Log.d(TAG, "Merged items: " + mergedItems.toString());
return mergedItems;
}

View file

@ -9,6 +9,7 @@ import java.io.IOException;
public class GPSExtractor {
private String filePath;
private double decLatitude, decLongitude;
public GPSExtractor(String filePath){
this.filePath = filePath;
@ -41,18 +42,27 @@ public class GPSExtractor {
longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
longitude_ref = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
Log.d("Image", "Latitude: " + latitude + " " + latitude_ref);
Log.d("Image", "Longitude: " + longitude + " " + longitude_ref);
decimalCoords = getDecimalCoords(latitude, latitude_ref, longitude, longitude_ref);
return decimalCoords;
}
}
//Converts format of coords into decimal coords as required by API for next step
public double getDecLatitude() {
return decLatitude;
}
public double getDecLongitude() {
return decLongitude;
}
//Converts format of coords into decimal coords as required by MediaWiki API
private String getDecimalCoords(String latitude, String latitude_ref, String longitude, String longitude_ref) {
double decLatitude, decLongitude;
if(latitude_ref.equals("N")){
decLatitude = convertToDegree(latitude);
@ -68,9 +78,12 @@ public class GPSExtractor {
decLongitude = 0 - convertToDegree(longitude);
}
return (String.valueOf(decLatitude) + "|" + String.valueOf(decLongitude));
String decimalCoords = String.valueOf(decLatitude) + "|" + String.valueOf(decLongitude);
Log.d("Coords", "Latitude and Longitude are " + decimalCoords);
return decimalCoords;
}
private double convertToDegree(String stringDMS){
double result;
String[] DMS = stringDMS.split(",", 3);

View file

@ -24,6 +24,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import fr.free.nrw.commons.caching.CacheController;
public class MwVolleyApi {
private static RequestQueue REQUEST_QUEUE;
@ -32,23 +34,27 @@ public class MwVolleyApi {
private String coordsLog;
protected static Set<String> categorySet;
private static List<String> categoryList;
private static final String MWURL = "https://commons.wikimedia.org/";
private static final String TAG = MwVolleyApi.class.getName();
public MwVolleyApi(Context context) {
this.context = context;
categorySet = new HashSet<String>();
}
//To get the list of categories for display
public static List<String> getGpsCat() {
List<String> list = new ArrayList<String>(categorySet);
return list;
return categoryList;
}
public static void setGpsCat(List cachedList) {
categoryList = new ArrayList<String>();
categoryList.addAll(cachedList);
Log.d(TAG, "Setting GPS cats from cache: " + categoryList.toString());
}
public void request(String coords) {
coordsLog = coords;
String apiUrl = buildUrl(coords);
Log.d("Image", "URL: " + apiUrl);
@ -77,7 +83,7 @@ public class MwVolleyApi {
.appendQueryParameter("codistancefrompoint", coords)
.appendQueryParameter("generator", "geosearch")
.appendQueryParameter("ggscoord", coords)
.appendQueryParameter("ggsradius", "100")
.appendQueryParameter("ggsradius", "10000")
.appendQueryParameter("ggslimit", "10")
.appendQueryParameter("ggsnamespace", "6")
.appendQueryParameter("ggsprop", "type|name|dim|country|region|globe")
@ -164,13 +170,14 @@ public class MwVolleyApi {
private String printSet() {
if (categorySet == null || categorySet.isEmpty()) {
GpsCatExists.setGpsCatExists(false);
Log.d("Cat", "gpsCatExists=" + GpsCatExists.getGpsCatExists());
Log.d(TAG, "gpsCatExists=" + GpsCatExists.getGpsCatExists());
return "No collection of categories";
} else {
GpsCatExists.setGpsCatExists(true);
Log.d("Cat", "gpsCatExists=" + GpsCatExists.getGpsCatExists());
Log.d(TAG, "gpsCatExists=" + GpsCatExists.getGpsCatExists());
return "CATEGORIES FOUND" + categorySet.toString();
}
}
@Override
@ -225,6 +232,7 @@ public class MwVolleyApi {
}
}
categoryList = new ArrayList<String>(categorySet);
builder.replace(builder.length() - 1, builder.length(), "");
return builder.toString();
}

View file

@ -11,6 +11,7 @@ import android.util.Log;
import android.widget.*;
import fr.free.nrw.commons.*;
import fr.free.nrw.commons.caching.CacheController;
import fr.free.nrw.commons.modifications.CategoryModifier;
import fr.free.nrw.commons.modifications.TemplateRemoveModifier;
import fr.free.nrw.commons.CommonsApplication;
@ -22,6 +23,8 @@ import fr.free.nrw.commons.modifications.ModificationsContentProvider;
import fr.free.nrw.commons.modifications.ModifierSequence;
import java.util.ArrayList;
import java.util.List;
public class ShareActivity
@ -46,6 +49,11 @@ public class ShareActivity
private UploadController uploadController;
private CommonsApplication cacheObj;
private boolean cacheFound;
private static final String TAG = ShareActivity.class.getName();
public ShareActivity() {
super(WikiAccountAuthenticator.COMMONS_ACCOUNT_TYPE);
}
@ -53,6 +61,13 @@ public class ShareActivity
public void uploadActionInitiated(String title, String description) {
Toast startingToast = Toast.makeText(getApplicationContext(), R.string.uploading_started, Toast.LENGTH_LONG);
startingToast.show();
if (cacheFound == false) {
//Has to be called after apiCall.request()
app.cacheData.cacheCategory();
Log.d(TAG, "Cache the categories found");
}
uploadController.startUpload(title, mediaUri, description, mimeType, source, new UploadController.ContributionUploadProgress() {
public void onUploadStarted(Contribution contribution) {
ShareActivity.this.contribution = contribution;
@ -168,29 +183,47 @@ public class ShareActivity
} else {
source = Contribution.SOURCE_EXTERNAL;
}
mimeType = intent.getType();
}
mediaUriString = mediaUri.toString();
Log.d("Image", "Uri: " + mediaUriString);
Log.d(TAG, "Uri: " + mediaUriString);
//convert image Uri to file path
FilePathConverter uriObj = new FilePathConverter(this, mediaUri);
String filePath = uriObj.getFilePath();
if (filePath != null) {
//extract the coordinates of image in decimal degrees
Log.d("Image", "Calling GPSExtractor");
Log.d(TAG, "Calling GPSExtractor");
GPSExtractor imageObj = new GPSExtractor(filePath);
String coords = imageObj.getCoords();
String decimalCoords = imageObj.getCoords();
if (decimalCoords != null) {
double decLongitude = imageObj.getDecLongitude();
double decLatitude = imageObj.getDecLatitude();
Log.d(TAG, "Decimal coords of image: " + decimalCoords);
app.cacheData.setQtPoint(decLongitude, decLatitude);
if (coords != null) {
Log.d("Image", "Coords of image: " + coords);
MwVolleyApi apiCall = new MwVolleyApi(this);
//asynchronous calls to MediaWiki Commons API to match image coords with nearby Commons categories
apiCall.request(coords);
List displayCatList = app.cacheData.findCategory();
boolean catListEmpty = displayCatList.isEmpty();
//if no categories found in cache, call MW API to match image coords with nearby Commons categories
if (catListEmpty) {
cacheFound = false;
apiCall.request(decimalCoords);
Log.d(TAG, "displayCatList size 0, calling MWAPI" + displayCatList.toString());
} else {
cacheFound = true;
Log.d(TAG, "Cache found, setting categoryList in MwVolleyApi to " + displayCatList.toString());
MwVolleyApi.setGpsCat(displayCatList);
}
}
}