Even though there is no such android specific sdk from linkedIn(like facebook and twitter sdk for android).Setting up linkedIn authorization with Oauth 1.0 was still easy using:
But its not the same story for authorization with Oauth2.0. Not too many usefull libraries or android specific examples. I tried using these:
I have read that Oauth 2.0 is much simpler to implement than the 1.0. Still I am not able to do so.
Any pointers towards implementing Oauth2.0 for LinkedIn in Android?
MainActivity:
public class MainActivity extends Activity {
/*CONSTANT FOR THE AUTHORIZATION PROCESS*/
/****FILL THIS WITH YOUR INFORMATION*********/
//This is the public api key of our application
private static final String API_KEY = "YOUR_API_KEY";
//This is the private api key of our application
private static final String SECRET_KEY = "YOUR_API_SECRET";
//This is any string we want to use. This will be used for avoiding CSRF attacks. You can generate one here: http://strongpasswordgenerator.com/
private static final String STATE = "E3ZYKC1T6H2yP4z";
//This is the url that LinkedIn Auth process will redirect to. We can put whatever we want that starts with http:// or https:// .
//We use a made up url that we will intercept when redirecting. Avoid Uppercases.
private static final String REDIRECT_URI = "http://com.amalbit.redirecturl";
/*********************************************/
//These are constants used for build the urls
private static final String AUTHORIZATION_URL = "https://www.linkedin.com/uas/oauth2/authorization";
private static final String ACCESS_TOKEN_URL = "https://www.linkedin.com/uas/oauth2/accessToken";
private static final String SECRET_KEY_PARAM = "client_secret";
private static final String RESPONSE_TYPE_PARAM = "response_type";
private static final String GRANT_TYPE_PARAM = "grant_type";
private static final String GRANT_TYPE = "authorization_code";
private static final String RESPONSE_TYPE_VALUE ="code";
private static final String CLIENT_ID_PARAM = "client_id";
private static final String STATE_PARAM = "state";
private static final String REDIRECT_URI_PARAM = "redirect_uri";
/*---------------------------------------*/
private static final String QUESTION_MARK = "?";
private static final String AMPERSAND = "&";
private static final String EQUALS = "=";
private WebView webView;
private ProgressDialog pd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get the webView from the layout
webView = (WebView) findViewById(R.id.main_activity_web_view);
//Request focus for the webview
webView.requestFocus(View.FOCUS_DOWN);
//Show a progress dialog to the user
pd = ProgressDialog.show(this, "", this.getString(R.string.loading),true);
//Set a custom web view client
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
//This method will be executed each time a page finished loading.
//The only we do is dismiss the progressDialog, in case we are showing any.
if(pd!=null && pd.isShowing()){
pd.dismiss();
}
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String authorizationUrl) {
//This method will be called when the Auth proccess redirect to our RedirectUri.
//We will check the url looking for our RedirectUri.
if(authorizationUrl.startsWith(REDIRECT_URI)){
Log.i("Authorize", "");
Uri uri = Uri.parse(authorizationUrl);
//We take from the url the authorizationToken and the state token. We have to check that the state token returned by the Service is the same we sent.
//If not, that means the request may be a result of CSRF and must be rejected.
String stateToken = uri.getQueryParameter(STATE_PARAM);
if(stateToken==null || !stateToken.equals(STATE)){
Log.e("Authorize", "State token doesn't match");
return true;
}
//If the user doesn't allow authorization to our application, the authorizationToken Will be null.
String authorizationToken = uri.getQueryParameter(RESPONSE_TYPE_VALUE);
if(authorizationToken==null){
Log.i("Authorize", "The user doesn't allow authorization.");
return true;
}
Log.i("Authorize", "Auth token received: "+authorizationToken);
//Generate URL for requesting Access Token
String accessTokenUrl = getAccessTokenUrl(authorizationToken);
//We make the request in a AsyncTask
new PostRequestAsyncTask().execute(accessTokenUrl);
}else{
//Default behaviour
Log.i("Authorize","Redirecting to: "+authorizationUrl);
webView.loadUrl(authorizationUrl);
}
return true;
}
});
//Get the authorization Url
String authUrl = getAuthorizationUrl();
Log.i("Authorize","Loading Auth Url: "+authUrl);
//Load the authorization URL into the webView
webView.loadUrl(authUrl);
}
/**
* Method that generates the url for get the access token from the Service
* @return Url
*/
private static String getAccessTokenUrl(String authorizationToken){
return ACCESS_TOKEN_URL
+QUESTION_MARK
+GRANT_TYPE_PARAM+EQUALS+GRANT_TYPE
+AMPERSAND
+RESPONSE_TYPE_VALUE+EQUALS+authorizationToken
+AMPERSAND
+CLIENT_ID_PARAM+EQUALS+API_KEY
+AMPERSAND
+REDIRECT_URI_PARAM+EQUALS+REDIRECT_URI
+AMPERSAND
+SECRET_KEY_PARAM+EQUALS+SECRET_KEY;
}
/**
* Method that generates the url for get the authorization token from the Service
* @return Url
*/
private static String getAuthorizationUrl(){
return AUTHORIZATION_URL
+QUESTION_MARK+RESPONSE_TYPE_PARAM+EQUALS+RESPONSE_TYPE_VALUE
+AMPERSAND+CLIENT_ID_PARAM+EQUALS+API_KEY
+AMPERSAND+STATE_PARAM+EQUALS+STATE
+AMPERSAND+REDIRECT_URI_PARAM+EQUALS+REDIRECT_URI;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class PostRequestAsyncTask extends AsyncTask<String, Void, Boolean>{
@Override
protected void onPreExecute(){
pd = ProgressDialog.show(MainActivity.this, "", MainActivity.this.getString(R.string.loading),true);
}
@Override
protected Boolean doInBackground(String... urls) {
if(urls.length>0){
String url = urls[0];
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(url);
try{
HttpResponse response = httpClient.execute(httpost);
if(response!=null){
//If status is OK 200
if(response.getStatusLine().getStatusCode()==200){
String result = EntityUtils.toString(response.getEntity());
//Convert the string result to a JSON Object
JSONObject resultJson = new JSONObject(result);
//Extract data from JSON Response
int expiresIn = resultJson.has("expires_in") ? resultJson.getInt("expires_in") : 0;
String accessToken = resultJson.has("access_token") ? resultJson.getString("access_token") : null;
Log.e("Tokenm", ""+accessToken);
if(expiresIn>0 && accessToken!=null){
Log.i("Authorize", "This is the access Token: "+accessToken+". It will expires in "+expiresIn+" secs");
//Calculate date of expiration
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, expiresIn);
long expireDate = calendar.getTimeInMillis();
////Store both expires in and access token in shared preferences
SharedPreferences preferences = MainActivity.this.getSharedPreferences("user_info", 0);
SharedPreferences.Editor editor = preferences.edit();
editor.putLong("expires", expireDate);
editor.putString("accessToken", accessToken);
editor.commit();
return true;
}
}
}
}catch(IOException e){
Log.e("Authorize","Error Http response "+e.getLocalizedMessage());
}
catch (ParseException e) {
Log.e("Authorize","Error Parsing Http response "+e.getLocalizedMessage());
} catch (JSONException e) {
Log.e("Authorize","Error Parsing Http response "+e.getLocalizedMessage());
}
}
return false;
}
@Override
protected void onPostExecute(Boolean status){
if(pd!=null && pd.isShowing()){
pd.dismiss();
}
if(status){
//If everything went Ok, change to another activity.
Intent startProfileActivity = new Intent(MainActivity.this, ProfileActivity.class);
MainActivity.this.startActivity(startProfileActivity);
}
}
};
}
And the xmlLayout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<WebView
android:id="@+id/main_activity_web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
The token is saved in the sharedpreference file.
Simple android project repo here in github.