📜 ⬆️ ⬇️

Search for images in Android using Flickr

In this publication I would like to share the experience of selecting a content provider when searching for images and describe the basic interface of interaction with one of them using the example of the Flickr service.

It so happened that during the implementation of one of my projects, it was necessary to search for images using specific keywords. The search should have been implemented based on two simple requirements:

I have been surfing the Internet for a long time in search of a suitable content provider providing a JSON API. As a result, 3 main candidates were selected: Google Search, Flickr and Bing Image Search. There was another option to connect to the old free API from Google, which is already 5 years old in the status of deprecated, but still work. But this option, alas, did not fit.

Unfortunately, the official Google Search API is, firstly, paid, and secondly, as a result of the issuance of Google for some requests, inappropriate images take off. With Bing Image Search, the situation is even more deplorable, although access to the API is cheaper and cheaper.

In order not to be unsubstantiated, I will give a comparison of the issuance of all three providers for provocative requests with the use of maximum filtering of the output of inappropriate content, forgive me for motorists.
')
Google issue


Bing issue


Flickr issue


At Google Search, at first glance, everything is more or less acceptable, but if you scroll the page a little lower, sometimes there are very sad pictures. Bing Image Search is still much more hardcore. For obvious reasons, I will not give screenshots of this here. I carried out many more similar comparisons, including on spicy requests, and in all of them Flickr turned out to be the definitive leader. Therefore, my choice fell on him. In addition, access to their API is free. The only fat disadvantage was the very poor search results in Russian. Looking ahead, I will say that it was decided on the backend - a simple service was raised that translated the Russian text into English. Thus, the request to Flickr consisted of two parts: a transfer request from our server, sending the result to Flickr.

Application registration


First of all, we need to get the API key to work with Flickr. To do this, follow the link (only for non-commercial use)
After filling out the form, you will be provided with Key and Secret:



Flickr Query Interface


To begin with, let's define how the request to the API looks like at all:

https://api.flickr.com/services/rest/?safe_search=safe&api_key=XXX&sort=relevance&method=flickr.interestingness.getList&per_page=50&media=photos&extras=url_sq,url_t,url_s,url_q,url_m,url_n,url_z,url_c,url_l,url_o&license=1,2,3,4,5,6&format=json 

We will be interested in two methods: flickr.photos.search and flickr.interestingness.getList.

The query method flickr.interestingness.getList returns us a list of the most popular images. Images do not stagnate and are periodically updated (according to my observations once every half hour - an hour).

The query method flickr.photos.search will be used directly for keyword searches.

You can read more about each of the request parameters in their official documentation .

Implementation example


To implement communication with the service, the following class was implemented:

 public class Flickr extends Model { public interface FlickrModelResponseHandler { public void onSuccess(ArrayList<HashMap<String, String>> responseArray); public void onFailure(String error); } public Flickr(Context context) { super(context); setUrl("/services/rest/"); } public void fetch (Map<String, String> inData, Map<String, Object> options, final FlickrModelResponseHandler handler) { HashMap<String, String> fetchedParams = new HashMap(inData); fetchedParams.put("api_key", "XXX"); fetchedParams.put("extras", "url_sq,url_t,url_s,url_q,url_m,url_n,url_z,url_c,url_l,url_o"); fetchedParams.put("format", "json"); fetchedParams.put("per_page", "50"); fetchedParams.put("safe_search", "safe"); fetchedParams.put("content_type", "1"); fetchedParams.put("media", "photos"); fetchedParams.put("sort", "relevance"); fetchedParams.put("license", "1,2,3,4,5,6"); super.fetch(fetchedParams, new HashMap<String, Object>() {{ put("host", "https://api.flickr.com"); }}, new ModelResponseHandler() { @Override public void onSuccess(Map<String, Object> responseDict) { ArrayList<HashMap<String, String>> photos = ((HashMap<String, ArrayList<HashMap<String, String>>>)(responseDict.get("photos"))).get("photo"); if (handler != null) handler.onSuccess(photos); } @Override public void onFailure(String error) { if (handler != null) handler.onFailure(error); } }); } @Override protected JSONObject deserialize(String responseString) { Pattern p = Pattern.compile(".*?\\((.*)\\)$"); Matcher m = p.matcher(responseString); String json = null; if (m.matches()) { json = m.group(1); } JSONObject response = null; try { response = new JSONObject(json); } catch (JSONException e) { e.printStackTrace(); } return response; } } 

As can be seen from the code above, the class is inherited from the Model class, which in turn implements primitive methods of communicating with the server (GET, POST, PUT, DELETE requests). The fetch method implements the GET http method and accepts request parameters as the first argument, various data processing flags, etc. as the second argument, and a callback interface as the third argument.

The deserialize method, as the name implies, deserializes the data. Since Flickr returns JSON wrapped in such a byaku: jsonFlickrApi (), then before deserializing a JSON object with a regular schedule, we discard everything unnecessary. For the rest, I think everything is clear.

Now we will implement the method to which the query string will be directly transferred.

  private void searchImages(String query) { HashMap<String, String> params = new HashMap<>(); flickr = new Flickr(ImageSearchActivity.this); if (query != null) { params.put("method", "flickr.photos.search"); params.put("text", query); } else { params.put("method", "flickr.interestingness.getList"); } flickr.fetch(params, null, new Flickr.FlickrModelResponseHandler() { @Override public void onSuccess(ArrayList<HashMap<String, String>> responseArray) { adapter.setArray(responseArray); } @Override public void onFailure(String error) { adapter.setArray(new ArrayList<HashMap<String, String>>()); } }); } 

Here, if the query is null, then we make a query using the flickr.interestingness.getList method, otherwise - flickr.photos.search with the text query.

And, finally, the result of the work.

Caution, 10 meter gif

Source: https://habr.com/ru/post/255051/


All Articles