To integrate the LinkedIn Sign-In functionality in an Android application, the LinkedIn API is implemented in the Android app. It thus provides the functionality to login using the LinkedIn account, shares post, etc. The LinkedIn Authentication Key (Client ID and Client Secret) and app Hash Key are a must for integrating the LinkedIn API in an Android app.
To generate LinkedIn Authentication Key and APP Hash Key:
- The LinkedIn developer account is to be created at https://www.linkedin.com/developer/apps.
- Click on the ‘Create app’ button.
- In the ‘Create a New Application’ form, fill all the required details of the Android application.
- Accept the LinkedIn API Terms of Use.
- Click ‘Submit’.
- The LinkedIn Authentication Key is generated, after submitting the application details.
- Select the ‘Default Application Permissions’ which will authorize the access privilege of the user account.
- Select r_basicprofile, and ‘r_emailaddress’.
- Click ‘Update’.
- The ‘Hash Key’ for the app can be generated by either of the two ways.
- Using command on command prompt.
- Using the programming code in Activity.java class.
- Using command on command prompt:
- Windows:
keytool -exportcert -keystore %HOMEPATH%\.android\debug.keystore -alias androiddebugkey | openssl sha1 -binary | openssl base64
- Windows:
-
- Mac/Unix:
keytool -exportcert -keystore ~/.android/debug.keystore -alias androiddebugkey | openssl sha1 -binary | openssl base64
- Mac/Unix:
The OpenSSL needs to be installed in the operating system, to generate the Hash Key through command prompt. The OpenSSL can be downloaded from
- For Windows: www.slproweb.com/products/Win32OpenSSL.html
- For Mac/Unix: http://www.openssl.org/source/.
- Using the programming code in Activity.java class:
PackageInfo info = getPackageManager().getPackageInfo( "Package Name", PackageManager.GET_SIGNATURES); for (Signature signature : info.signatures) { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(signature.toByteArray()); Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
To generate ‘Hash Key’ for this application, we are using the programming code. To do this, write the below code in the application and run it. The application ‘Hash Key’ will be displayed in the Logcat.
MainActivity.java:
package com.example.radioapp; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Base64; import android.util.Log; import java.security.MessageDigest; public class MainActivity extends AppCompatActivity { public static final String PACKAGE = "example.com.linkedinlogindemo"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); computePakageHash(); } private void computePakageHash() { try { PackageInfo info = getPackageManager().getPackageInfo( "example.com.linkedinlogindemo", PackageManager.GET_SIGNATURES); for (Signature signature : info.signatures) { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(signature.toByteArray()); Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT)); } } catch (Exception e) { Log.e("TAG",e.getMessage()); } } } |
- Copy and Paste the ‘Hash Key’ from the Logcat to the Mobile tab of the application.
- Click on ‘Add’ and ‘Update’ buttons.
- Thus the application ‘Hash Key’ will be registered with the LinkedIn API.
Example:
In the below example, we are integrating the LinkedIn log-in functionality in our Android application. The user will be redirected to another activity i.e., ProfileActivity, after a successful user log-in. The user information will thus be displayed. To add the LinkedIn SDK for Android in a project, download it from https://developer.linkedin.com/downloads#androidsdk.
AndroidManifest.xml:
In the AndroidManifest.xml file, we will write the code to add the Internet permission.
Required Permission:
<uses-permission android:name="android.permission.INTERNET" /> |
Code:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.radioapp"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ProfileActivity" /> </application> </manifest> |
settings.gradle:
In the settings.gradle file, we will write the code to add the linkedin-sdk.
include ':app', ':linkedin-sdk' |
build.gradle (Module):
In the build.gradle file, we will write the code to add the compile project(path: ‘:linkedin-sdk’).
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:support-v4:28.0.0' implementation 'com.android.support:support-annotations:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support:design:28.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation project(path: ':linkedin-sdk') android { useLibrary 'org.apache.http.legacy' } Code: apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { applicationId "com.example.radioapp" minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } sourceSets { main { assets { srcDirs 'src/main/assets', 'src/main/res/assets/' } } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:support-v4:28.0.0' implementation 'com.android.support:support-annotations:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.android.support:design:28.0.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.google.zxing:core:3.2.1' implementation project(path: ':linkedin-sdk') android { useLibrary 'org.apache.http.legacy' } } |
activity_main.xml:
In the activity_main.xml file, we will write the below code. The LinkedIn button can be downloaded from the LinkedIn developer site https://developer.linkedin.com/downloads. We will add the button as the background of the button.
Code:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/login_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="50dp" android:background="@drawable/loginbutton" tools:layout_editor_absoluteX="100dp" tools:layout_editor_absoluteY="800dp" /> </RelativeLayout> |
MainActivity.java:
In the MainActivity.java file, we will write the code to add the LISessionManager class. This class provides the functionalities to create and manage the LISession object i.e., LinkedIn session object. To access the basic profile information of the user and the email address of LinkedIn, scope adds the ‘Scope.R_BASICPROFILE’ and ‘Scope.R_EMAILADDRESS’, in the build.
Code:
package com.example.radioapp; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.linkedin.platform.LISessionManager; import com.linkedin.platform.errors.LIAuthError; import com.linkedin.platform.listeners.AuthListener; import com.linkedin.platform.utils.Scope; public class MainActivity extends AppCompatActivity { Button loginBtn; TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); loginBtn = (Button) findViewById(R.id.login_button); loginBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { loginHandle(); } }); } public void loginHandle() { LISessionManager.getInstance(getApplicationContext()).init(MainActivity.this, buildScope(), new AuthListener() { @Override public void onAuthSuccess() { // Authentication was successful. You can now do other calls with the SDK. Intent intent=new Intent(MainActivity.this,ProfileActivity.class); startActivity(intent); } @Override public void onAuthError(LIAuthError error) { // Handle authentication errors Toast.makeText(getApplicationContext(),"Login Error "+error.toString(),Toast.LENGTH_LONG).show(); } }, true); } private static Scope buildScope() { return Scope.build(Scope.R_BASICPROFILE, Scope.R_EMAILADDRESS); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Add this line to your existing onActivityResult() method LISessionManager.getInstance(getApplicationContext()).onActivityResult(this, requestCode, resultCode, data); } } |
activity_profile.xml:
In the activity_profile.xml file, we will write the code to display the user information after a successful login.
Code:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal" tools:context=".ProfileActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Welcome to profile" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/userDetail" android:text="userdetail" android:layout_marginTop="20dp" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:textColor="#FFF" android:text="logout" android:id="@+id/logout_button" android:background="#022885" /> </LinearLayout> |
ProfileActivity.java:
In the ProfileActivity.java file, we will write the code to add the LinkedIn API URL https://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address) in getRequest() method of APIHelper class. The user information will thus be retrieved on the success of the LinkedIn API.
Code:
package com.example.radioapp; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.linkedin.platform.APIHelper; import com.linkedin.platform.LISession; import com.linkedin.platform.LISessionManager; import com.linkedin.platform.errors.LIApiError; import com.linkedin.platform.listeners.ApiListener; import com.linkedin.platform.listeners.ApiResponse; import org.json.JSONException; import org.json.JSONObject; public class ProfileActivity extends AppCompatActivity { TextView user_detail; String firstName,lastName,userEmail; Button logout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); user_detail=(TextView)findViewById(R.id.userDetail); logout=(Button)findViewById(R.id.logout_button); fetchuserData(); logout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { LISessionManager.getInstance(getApplicationContext()).clearSession(); Toast.makeText(getApplicationContext(),"Logout Successfully",Toast.LENGTH_LONG).show(); Intent intent = new Intent(ProfileActivity.this, MainActivity.class); startActivity(intent); } }); } private void fetchuserData() { String url = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address)"; APIHelper apiHelper = APIHelper.getInstance(getApplicationContext()); apiHelper.getRequest(this, url, new ApiListener() { @Override public void onApiSuccess(ApiResponse apiResponse) { // Success! try { JSONObject jsonObject = apiResponse.getResponseDataAsJson(); firstName = jsonObject.getString("firstName"); lastName = jsonObject.getString("lastName"); userEmail = jsonObject.getString("emailAddress"); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("First Name " + firstName + "\n\n"); stringBuilder.append("Last Name " + lastName + "\n\n"); stringBuilder.append("Email " + userEmail); user_detail.setText(stringBuilder); } catch (JSONException e) { e.printStackTrace(); } } @Override public void onApiError(LIApiError liApiError) { // Error making GET request! Toast.makeText(getApplicationContext(),"API Error"+liApiError.toString(),Toast.LENGTH_LONG).show(); } }); } } |
Output 1:
Output 2: