diff --git a/CHANGELOG.md b/CHANGELOG.md index 530cfb01c..6255cd920 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Wikimedia Commons for Android +## v1.5 +- New feature: Suggests nearby Commons categories + ## v1.3 - Removed 'send usage reports' setting - Fixed package naming issue diff --git a/commons/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java b/commons/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java index c5ecdafa8..e5491c27f 100644 --- a/commons/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java +++ b/commons/src/main/java/fr/free/nrw/commons/category/CategorizationFragment.java @@ -8,6 +8,7 @@ import android.os.*; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; +import android.util.Log; import android.view.*; import android.widget.*; import com.actionbarsherlock.app.SherlockFragment; @@ -18,12 +19,14 @@ import org.mediawiki.api.ApiResult; import org.mediawiki.api.MWApi; import fr.free.nrw.commons.CommonsApplication; import fr.free.nrw.commons.R; +import fr.free.nrw.commons.upload.MwVolleyApi; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.concurrent.ScheduledThreadPoolExecutor; public class CategorizationFragment extends SherlockFragment{ @@ -112,6 +115,7 @@ public class CategorizationFragment extends SherlockFragment{ items.add(new CategoryItem(category, false)); } } + categoriesAdapter.setItems(items); categoriesAdapter.notifyDataSetInvalidated(); categoriesSearchInProgress.setVisibility(View.GONE); @@ -132,6 +136,8 @@ public class CategorizationFragment extends SherlockFragment{ protected ArrayList doInBackground(Void... voids) { if(TextUtils.isEmpty(filter)) { ArrayList items = new ArrayList(); + ArrayList mergedItems= new ArrayList(); + try { Cursor cursor = client.query( CategoryContentProvider.BASE_URI, @@ -144,12 +150,25 @@ public class CategorizationFragment extends SherlockFragment{ Category cat = Category.fromCursor(cursor); items.add(cat.getName()); } - } catch (RemoteException e) { + + if (MwVolleyApi.GpsCatExists.getGpsCatExists() == true){ + Log.d("Cat", "GPS cats found in CategorizationFragment.java" + MwVolleyApi.getGpsCat().toString()); + List gpsItems = new ArrayList(MwVolleyApi.getGpsCat()); + Log.d("Cat", "GPS items: " + gpsItems.toString()); + + mergedItems.addAll(gpsItems); + } + + mergedItems.addAll(items); + } + catch (RemoteException e) { // faaaail throw new RuntimeException(e); } - return items; + Log.d("Cat", "Merged items: " + mergedItems.toString()); + return mergedItems; } + if(categoriesCache.containsKey(filter)) { return categoriesCache.get(filter); } diff --git a/commons/src/main/java/fr/free/nrw/commons/upload/FilePathConverter.java b/commons/src/main/java/fr/free/nrw/commons/upload/FilePathConverter.java index f8fff7a8a..9267bf9f8 100644 --- a/commons/src/main/java/fr/free/nrw/commons/upload/FilePathConverter.java +++ b/commons/src/main/java/fr/free/nrw/commons/upload/FilePathConverter.java @@ -23,27 +23,34 @@ public class FilePathConverter { * May return null */ public String getFilePath(){ + String filePath =""; - // Will return "image:x*" - String wholeID = DocumentsContract.getDocumentId(uri); - // Split at colon, use second item in the array - String id = wholeID.split(":")[1]; - String[] column = { MediaStore.Images.Media.DATA }; + try { + // Will return "image:x*" + String wholeID = DocumentsContract.getDocumentId(uri); - // where id is equal to - String sel = MediaStore.Images.Media._ID + "=?"; - Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - column, sel, new String[]{id}, null); + // Split at colon, use second item in the array + String id = wholeID.split(":")[1]; + String[] column = {MediaStore.Images.Media.DATA}; - int columnIndex = cursor.getColumnIndex(column[0]); + // where id is equal to + String sel = MediaStore.Images.Media._ID + "=?"; + Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + column, sel, new String[]{id}, null); - if (cursor.moveToFirst()) { - filePath = cursor.getString(columnIndex); + int columnIndex = cursor.getColumnIndex(column[0]); + + if (cursor.moveToFirst()) { + filePath = cursor.getString(columnIndex); + } + cursor.close(); + + Log.d("Image", "File path: " + filePath); + return filePath; + } catch (IllegalArgumentException e) { + Log.w("Image", e); + return null; } - cursor.close(); - - Log.d("Image", "File path: " + filePath); - return filePath; } } diff --git a/commons/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java b/commons/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java index d8c6b62e7..88191b894 100644 --- a/commons/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java +++ b/commons/src/main/java/fr/free/nrw/commons/upload/GPSExtractor.java @@ -26,6 +26,16 @@ public class GPSExtractor { try { exif = new ExifInterface(filePath); + } catch (IOException e) { + Log.w("Image", e); + return null; + } + + if (exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE) == null) { + Log.d("Image", "Picture has no GPS info"); + return null; + } + else { latitude = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE); latitude_ref = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF); longitude = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE); @@ -35,11 +45,8 @@ public class GPSExtractor { Log.d("Image", "Longitude: " + longitude + " " + longitude_ref); decimalCoords = getDecimalCoords(latitude, latitude_ref, longitude, longitude_ref); - - } catch (IOException e) { - Log.w("Image", e); + return decimalCoords; } - return decimalCoords; } //Converts format of coords into decimal coords as required by API for next step diff --git a/commons/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java b/commons/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java index b835ce1ee..e3c69d2b4 100644 --- a/commons/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java +++ b/commons/src/main/java/fr/free/nrw/commons/upload/MwVolleyApi.java @@ -1,6 +1,7 @@ package fr.free.nrw.commons.upload; import android.content.Context; +import android.net.Uri; import android.util.Log; import com.android.volley.Cache; @@ -18,23 +19,75 @@ import com.google.gson.GsonBuilder; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class MwVolleyApi { private static RequestQueue REQUEST_QUEUE; private static final Gson GSON = new GsonBuilder().create(); private Context context; + private String coordsLog; + + protected static Set categorySet; + + private static final String MWURL = "https://commons.wikimedia.org/"; public MwVolleyApi(Context context) { this.context = context; + categorySet = new HashSet(); } - public void request(String apiUrl) { + + //To get the list of categories for display + public static List getGpsCat() { + List list = new ArrayList(categorySet); + return list; + } + + + public void request(String coords) { + + coordsLog = coords; + String apiUrl = buildUrl(coords); + Log.d("Image", "URL: " + apiUrl); + JsonRequest request = new QueryRequest(apiUrl, new LogResponseListener(), new LogResponseErrorListener()); getQueue().add(request); } - private RequestQueue getQueue() { + /** + * Builds URL with image coords for MediaWiki API calls + * Example URL: https://commons.wikimedia.org/w/api.php?action=query&prop=categories|coordinates|pageprops&format=json&clshow=!hidden&coprop=type|name|dim|country|region|globe&codistancefrompoint=38.11386944444445|13.356263888888888& + * generator=geosearch&redirects=&ggscoord=38.11386944444445|13.356263888888888&ggsradius=100&ggslimit=10&ggsnamespace=6&ggsprop=type|name|dim|country|region|globe&ggsprimary=all&formatversion=2 + */ + private String buildUrl (String coords){ + + Uri.Builder builder = Uri.parse(MWURL).buildUpon(); + + builder.appendPath("w") + .appendPath("api.php") + .appendQueryParameter("action", "query") + .appendQueryParameter("prop", "categories|coordinates|pageprops") + .appendQueryParameter("format", "json") + .appendQueryParameter("clshow", "!hidden") + .appendQueryParameter("coprop", "type|name|dim|country|region|globe") + .appendQueryParameter("codistancefrompoint", coords) + .appendQueryParameter("generator", "geosearch") + .appendQueryParameter("ggscoord", coords) + .appendQueryParameter("ggsradius", "100") + .appendQueryParameter("ggslimit", "10") + .appendQueryParameter("ggsnamespace", "6") + .appendQueryParameter("ggsprop", "type|name|dim|country|region|globe") + .appendQueryParameter("ggsprimary", "all") + .appendQueryParameter("formatversion", "2"); + + return builder.toString(); + } + + private synchronized RequestQueue getQueue() { return getQueue(context); } @@ -80,12 +133,10 @@ public class MwVolleyApi { return Response.success(queryResponse, cacheEntry(response)); } - private Cache.Entry cacheEntry(NetworkResponse response) { return HttpHeaderParser.parseCacheHeaders(response); } - private String parseString(NetworkResponse response) { try { return new String(response.data, HttpHeaderParser.parseCharset(response.headers)); @@ -95,12 +146,40 @@ public class MwVolleyApi { } } + public static class GpsCatExists { + private static boolean gpsCatExists; + + public static void setGpsCatExists(boolean gpsCat) { + gpsCatExists = gpsCat; + } + + public static boolean getGpsCatExists() { + return gpsCatExists; + } + } + private static class QueryResponse { - private Query query; + private Query query = new Query(); + + private String printSet() { + if (categorySet == null || categorySet.isEmpty()) { + GpsCatExists.setGpsCatExists(false); + Log.d("Cat", "gpsCatExists=" + GpsCatExists.getGpsCatExists()); + return "No collection of categories"; + } else { + GpsCatExists.setGpsCatExists(true); + Log.d("Cat", "gpsCatExists=" + GpsCatExists.getGpsCatExists()); + return "CATEGORIES FOUND" + categorySet.toString(); + } + } @Override public String toString() { - return "query=" + query.toString(); + if (query != null) { + return "query=" + query.toString() + "\n" + printSet(); + } else { + return "No pages found"; + } } } @@ -115,7 +194,9 @@ public class MwVolleyApi { builder.append("\n"); } builder.replace(builder.length() - 1, builder.length(), ""); + return builder.toString(); + } } @@ -130,16 +211,19 @@ public class MwVolleyApi { public String toString() { StringBuilder builder = new StringBuilder("PAGEID=" + pageid + " ns=" + ns + " title=" + title + "\n" + " CATEGORIES= "); - if (categories != null) { + + if (categories == null || categories.length == 0) { + builder.append("no categories exist\n"); + } else { for (Category category : categories) { builder.append(category.toString()); builder.append("\n"); + if (category != null) { + String categoryString = category.toString().replace("Category:", ""); + categorySet.add(categoryString); + } } } - else { - builder.append("no categories exist"); - builder.append("\n"); - } builder.replace(builder.length() - 1, builder.length(), ""); return builder.toString(); @@ -147,12 +231,11 @@ public class MwVolleyApi { } private static class Category { - private int ns; private String title; @Override public String toString() { - return " ns=" + ns + " title=" + title; + return title; } } } diff --git a/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java b/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java index 0ead49cb5..369d9b990 100644 --- a/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java +++ b/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java @@ -179,20 +179,20 @@ public class ShareActivity FilePathConverter uriObj = new FilePathConverter(this, mediaUri); String filePath = uriObj.getFilePath(); - //extract the coordinates of image in decimal degrees - GPSExtractor imageObj = new GPSExtractor(filePath); - String coords = imageObj.getCoords(); - Log.d("Image", "Coords of image: " + coords); + if (filePath != null) { + //extract the coordinates of image in decimal degrees + Log.d("Image", "Calling GPSExtractor"); + GPSExtractor imageObj = new GPSExtractor(filePath); + String coords = imageObj.getCoords(); - //build URL with image coords for MediaWiki API calls - String apiUrl = UrlBuilder.buildUrl(coords); - Log.d("Image", "URL: " + apiUrl); - - - //asynchronous calls to MediaWiki Commons API to match image coords with nearby Commons categories - MwVolleyApi apiCall = new MwVolleyApi(this); - apiCall.request(apiUrl); + 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); + } + } ImageLoader.getInstance().displayImage(mediaUriString, backgroundImageView); @@ -220,35 +220,4 @@ public class ShareActivity return super.onOptionsItemSelected(item); } - /** - * Builds URL with image coords for MediaWiki API calls - * Example URL: https://commons.wikimedia.org/w/api.php?action=query&prop=categories|coordinates|pageprops&format=json&clshow=!hidden&coprop=type|name|dim|country|region|globe&codistancefrompoint=38.11386944444445|13.356263888888888& - * generator=geosearch&redirects=&ggscoord=38.11386944444445|13.356263888888888&ggsradius=100&ggslimit=10&ggsnamespace=6&ggsprop=type|name|dim|country|region|globe&ggsprimary=all&formatversion=2 - */ - public static class UrlBuilder { - private static String buildUrl (String coords){ - - Uri.Builder builder = Uri.parse("https://commons.wikimedia.org/").buildUpon(); - - builder.appendPath("w") - .appendPath("api.php") - .appendQueryParameter("action", "query") - .appendQueryParameter("prop", "categories|coordinates|pageprops") - .appendQueryParameter("format", "json") - .appendQueryParameter("clshow", "!hidden") - .appendQueryParameter("coprop", "type|name|dim|country|region|globe") - .appendQueryParameter("codistancefrompoint", coords) - .appendQueryParameter("generator", "geosearch") - .appendQueryParameter("ggscoord", coords) - .appendQueryParameter("ggsradius", "100") - .appendQueryParameter("ggslimit", "10") - .appendQueryParameter("ggsnamespace", "6") - .appendQueryParameter("ggsprop", "type|name|dim|country|region|globe") - .appendQueryParameter("ggsprimary", "all") - .appendQueryParameter("formatversion", "2"); - - return builder.toString(); - } - } - }