📜 ⬆️ ⬇️

Flickr API in Android App. Authorization

Hi, habra people!

I want to share with you a little experience of using the Flickr API in Android applications and tell you about the authorization of the Flickr user. Which in the future can be used for example to display a list of albums and images.

Application registration


First of all, we need to get an API Key, we will use applications not for commercial purposes, for registration we follow the link Create an App .


')
We are asked to enter “Name”, “Purpose” and “Rights Agreements”, we send our data and as a result we get API Key and API Secret. We need them in the future to form a request to the server.



After that we need to edit some data, in the same window we go to Edit auth flow for this app .



Descriptions and logo are not interesting to us, you can enter at will. In the Callback URL field, we definitely need to specify a callback address, which we will use to return to our Activity. In my case, I ask appforflickr: // callback . In <intent-filter> this will look like this:
... <data android:scheme="appforflickr" android:host="callback"/> ... 
App Type - select the Web Application and Save the changes.

Next, go directly to the construction of the application itself.

In the application manifest, we add “android.permission.INTERNET” and the <intent-filter> block as a result we get:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="test.testflickrapi" > <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".ui.activities.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> <data android:scheme="appforflickr" android:host="callback"/> </intent-filter> </activity> </application> </manifest> 


Creating a link to authorize the user


To authorize users in the application, we will launch the Activity from the WebView. But first, we will create the login address. The template looks like this:
 http://flickr.com/services/auth/?api_key=[api_key]&perms=[perms]&api_sig=[api_sig] 
[api_key] is our key obtained when registering the application. [perms] - account access level, can have the following values:

[api_sig] - the signature, it includes the Secret obtained when registering the application and the list of arguments in alphabetical order, name and value.
In our case, the API Key: 5744fadec815a7e8142d03901065c97b , API Secret: 8b2c12e80b67970b , write access rights, the signature is a string of:
 secret + 'api_key' + [api_key] + 'perms' + [perms] 
, that is, we have: 8b2c12e80b67970bapi_key5744fadec815a7e8142d03901065c97bpermswrite and now we need to encrypt this string in MD5. To do this, use the following method:

 public static final String md5SumOfString(final String s) { try { MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); digest.update(s.getBytes()); byte messageDigest[] = digest.digest(); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < messageDigest.length; i++) hexString.append(Integer.toHexString(0xFF & messageDigest[i])); return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } 

and get the values ​​[api_sig].

As a result, the address for user authorization will be as follows:

 http://www.flickr.com/services/auth/?api_key=9a0554259914a86fb9e7eb014e4e5d52&perms=write&api_sig=b8d7c1ae026d5f86f1f44944f5257f3 
Add to onCreate ()
 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 
where url is the above address. After launching the application, we open a web page to specify a username and password. If the entered data is correct, the Callback URL will automatically redirect us to our application. The frob parameter of the values ​​is added to the url, that is, in our case it looks like this:

 appforflickr://callback?frob=72157650137623777-b09eae52121bf8ad-130818926 
Frob is needed to get Access token .
Add conditions to onCreate () to get a frob:

 Uri uri = getIntent().getData(); if (uri != null) { String frob = uri.getQueryParameter("frob"); } else startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 

After processing, we call the flickr.auth.getToken method from the API to get the token and nsid , which will be needed for further requests, as well as the username and fullname of the user.

To send requests, create a class HttpRequest:

 public class HttpRequest extends AsyncTask<String, String, String> { public static final String TAG = HttpRequest.class.getSimpleName(); @Override protected void onPreExecute() { Log.d(TAG, "START"); } @Override protected String doInBackground(String... params) { String result = ""; try { String uri = params[0]; HttpGet httpGet = new HttpGet(uri); HttpResponse response = HttpClientHelper.getHttpClient().execute(httpGet); HttpEntity entity = response.getEntity(); if (entity != null) { InputStream inStream = entity.getContent(); result = InputStreamConverter.convertStreamToString(inStream); inStream.close(); } return result; } catch (IllegalStateException e) { return result; } catch (ClientProtocolException e) { return result; } catch (IOException e) { return result; } } @Override protected void onPostExecute(String result) { Log.d(TAG, "STOP"); } } 


Class HttpClientHelper to get the HttpClient:

 public class HttpClientHelper { private static HttpClient httpClient = null; private static final int REGISTRATION_TIMEOUT = 30 * 1000; private static final int WAIT_TIMEOUT = 30 * 1000; private HttpClientHelper() {} public static synchronized HttpClient getHttpClient() { if (httpClient == null) { HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); ConnManagerParams.setTimeout(params, WAIT_TIMEOUT); HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT); HttpConnectionParams.setSoTimeout(params, WAIT_TIMEOUT); SchemeRegistry schemeReg = new SchemeRegistry(); schemeReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager connectionMgr = new ThreadSafeClientConnManager(params, schemeReg); httpClient = new DefaultHttpClient(connectionMgr, params); } return httpClient; } } 


Class InputStreamConverter to convert an InputStream to String:

 public class InputStreamConverter { private InputStreamConverter() {} public static String convertStreamToString(InputStream inputStream) { BufferedReader reader = new BufferedReader(new InputStreamReader( inputStream)); StringBuilder builder = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { builder.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return builder.toString(); } } 


Address to get token:

 https://api.flickr.com/services/rest/?method=flickr.auth.getToken&api_key=9a0554259914a86fb9e7eb014e4e5d52&frob=72157650137623777-b09eae52121bf8ad-130818926&format=json&nojsoncallback=1&perms=write&api_sig=8fd09b55f670ec9a4ba07c076e520ae8 
so that the answer comes in the form of json, we added parameters from the values format = json and nojsoncallback = 1

We make another change to onCreate () to send the request:

 Uri uri = getIntent().getData(); if (uri != null) { String frob = uri.getQueryParameter("frob"); String url = "..."; //      token String response = ""; HttpRequest httpRequest = new HttpRequest(this); httpRequest.execute(url); try { response = httpRequest.get(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } else startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 


Further, the answer is:
 {"auth":{"token":{"_content":"12134650097774510-014feda8303a4a64"},"perms":{"_content":"write"},"user":{"nsid":"230211065@N05","username":"user","fullname":"User Alex"}},"stat":"ok"} 
you can get the desired token and nsid using libraries like gson or jackson is already an amateur.

I hope my article will be useful to someone.

Ps. This is my first post on Habré, so sorry for the few words and do not judge strictly.

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


All Articles