Friendly Score Android SDK Integration

The repository provides access to Friendly Score Android SDK. It includes a demo app, the libraries that are needed to create your own app. The documentation also goes through some of the key code included in the DEMO app.

Getting Started

These instructions will help you get started to integrate FriendlyScore Android SDK in your App.

Prerequisites

Android Studio Stable Version.

Supports Android SDK >=18(Jelly Bean)

Pay attention to conflicts arising due to dependencies on different versions.

Currently, all the SDK dependencies are listed in friendlyscore-libs & in app/build.gradle.

The key things to focus is on having the identical version numbers in your app/build.gradle. If you add any of the dependencies listed above. Also, your

    minSDKVersion should be >=18.

    buildToolsVersion should be "27.0.3".

Friendly Score App Id. You can get one at Friendly Score for Businesses


Social Media Authentication Pre-requisites


Do not forget to add your authentication API keys for Google, Facebook, Twitter(In res/values/strings.xml) and Paypal(In Code).

Remember to change your API Keys to production, when you launch the Apps.

You need to do this only for the Social Media accounts you have enabled for your Friendly Score App.

Generating Hash Keys.

  • Debug Keys

Windows

keytool -exportcert -keystore %HOMEPATH%.android\debug.keystore -alias androiddebugkey | openssl sha1 -binary | openssl base64

MAC OS/UNIX

keytool -exportcert -keystore ~/.android/debug.keystore -alias androiddebugkey | openssl sha1 -binary | openssl base64

  • Release Keys

keytool -exportcert -keystore YOUR_RELEASE_KEY_PATH -alias YOUR_RELEASE_KEY_ALIAS | openssl sha1 -binary | openssl base64

Google - Google Developer Console Dashboard

Scopes are set in Code(Included as Constants in the SDK)

Create Android API Key Credentials Credentials

  1. Google Calendar API

  2. Analytics API

  3. Google+ API

  4. Gmail API

  5. IdentityToolkit API

  6. Google Drive API


Twitter - Twitter My Apps

Scopes - Read, write, and direct messages

These are set in the Access level section of Application Settings

You will need to use the Consumer API Key Listed in the Application Setting, used in the Android App you create.


Linkedin - Linkedin apps

Scopes - r_basicprofile, r_emailaddress, rw_company_admin, w_share

Create an app and in the authentication section set the above mentioned scopes. You will need your app package name and package hash(mentioned earlier).

You can use the Linkedin android SDK or Oauth to connect to Linkedin. Linkedin SDK, will force the user to download the Linkedin App. Using Oauth the user can sign in to Linkedin in the webview. Both implementations are included in the demo app.


Paypal - Paypal My Apps

Scopes(Just for information) - openid(Basic Authentication. Its already set), email, phone, address, profile.

Due to the way Paypal Authentication operates please contact us for the Paypal Client ID to use in your Friendly Score, which you can do so on the Slack Channel, https://friendlyscoregroup.slack.com

Create App Using the Downloaded Git Repository

  1. Download the repository and unzip it.
  2. Open Android Studio and Go to File->New->Import Project.
  3. Navigate to the folder where you unzip the repository. Select the 'FriendlyscoreandroidDEMO' folder and press OK.
  4. Let the project get set up. You may have to update gradle version and android support files. Android Studio would directly prompt you.
  5. Once the project is loaded. Go to StartActivity. Add your FriendlyScore App Id as the value of the String. private String client_id = "YOUR_FRIENDLYSCORE_CLIENT_ID";
  6. You would need an App Registered to use Google, Linkedin, Twitter and Paypal Authentication with Appropriate Authentication Scopes. The previous section provided links and details on scopes for each of the social media authentication process.
  7. Once you have the appropriate keys and ids, please add values for the keys in SocialCredentials.java in the demo

7a. For Twitter:

    /****YOUR TWITTER APP INFO HERE*********/
public static final String TWITTER_CONSUMER_KEY = "twitter_api_key";
public static final String TWITTER_CONSUMER_SECRET_KEY = "twitter_api_secret";

7b. For Google: Ensure google-services.json is added to app/ folder.

7c. For Paypal: Please contact us for information on the client_id to use for integrating Paypal.

    /*

Paypal
 */


public static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_PRODUCTION;
public static final String FSCORE_PROD_CONFIG_CLIENT_ID = "paypal_client_id";
public static final int REQUEST_CODE_PROFILE_SHARING = 3;

7c. For Linkedin: No variables needed.(Just the LinkedinSDK) or for OAuth, you need the Linkedin client_id and client_secret

/****YOUR LINKEDIN APP INFO HERE*********/
public static final String API_KEY = "linkedin_api_key";
public static final String SECRET_KEY = "linkedin_secret";
  1. You should be ready. If you have connected a device, run by clicking on the green arrow.

Create App From Scratch

  • Create a new App in Android Studio.Create Android App

  • Keep your app package, it will be needed later.

  • App Registered to use Google, Linkedin, Twitter and Paypal Authentication with Appropriate Authentication Scopes

Add FriendlyScore Android SDK to your project

From the downloaded repository, in the folder FriendlyScoreAndroidSDK are the two .AAR files needed to add FriendlyScore features to your app.

fs-core-sdk-release-2.24.aar
fs-ui-sdk-release-2.53.aar
fs-location-sdk-release-1.28.aar
fs-calendar-sdk-release-1.1.aar
fs-contacts-sdk-release-1.1.aar
fs-camera-sdk-release-1.2.aar
fs-calls-sms-sdk-release-1.001.aar

Create a Library module using the downloaded modules.

All the required external libraries required by the SDK are included in the friendlyscore-libs module.Please import this module to your project and include it in your projects app/build.gradle


  1. In Android Studio, choose File->New->New Module.
  2. Select Import .JAR/.AAR Package option and Press Next.
  3. In File Name choose the AAR file from the various modules.
  4. In Subproject name add the name to the library module. For example FriendlyScoreAndroidSDK and Press Finish.
Add the created library module.
compile project(':fs-core-sdk-release-2.24')

Follow the above steps for creating and add library module for other modules.

Let the project creation finish and sync.

Before integration, please ensure you have followed these steps so you can add the various social authentications to your app.

You would need an App Registered to use Facebook, Google, Linkedin, Twitter and Paypal Authentication with Appropriate Authentication Scopes. The Social Media Authentication Pre-requisite section provided links and details on scopes for each of the social media authentication process.

  1. Once you have the appropriate keys and ids, please follow the steps below

1a. For Twitter:

/****YOUR TWITTER APP INFO HERE*********/
public static final String TWITTER_CONSUMER_KEY = "twitter_api_key";
public static final String TWITTER_CONSUMER_SECRET_KEY = "twitter_api_secret";

1b. For Google: Ensure google-services.json is added to app/ folder.

1c. For Paypal: Please contact us for information on the client_id to use for integrating Paypal.

    private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_PRODUCTION;
    private static String FSCORE_PROD_CONFIG_CLIENT_ID = "";

1d. For Linkedin: Do nothing if you use the LinkedinSDK or for OAuth

    /****YOUR LINKEDIN APP INFO HERE*********/
public static final String API_KEY = "linkedin_api_key";
public static final String SECRET_KEY = "linkedin_secret";

Once you have the FriendlyScore APP ID and your APP registered with Social Networks and the respective Authentication Keys, you can proceed towards Integration. This flow can also be used to understand the flow of the DEMO app.

In the onCreate function of the LaunchActivity of your app add the following

 try {
        ProviderInstaller.installIfNeeded(getApplicationContext());
    } catch (GooglePlayServicesRepairableException e) {
        e.printStackTrace();
    } catch (GooglePlayServicesNotAvailableException e) {
        e.printStackTrace();
    }

This allows the OS to download any relevant security libraries that are not available on the device as the OS has not been updated.


1. Create an Activity which will start the FriendlyScore UI flow say after clicking a button('Connect to FriendlyScore' in StartActivity in the demo application). In the DEMO app, this activity sends the user identification, if its a repeat user & the FriendlyScore APP ID

2. To call FriendlyScore in your onCreate function in StartActivity

     public void startCred(){
    String client_id = "your_friendly_score_client_id";

    //
    Credentials credentials = new Credentials(client_id, this);


    credentials.getFriendlyScoreInstance(ClientPrefsHelper.readAppUserToken(this));

}

3. In order to listen for any Error messages in the initialising process

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(FriendlyScoreError friendlyScoreError){

    Log.d(TAG, friendlyScoreError.getErrorMessage());
}

@Override
protected void onStart() {
    super.onStart();

    if(!EventBus.getDefault().isRegistered(this))
        EventBus.getDefault().register(this);
}


@Override
protected void onDestroy() {
    super.onDestroy();
    if(EventBus.getDefault().isRegistered(this))
        EventBus.getDefault().unregister(this);

}


//If you want to log signinevents
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(SignInEvents signInEvents){

    Log.d(TAG,"signinevents:"+signInEvents.event_name+":"+signInEvents.message);

}

@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessage(UIConfigsDownloaded uiConfigsDownloaded){

    Log.d(TAG,"uiConfigsDownloaded");
    if(Configs.getUiConfigValue()!=null){
        UIConfigs.parseUIConfig();

        if(ClientPrefsHelper.readAppUserToken(this)!=null)
        {
            if(!loaded)
            {
                loaded = true;
                startScoringProcess();
            }

        }
        else
        {
            startAuthProcess();
        }
    }

}

 private void startScoringProcess(){

    loaded = false;
    Intent clientIntent = null;

    int requestcode =  FRIENDLY_SCORE_NEW_AUTH;

    clientIntent = new Intent(this, ClientActivity.class);

    startActivityForResult(clientIntent, requestcode);

}
private void startAuthProcess(){
    Intent clientIntent = null;

    int requestcode = FRIENDLY_SCORE_NEW_AUTH;

    clientIntent = new Intent(this,SignUpActivity.class);

    startActivityForResult(clientIntent, requestcode);

}

4. Create the FriendlyScore UI. You do that by extending LaunchUI

  public class ClientActivity extends FSUIView

5. You have to implement the function below to connect to the appropriate data source, based on the Connect Button user clicks the button in the FriendlyScore UI.

    @Override
public void setClicked(int networkType, boolean connected) {

    //Log.d(TAG,event.networkType);
    switch (networkType){
        case Constants.GOOGLE_ID:
            signInWithGoogle();
            break;
        case Constants.TWITTER_ID:
            executeTwitterLogin();
            break;
        case Constants.LINKEDIN_ID:
            linkedinOauth();
    //If you implement using linkedinSDK, linkedinSDK().
            break;
        case Constants.PAYPAL_ID:
            onProfileSharing();
            break;
    case Constants.INSTAGRAM_ID:
            loginWithInstagram();
            break;
    }

An example of implementing Google Authentication is explained in detail later, in the next section.

6. To access the user identifier for FriendlyScore

ClientPrefsHelper - package is changed to *com.friendlyscore.ClientPrefsHelper* from *com.FriendlyScoreUI.ClientPrefsHelper*
ClientPrefsHelper.readAppUserToken(context)

7. Once you have data from the respective social networks, you have to send the data to FriendlyScore. You need to pass the data along with the identification of Social Network. This can be got using Constants.GOOGLE_AUTH for example. Similarly for other networks.

        Post2FriendlyScore.post(AppConstants.callAct, ClientPrefsHelper.readAppUserToken(AppConstants.callAct),info.toString(), com.friendlyscore.Constants.GOOGLE_ID);

9. To enable logging add the setting

Configs.logging = true. 
But default it is set to false. To use it make sure, the below grade is enabled. Included in friendlyscore-libs/build.gradle
implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'

Steps for allowing sign in with Google

1. For the ClientActivity class created before, implement GoogleApiClient.OnConnectionFailedListener.

  public class ClientActivity extends LaunchUI implements
    GoogleApiClient.OnConnectionFailedListener{

    private GoogleApiClient mGoogleApiClient;

    //Used in Google Auth
    private static final int GOOGLE_SIGN_IN_CODE = 9001;

    ...
    }

2. To use Google Sign in, Google Play Services must be upto date. This check can be done in this way.

    //For Google Login, ensure you check for presence of Google Play Services
    @Override
        public  boolean checkGooglePlayServicesVersion(){
            int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

            switch (status){
                case ConnectionResult.SUCCESS:
                    return true;
                case ConnectionResult.SERVICE_MISSING:
                    showGooglePlayServicesErrorAlert(
                            getResources().getString(R.string.no_google_play_services),
                            getResources().getString(R.string.no_google_play_services_title));
                    return false;
                case ConnectionResult.SERVICE_UPDATING:
                    showGooglePlayServicesErrorAlert(
                            getResources().getString(R.string.google_play_services_updating),
                            getResources().getString(R.string.google_play_services_updating_title));
                    return false;
                case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
                    showGooglePlayServicesErrorAlert(
                            getResources().getString(R.string.google_play_services_update),
                            getResources().getString(R.string.google_play_services_title_update));
                    return false;
                case ConnectionResult.SERVICE_DISABLED:
                    showGooglePlayServicesErrorAlert(
                            getResources().getString( R.string.google_play_services_disabled),
                            getResources().getString(R.string.google_play_services_disabled_title));
                    return false;
                case ConnectionResult.SERVICE_INVALID:
                    showGooglePlayServicesErrorAlert(
                            getResources().getString(R.string.google_play_services_invalid),
                            getResources().getString(R.string.google_play_services_invalid_title));
                    return false;
           }
          return false;
     }

3. Call this function in onCreate, as below.

    checkGooglePlayServicesVersion()

4. Next You need to Set Up Google Auth.

    //The function sets up the process for authentication with Google with
    //appropriate scopes and permissions. This is necessary or it would trigger
    //error by the SDK in computing user score.
    private void setUpGoogle(){
          GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                  .requestIdToken(getString(R.string.default_web_client_id))
                  .requestServerAuthCode(getString(R.string.default_web_client_id))
                  .requestScopes(
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[0]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[1]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[2]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[3]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[4]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[5]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[6]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[7]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[8]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[9]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[10]),
                          new com.google.android.gms.common.api.Scope(Constants.GOOGLE_SCOPES[11])
                  )
                  .requestEmail()
                  .build();
          // [END config_signin]

      mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this , this)
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();
      }

      @Override
      public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
          // An unresolvable error has occurred and Google APIs (including Sign-In) will not
          // be available.
          Log.d(TAG, "onConnectionFailed:" + connectionResult);
          //Toast.makeText(this, "Google Play Services error.", Toast.LENGTH_SHORT).show();
      }

5. Cal this function in your onCreate function.

    setUpGoogle();

6. Sign in With Google Function that must be called from the setClicked function described earlier.

  private void signInWithGoogle(){
    mGoogleApiClient.clearDefaultAccountAndReconnect();
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, GOOGLE_SIGN_IN_CODE);
  }

6. Handle the Sign in flow result.

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
        if (requestCode == GOOGLE_SIGN_IN_CODE) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = result.getSignInAccount();

                handleGoogleAuthorization(account);
            } else {

                // Google Sign In failed, update UI appropriately

              //Defined in LaunchUI
                userAuthError(Constants.GOOGLE_AUTH);

              }
          }
      }

      private void handleGoogleAuthorization(GoogleSignInAccount acct){
          //For score calculation using Google Authentication on Android, we need
          //IdToken and ServerAuthorizationCode.
          //Code is Below
              new GoogleServerAuthCodeTask(this).execute(acct.getEmail(),"com.google",acct.getIdToken());
              Log.d(TAG,acct.getIdToken());
      }

7. For score calculation using Google Authentication on Android, we need IdToken and ServerAuthorizationCode. The previous section showed how to get the IdToken. Below is the code to get the ServerAuthorizationCode.

    import android.accounts.Account;
    import android.app.Activity;
    import android.os.AsyncTask;

    import com.google.android.gms.auth.GoogleAuthUtil;
    import com.google.android.gms.auth.UserRecoverableAuthException;

    import org.json.JSONObject;

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.Calendar;

    import FriendlyScore.Constants;
    import FriendlyScore.SendToFriendlyScore;


    public class GoogleServerAuthCodeTask extends AsyncTask<String, Void, JSONObject> {


        String TAG = "GoogleServerAuthCodeTask";

        Activity callAct;
        public GoogleServerAuthCodeTask(Activity act){

            callAct = act;
        }
        @Override
        protected JSONObject doInBackground(String... params) {
            HttpURLConnection urlConnection = null;

            JSONObject googleToken = new JSONObject();

            String mEmail = params[0];
            String mType = params[1];
            String idToken = params[2];
            try {
                URL url = new URL("https://www.googleapis.com/plus/v1/people/me");

                Account account = new Account(mEmail, mType);

                String scope = Constants.GOOGLE_SERVER_CODE_SCOPE;
                String token =  GoogleAuthUtil.getTokenWithNotification(callAct, account, scope,null);



                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestProperty("Authorization", "Bearer " + token);

                BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
                StringBuilder total = new StringBuilder();
                String line;
                while ((line = r.readLine()) != null) {
                    total.append(line).append('\n');
                }

                googleToken.put("id_token",idToken);
                googleToken.put("access_token",token);

            } catch (UserRecoverableAuthException userAuthEx) {
                // Start the user recoverable action using the intent returned by
                // getIntent()
                //startActivityForResult(userAuthEx.getIntent(), RC_SIGN_IN);

                return null;
            } catch (Exception e) {
                // Handle error
                // e.printStackTrace(); // Uncomment if needed during debugging.
                return null;

            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }

            return googleToken;
        }

        @Override
        protected void onPostExecute(JSONObject info) {
            // Store or use the user's email address
            if(info!=null)
                new SendToFriendlyScore(callAct).execute(info.toString(), Constants.GOOGLE_AUTH);
            else{
                //TODO(Inform User to Add Appropriate Message For User)
            }
        }

    }

If you wish to Customize

To change the toolbar back button icon

    setToolbarIcon(R.drawable.my_back_button_icon);

To change the toolbar settings icon

    setOverflowIcon(getResources().getDrawable(R.drawable.my_overflow_menu_icon));

values/client_colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <color name="colorPrimary">#7038A7</color>

    <color name="colorPrimaryDark">#6538A7</color>

    <color name="colorAccent">#E91171</color>

    <color name="colorCardStart">#E91171</color>

    <color name="colorPhoneRect">#E91171</color>

    <color name="colorCardEnd">#E91171</color>

    <color name="colorAppBackgroundStart">#fff</color>

    <color name="colorAppBackgroundEnd">#fff</color>

    <color name="colorCompleteButtonStart">#7038A7</color>

    <color name="colorCompleteButtonEnd">#7038A7</color>

    <color name="colorCompleteButtonPressed">#9838A7</color>

    <color name="complete_button_label_color">#ffffff</color>

    <color name="info_label_color">#ffffff</color>

    <color name="average_score_bar_color">#E91171</color>

    <color name="your_score_bar_color">#7038A7</color>

    <color name="bar_background_color">#f6f6f6</color>

    <!--TODO(Cannot be adjusted on Android)-->
    <color name="default_drop_shadow_color">#000000</color>

    <!--TODO(Inform client to add, Not in configuration)-->
    <color name="connectDataColorButtonPress">#80d33a6d</color>

    <color name="unselected_pager_color">#000</color>

    <color name="selected_pager_color">#fff</color>

    <color name="initial_loading_color_start">#fff</color>

    <color name="initial_loading_color_end">#fff</color>

    <color name="toolbar_text_color">#000</color>

    <color name="toolbar_icon_color">#000</color>

    <color name="toolbar_background">#3F51B5</color>




    <!--SMS Auth Colors-->

    <color name="country_code_color">#FFF</color>

    <color name="greeting_label_color">#6dcddd</color>

    <color name="arrow_resend_color">#6dcddd</color>

    <color name="verify_box_start_color">#d33a6d</color>

    <color name="verify_box_end_color">#d33a6d</color>

    <color name="sms_code_hint_color">#F48FB1</color>

    <!--- Form Colors -->
    <color name="switch_color_thumb_text">#ffffff</color>

    <color name="colorSwitchThumbNormal">#ff0000</color>

    <color name="switch_color_track">#ffffff</color>

    <color name="hint_color">#a9a9a9</color>

    <color name="section_divider">@android:color/darker_gray</color>

    <color name="error_color">#D32F2F</color>

    <color name="tint_color">#FFFF</color>

    <!--Photo Section Colors-->
    <color name="colorPhotoUpdating">#7038A7</color>
    <color name="colorPhotoRemove">@android:color/transparent</color>

    <!--Location Section Colors-->
    <color name="colorLocationOn">#7038A7</color>


    <color name="colorMapRadius">#E91171</color>

    <color name="colorInfoWindowBorder">#2196aa</color>


    <color name="colorBackground">#FF4081</color>

    <color name="scoreTextColors">#000</color>

    <color name="form_direct_color">#000</color>

    <color name="form_text_color">#000</color>

    <color name="form_background">#fff</color>

    <color name="main_text_color">#000</color>


</resources>

Additional Functionality & Information

When building a release version of the app, it is necessary to sign it with a key. In Android studio when generating the release version, sign with both v1(jar - to release on devices with OS before Android 7.0) & v2(apk to release on devices with OS Android 7.0 onwards)

You can check the list of users you add online on friendlyscore.com in your business account.
To Generate List of your clients, Follow the instructions Integrate Friendly Score

In order to customize the text of the UI flow please contact us, in the Slack Channel https://friendlyscoregroup.slack.com