Skip to content
Vinayaga Sundar edited this page Jan 11, 2018 · 21 revisions

Generic Partner Application

Generic Partner App is a distribution of data between Ekstep(Genie) and it's partner.

Generic Partner App will launch from Genie App and the Partner Apps to register, manage sessions and send partner data to Genie via Genie-Service SDK. After completion of all the process then the Partner app should launch a Genie App.

Generic Partner App will register one time after successful registration, it could be start session and send partner data to Genie Services.

Genie Service Usage:

The Genie service sdk is used by the Partner Apps to register, manage sessions and send partner data to Genie.

1. Add dependencies in your build.gradle(app module) files

	buildscript {
		repositories {
			maven { url "https://platform.ekstep.in/downloads/content/repositories/production" }
		}
	}
    
	repositories {
		maven { url "https://platform.ekstep.in/downloads/content/repositories/production" }
	}

	dependencies {
	    compile "org.ekstep.genieservices:genie-integration:1.0.32"
	}

2. Initiaiize Genie SDK: Initiailize the Genie SDK in Application class before using any Genie API.

public class PartnerApps extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        GenieSDK.init(this, "org.ekstep.genieservices");
    }
}

3. Register Partner: Partner App will register only once. After successful registration, it could start session and send partner data to Genie Services

    //Sample code
    PartnerData partnerData = new PartnerData(null, null, PARTNER_ID, null, PARTNER_PUBLIC_KEY);
    PartnerService partnerService = GenieSDK.getGenieSDK().getPartnerService();
    partnerService.register(partnerData, responseHandler);
   
    /**
     * This api is used to register a partner with the specified partnerID and publicKey in PartnerData
     * <p>
     * <p>On successful registering the partner, the response will return status as TRUE and with "successful" message.
     * <p>
     * <p>On failing to register the partner, the response will return status as FALSE and the errors could be one of the following:
     * <p>MISSING_PARTNER_ID - partnerID is not provided</p>
     * <p>MISSING_PUBLIC_KEY - publicKey is not provided</p>
     * <p>INVALID_RSA_PUBLIC_KEY - publicKey is not as per specs</p>
     * <p>INVALID_DATA - some data is still invalid</p>
     *
     * @param partnerData
     * @param responseHandler
     */
    public void registerPartner(PartnerData partnerData, IResponseHandler<Void> responseHandler) 

4. Start Partner Session:

    //Sample code
    PartnerData partnerData = new PartnerData(null, null, PARTNER_ID, null, PARTNER_PUBLIC_KEY);
    PartnerService partnerService = GenieSDK.getGenieSDK().getPartnerService();
	partnerService.startPartnerSession(partnerData, IResponseHandler);
	
   
    /**
     * This api is used to start the Partner Session with the specified partnerID in PartnerData.
     * <p>
     * <p>On successful starting the session, the response will have status as TRUE and message as "successful".
     * <p>
     * <p>
     * <p>On failing to start the session, the response will have status as FALSE with the following error.
     * <p>UNREGISTERED_PARTNER - Session start failed! Partner: <partnerId> </p>
     *
     * @param partnerData
     * @param responseHandler
     */
    public void startPartnerSession(PartnerData partnerData, IResponseHandler<Void> responseHandler)

5. Create Profile:

    //Sample code
    Profile profile=new Profile("Name","Avatar","en");
    profile.setStandard(5);
    profile.setGender("Male");
    profile.setAge(10);
	
    UserService userService = GenieSDK.getGenieSDK().getUserService();
    userService.createUserProfile(profile, IResponseHandler);

    /**
     * This api is used to create a new user with specific {@link Profile}.
     * <p>
     * <p>On Successful creation of new profile, the response will return status as TRUE and with successful message
     * <p>
     * <p>On failing to delete a user, the response will have status as FALSE with the following error:
     * <p>FAILED - createProfile
     *
     * @param profile         - {@link Profile}
     * @param responseHandler - {@link IResponseHandler<Map>}
     */
    public void createUserProfile(Profile profile, IResponseHandler<Map> responseHandler) 

6. Set Current User:

 //Sample code
 UserService userService = GenieSDK.getGenieSDK().getUserService();
 userService.setUser(UID, IResponseHandler) //This UID will get it from CreateUserProfile response data...

 /**
  * This api sets the specific uid passed to it as active current user.
  * <p>
  * <p>
  * <p>On successful setting a user active, the response will return status as TRUE and with successful message
  * <p>
  * <p>On failing to set the uid to current user, the response will have status as FALSE with the following error:
  * <p>INVALID_USER
  *
  * @param uid
  * @param responseHandler - {@link IResponseHandler<Void>}
  */
 public void setUser(final String uid, IResponseHandler<Void> responseHandler)

7. Send Partner Data to Genie Services:

    //Sample code
	Map<String,Object> partnerDataMap = new HashMap<>();
	partnerDataMap.put("userId", UID); //Child user id generated by Genie Services...
	
	partnerDataMap.put("child_name", "TestUser");
    partnerDataMap.put("father_name","Gupta");
    partnerDataMap.put("_class", 5);
    partnerDataMap.put("sex", "Male");
    partnerDataMap.put("dob", "31-12-1998");
    partnerDataMap.put("district", "Bangalore-urban");
    partnerDataMap.put("block","Bangalore");
    partnerDataMap.put("clust","Bommanahalli");
    partnerDataMap.put("school_name", "Govt school");
    partnerDataMap.put("school_code", "123");

    JSONObject partnerJSONObject = new JSONObject(partnerDataMap);

    PartnerData partnerData = new PartnerData(null, null, PARTNER_ID, partnerJSONObject.toString(),
                PARTNER_PUBLIC_KEY)
    PartnerService partnerService = GenieSDK.getGenieSDK().getPartnerService();
	partnerService.sendPartnerData(partnerData, IResponseHandler);
   
   
     /**
     * This api is used to send Partner data specified in PartnerData. This api will encrypt the partnerData with the publicKey given earlier during registration.
     * <p>
     * <p>On successful sending the data, the response will have status as TRUE and result can be fetched from the response.
     * <p>
     * <p>On failing to send data, the response will return status as FALSE and the errors could be one of the following:
     * <p>UNREGISTERED_PARTNER - Sending data failed! Partner: <partnerId> </p>
     * <p>ENCRYPTION_FAILURE - Encrypting data failed! Partner: <partnerId> </p>
     *
     * @param partnerData
     * @param responseHandler
     */
    public void sendData(final PartnerData partnerData, IResponseHandler<Map> responseHandler)

8. Send Telemetry Data to Genie services

 String event = "{
   "eid": "OE_END", // unique event ID
   "ets": 1442816723,
   "ver": "2.0",
   "gdata": {
 	 "id": "lit.scrnr.kan.android",
 	 "ver": "1.0"
   },
   "sid": "de305d54-75b4-431b-adb2-eb6b9e546013",
   "uid": "123e4567-e89b-12d3-a456-426655440000",
   "did": "ff305d54-85b4-341b-da2f-eb6b9e5460fa",
   "edata": {
 	 "eks":{
 		"length": 1234567 // length of the game session in seconds
 	 }
   }
 }";

 //Sample code
 TelemetryService telemetryService = GenieSDK.getGenieSDK().getTelemetryService();
 telemetryService.saveTelemetryEvent(event, IResponseHandler);


/**
  * Send a telemetry event to genie-services
  *
  * @param event           {@link String} The telemetry event will be a json string.
  * @param responseHandler {@link IResponseHandler} This is the callback. The class needs to be defined in client  handling both success and failure scenario
  * <p>
  * <p> In case of a successful response onSuccess will be called, response.getStatus() will return successful.
  */
public void saveTelemetryEvent(String event, IResponseHandler responseHandler);	

9.Terminate Partner Session:

    //Sample code
    PartnerData partnerData = new PartnerData(null, null, PARTNER_ID, null, PARTNER_PUBLIC_KEY);
    PartnerService partnerService = GenieSDK.getGenieSDK().getPartnerService();
	partnerService.endPartnerSession(partnerData, IResponseHandler);
    
	/**
     * This api is used to terminate the Partner Session with the specified partnerID.
     * <p>
     * <p>On successful terminating the session, the response will have status as TRUE and message as "successful"
     * <p>
     * <p>
     * <p>On failing to start the session, the response will have status as FALSE with the following error.
     * <p>UNREGISTERED_PARTNER - Session start failed! Partner: <partnerId> </
     *
     * @param partnerData
     * @param responseHandler
     */
    public void endPartnerSession(PartnerData partnerData, IResponseHandler<Void> responseHandler)

10. Launch Genie App: While launching Genie partner app can send partner related information so that Genie will show partner specific content

Partner app can send following information

1. Audience

Audience can be of 2 types

  • learner
  • instructor

2. Channel

Contact Ekstep team to get details about the channel

3. Language

The type of language partner want in Genie.The partner will have to send ISO 639 language code.Currently Genie supports English(en),Hindi(hi),Telegu(te),Marathi(mr),Tamil(ta).

4. Mode

Mode can be soft or hard

If the mode is set to soft then partner can see its channel specific content along with other channel contents and if mode is set to hard then partner can only its channel specific contents.

5. Program Tag

If partners want to create a program tag to keep track of their events then they can send a program tag and Genie will tag all the events with the provide tag.

Partner will have to provide following info to Genie to create a Program tag

  • Name
  • Description
  • Start Date
  • End Date

Sample usage

private void launchGenieApp(Context context){
       PackageManager manager =context.getPackageManager();
        try {
            Intent intent = manager.getLaunchIntentForPackage("org.ekstep.genieservices");
            intent.addCategory(Intent.CATEGORY_LAUNCHER);
            
            String [] audienceArray = {"learner"};
            String [] channelArray = {"AP_1"};
            intent.putExtra("audience_array", audienceArray);
            intent.putExtra("channel_array", channelArray);

            HashMap<String,String> programTag=new HashMap<>();
            programTag.put("name","SampleTagName");
            programTag.put("desc","SampleTagDesc");
            programTag.put("startDate","2017-05-16");
            programTag.put("endDate","2017-05-26");

            intent.putExtra("program_tag",programTag);
            intent.putExtra("language","hi");
            intent.putExtra("mode","hard");
            context.startActivity(intent);
        } catch (Exception e) {}
 }

Steps to Generate RSA public and private keys:

  1. Download openssl from this link:   http://www.indyproject.org/Sockets/fpc/OpenSSLforWin64.en.aspx
  2. Extract the downloaded folder and click on "openssl.exe" then it will open cmd prompt.(Right click and Run as a Administrator)
  3. To generate an RSA Private key pair use: (Type below cmd in the cmd prompt)    
    genrsa -out rsa_1024_priv.pem 1024
  4. This private key file "rsa_1024_priv.pem" will be generated on your extracted folder.
  5. To generate the Public Key in PEM format use:(Type below cmd in the cmd prompt)    
    rsa -pubout -in rsa_1024_priv.pem -out rsa_1024_pub.pem
  6. This public key file "rsa_1024_pub.pem" will be generated on your extracted folder.

Sample Source code:

The minimum requirements for Android Studio are:
Windows

  1. Microsoft Windows 10/8/7/Vista/2003 (32 or 64-bit)
    2.Java Development Kit (JDK) 7

Mac OS X

  1. Mac OS X 10.8.5 or higher, up to 10.9 (Mavericks)
  2. Java Runtime Environment (JRE) 6
    Java Development Kit (JDK) 7

Linux

  1. GNOME or KDE desktop
  2. Oracle Java Development Kit (JDK) 7

Software required
1.Android studio
http://developer.android.com/sdk/index.html
2. JDK
http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html

Installation
1.Install JDK
2.Set Path of JDK in Windows follow below links
http://www.javatpoint.com/how-to-set-path-in-java

After setting path restart system.
3.Install Android studio
After successful installation open Android studio.

Source Code
1.Download the source code
https://github.com/ekstep/EkStep-Partner-App

  1. Unzip(extract) it

    After successful this, You have source-code of Generic partner app.

Import Source Code into Android Studio
1.Open Android Studio

2.Select File option(from Top left corner) then select Open.. Option
Then select path of source code( e.g. E:\EkStep-Partner-App-master)

3.Left SIDE-BAR there is option project click on Project
You will see EkStep-Partner-App-master(Project-name)

4.Click on EkStep-Partner-App-master ->app->src->main->assets->config.json

5.Open Config.json file
a. Configuration file(config.json) where Partner can define their name and own set of rules like number of fields with description with their data types.
b. Change in this file according to your requirements.

6 . To Change Logo of App
a). Go inside particular folder
C:\Generic-Scripts-PUBLIC-master\app\src\main\res
b). Copy icon inside
drawable-hdpi
drawable-mdpi
drawable-xhdpi
drawable-xxhdpi
drawable-xxhdpi

With respective dimensions name as partner_logo each image(there is already partner_logo just overwrite it)
7. Change App Name

  1. Open String.xml file, You will find this file
    Generic-Partner-App\app\src\main\res\values
  2. Inside String.xml file
    you will find "GPA "
    change GPA by Partner-Name

8.Run option on Top toolbars
Click Run->Run app
After successful running it will build apk at following locations

C:\Generic-Scripts-PUBLIC-master\app\build\outputs\apk
Generic-Partner-App-1.0.local-debug.apk

Now you can install this apk .
Enjoy :)

Here example of Config.json file

{
  "partnerName": "LME",
  "partnerId": "org.ekstep.partner.lme",
  "partnerPublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvgDm/lRk4ZU4ZUAaLRqXhzxGbRzSFOjOsIEgGAMYkh3+pULK/9evvOhI5X2afbnLLTo6h9MzjzWKio/G5jTH8YRS61ohBnhL8TKkVwXlU9GYnvOZimIoizPXimhNrVcAYvo4GNwrB9sxGFyNPup0CBCnyWifdhKOWGo5LGhNCP9ehmJJchPw23RN+VeF/fsW9WVJNTZFXy4WYbsM7YVGcQWYgCZX4eNqBcckP3aXaFTej1pPHfti2n+BLmudGK60lnZ4ePBidEi6WoPzpMrdMnwzkYOnQ8KBV0LKJr0vzqATzxGMC85fo1OUm+ZMobdl8SCLAzn5+2WFnNKyct1mtwIDAQAB",
  "sections": [
    //------------------Section represented by[ ] --------------------
    [
      {
        "SectionHeading": "Employee Details",  //Section 1st heading it will display on Top
        "instructions": {
          "title": "Star(*) denotes Mandatory field.",  //if Any instruction you want to give inside partucular section  as title
          "displayOrder": 2  // displayOrder representing position of  field ,it will show  at 2nd position inside partucular section
        }
      },
      {
        "fieldName": "Email-Id",   //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "Text",
          "fieldInputType": "textEmailAddress", //where user will enter email  e.g. [email protected]
          "validation": {
            "flag": false,  //false represents don't validate field
            "minimum": 8,   // It represents mimimum '8' character should  be
            "maximum": 12   // It represents maximum '12' character should  be
          }
        },
        "fieldHint": "enter aplhabet character",  //fieldHint as Help what fieldInputType should be
        "displayOrder": 1,  //displayOrder representing position of  field, it will show  at 1st position inside first section
        "fieldValues": []
      },
      {
        "fieldName": "FirstName", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "Text",
          "fieldInputType": "text",//where user will enter FirstName  e.g. Dhruv
          "validation": {
            "flag": true,  //true represents  validate field
            "minimum": 3,  // It represents mimimum '3' character should  be
            "maximum": 25  // It represents maximum '25' character should  be
          }
        },
        "fieldHint": "enter aplhabet character",
        "displayOrder": 13,
        "fieldValues": []
      },
      {
        "fieldName": "Skills", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "MultipleChoiceMore", //MultipleChoiceMore means You can select one or more options
          "fieldInputType": "None", //fieldInputType None means where user has to select from given option
          "validation": {
            "flag": true,  //true represents  validate field
            "minimum": 1,  // It represents mimimum '1' field has to select
            "maximum": 2   // It represents maximum  '2' field has to select
          }
        },
        "fieldHint": "You can select one or more options",
        "displayOrder": 5,
        "fieldValues": ["Java","PHP","Android","SAP"] // It showing the option list corresponding to field
      },
      {
        "fieldName": "Gender", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "MultipleChoiceSingle", //MultipleChoiceSingle means You can select only one option
          "fieldInputType": "None",
          "validation": {
            "flag": true, //true represents  validate field
            "minimum": 1, // It represents mimimum '1' field has to select
            "maximum": 1  // It represents maximum '1' field has to select
          }
        },
        "fieldHint": "You can select one option only",
        "displayOrder": 6,
        "fieldValues": ["Male","Female"]
      },
      {
        "fieldName": "Password", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "Text",
          "fieldInputType": "textPassword", //textPassword means it will hide what user is enetered e.g. ********
          "validation": {
            "flag": true, //true represents  validate field
            "minimum": 6,  // It represents mimimum '6' character should be
            "maximum": 10  // It represents maximum '10' character should be
          }
        },
        "fieldHint": "enter password max 10 char",
        "displayOrder": 4,
        "fieldValues": []
      },
      {
        "fieldName": "Joining Date", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "Text",
          "fieldInputType": "date", //User has to select date from calander
          "validation": {
            "flag": true, //true represents  validate field
            "minimum": 1, // It represents mimimum '1' year should be from current date
            "maximum": 2 // It represents maximum '2' year should be from current date
          }
        },
        "fieldHint": "select date from calander",
        "displayOrder": 3,
        "fieldValues": []
      }
    ],
    //----------------------end of Section First-------------------------------------------
    //---------------------- Section Second-------------------------------------------

    [
      {
        "SectionHeading": "Address Details", //Section 2nd heading it will display below Section First
        "instructions": {
          "title": "",   //if Any instruction you want to give inside partucular section  as title, Here no instruction
          "displayOrder": 0 // displayOrder '0' means no title
        }
      },
      {
        "fieldName": "State", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "DropDown", //DropDown means You can select only one option
          "fieldInputType": "None",
          "validation": {
            "flag": true, //true represents  validate field
            "minimum": 1, // It represents mimimum '1' has to select
            "maximum": 1 // It represents maximum '1'  has to select
          }
        },
        "fieldHint": "please select one state",
        "displayOrder": 1,
        "fieldValues": [
          "Karnataka",
          "Tamilandu",
          "Bihar"
        ]
      },
      {
        "fieldName": "Street Address", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "TextComment",
          "fieldInputType": "textMultiLine", //textMultiLine means User can enter input more than one line
          "validation": {
            "flag": true, //true represents  validate field
            "minimum": 1, // It represents mimimum '1' line should be
            "maximum": 3  // It represents maximum '3' line should be
          }
        },
        "fieldHint": "enter address",
        "displayOrder": 2,
        "fieldValues": []
      }
    ],
    //----------------------end of Section Second----------------

    //------------------------Section third----------------------------
    [
      {
        "SectionHeading": "",// No heading
        "instructions": {
          "title": "",   //No title
          "displayOrder": 0 //No displaying position
        }
      },
      {
        "fieldName": "Age", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "Text",
          "fieldInputType": "number", //where user can enter age as integer like 12,24,35,36 etc
          "validation": {
            "flag": true, //true represents  validate field
            "minimum": 3, // It represents mimimum value should be 3
            "maximum": 10 // It represents maximum value should be 10
          }
        },
        "fieldHint": "enter age in years only",
        "displayOrder": 1,
        "fieldValues": []
      },


      {
        "fieldName": "Mobile Number", //It's fieldName which will display as Label
        "fieldvalue": {
          "fieldType": "Text",
          "fieldInputType": "phone", //fieldInputType 'phone' means it will be integer like e.g. 8050691172
          "validation": {
            "flag": true, //true represents validate field
            "minimum": 10, // It represents mimimum '10' number should  be
            "maximum": 12  // It represents maximum '12' number should  be
          }
        },
        "fieldHint": "enter mobile number",
        "displayOrder": 2,
        "fieldValues": []
      },
      {
        "fieldName": "Price",
        "fieldvalue": {
          "fieldType": "Text",
          "fieldInputType": "numberDecimal", //where user can enter decimal values e.g. 50.65,75,85.82,
          "validation": {
            "flag": true,
            "minimum": 50,
            "maximum": 124
          }
        },
        "fieldHint": "enter Price ",
        "displayOrder": 10,
        "fieldValues": []
      }
    ]
  ]
}

Summary of Config.json

Any partner can change only following things
i)PartnerName
ii)PartnerId
iii)PartnerPublicKey
iv)Sections
1.SectionHeading
2.instructions
a)title b)Displayorder 3. fieldName
a)validation
-flag :true/false
minimum : integer value
maximum :integer value
4. fieldHint
5. fieldValues

Generic Partner App functionaliy( for partner developer)

  1. Register the partner(partner.register(String partnerID, String publicKey, IResponseHandler responseHandler))

  2. Read the configuration file(readConfigFile())

  3. Store the configuration file( storeConfigModel())

  4. To start OE_EVENT (generateOEStartEvent() )

  5. To display form (displayForm()) based on configuration file.

  6. To validate form data( isValidateData())

  7. Send data to Genie services( sendDataToGenieServices())
    i. End the partner session
    partner.terminatePartnerSession(Util.partnerId, endSessionResponseHandler)
    ii. Create Profile
    userProfile.createUserProfile(profile, userProfileResponseHandler)
    where you will get UID on succuess

    iv. Set current User
    userProfile.setCurrentUser(UID, currentuserSetResponseHandler)

    v. Get current User
    userProfile.getCurrentUser(currentGetuserResponseHandler);

    vi. Start session
    partner.startPartnerSession(Util.partnerId,startSessionResponseHandler);

    vii. Send partner data to Genie services
    partner.sendData(UID,partnerData,partnerDataResponseHandler);

    viii. To end OE_EVENT (generateOEEndEvent())

    ix.End the partner session
    partner.terminatePartnerSession(Util.partnerId, endSessionResponseHandler)

  8. To exit the app(exitApp())

How to use Genie service SDK:

https://community.ekstep.in/developer-knowledgebase/70-getting-started-with-genie-service-sdk

PARTNER App sample source code:

https://github.com/ekstep/EkStep-Partner-App

PARTNER App sample Implementation:

https://github.com/ekstep/Common-Design/wiki/PARTNER-SDK-IMPLEMENTATION

Telemtry V2 documentation:

https://community.ekstep.in/specifications-guides/53-telemetry-specification