mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-27 04:43:54 +01:00
commit
4290fdf4c3
8 changed files with 179 additions and 25 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue