Provider
Overview
For native applications, a convenience AAR library is available to access the provider information directly without the complexity of implementing your own content provider code. This library contains a static class LauncherProviderHelper with functions to access configuration or session data.
Using this provider, applications will have the ability to access the current session from the Launcher to get information about the current logged-in user and the store information, configuration, etc.
LauncherProvider Method
A wrapper class for the above content provider access is provided using an aar library, to simplify access to the session information. Typically, you should try to retrieve the session information in the on-resume of your application’s activity, so you can take action or re-authenticate if the session is invalid.
Example Java Code and Configuration
Gradle
// in your project's build.gradle file:
dependencies {
...
implementation(name: 'launcherProvider-x.x.x', ext: 'aar', version: 'x.x.x')
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.jakewharton.timber:timber:4.7.1'
...
}
Code
In your java class:
import com.bluefletch.launcherprovider.LauncherProviderHelper;
import com.bluefletch.launcherprovider.Session;
...
public class SampleActivity extends Activity {
// in this example, getProviderInfo is the local method used to retrieve the
// current session information
protected void getProviderInfo() {
Session session = LauncherProviderHelper.getCurrentSession(this);
// all fields should be present. If group is “*” then there is no
// logged in session so the app should handle accordingly.
//
String userId = session.get(Session.USER_ID);
String userName = session.get(Session.USER_NAME);
String groups = session.get(Session.GROUPS);
String accessToken = session.getExtendedAttribute("accessToken");
// Get the site information from the config. This information
// is stored in the extendedAttributes.
//
Config config = LauncherProviderHelper.getCurrentConfig(this);
String storeNumber = config.getExtAttr("siteId");
String storeName = config.getExtAttr("siteName");
String deviceId = config.getExtAttr("deviceId");
}
Configuration Requirements
Beginning Launcher 3.15.x, customers are strongly encouraged to whitelist applications in the authorizedClients
section of the launcher configuration. If this section is present in the launcher configurations, only applications defined here will be granted access to provider data.
{
...
"authorizedClients" : [
"com.mydomain.fulfillment",
"com.mydomain.mobilepos"
],
}
Example Cordova Plugin
Install the Cordova Plugin for accessing Content Providers:
cordova plugin add com.phearme.cordovaplugin.contentproviderplugin
Using the content provider of com.bluefletch.launcherprovider, use this Javascript to get session information:
if (window.plugins && window.plugins.contentproviderplugin) {
window.plugins.contentproviderplugin.query({
contentUri: "content://com.bluefletch.launcherprovider/session",
projection: ["data"],
selection: null,
selectionArgs: null,
sortOrder: null
}, function (data) {
console.log('session data is:', data);
var sessionData = {};
if (data.length > 0) {
sessionData = JSON.parse(data[0]["DATA"]);
}
// get the user id
var userid = sessionData.userId;
var username = sessionData.userName;
var groups = sessionData.groups;
var extendedAttrs = JSON.parse(sessionData.extendedAttributes);
var extAttrAccessToken = extendedAttrs.accessToken;
}, function (err) {
// use default
console.log('session error:', err);
});
}
Example React Native
Reference
https://facebook.github.io/react-native/docs/native-modules-android
High Level
- Android: Update the project with the following:
- Include the AAR for Launcher Provider
- Update the Gradle file to include Launcher Provider AAR
- Include React Bridge Code
- Update Main Application to include React Bridge Code
- React Code
- Include the Launcher Exported Javascript
Android in Detail
AAR: Within the project tree, under “app” folder, create a folder named “libs”. Place the launcherProvider-x.x.x.aar within the libs directory.
Gradle: Include a reference to the library along with gson and timber within the application build.gradle by adding the following to the dependency list:
implementation(name: 'launcherProvider-x.x.x', ext: 'aar', version: 'x.x.x')
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.jakewharton.timber:timber:4.7.1'
Ensure your Project build.gradle allows pulling from the libs directory by adding the Flat Directory to the repositories list
allprojects {
repositories {
mavenLocal()
google()
jcenter()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url"$rootDir/../node_modules/react-native/android"
}
flatDir {
dirs 'libs' //this way we can find the .aar files in libs folder
}
}
}
Bridge code:
Within MainApplication, create an instance of 'LauncherSessionPackage'
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new ModuleRegistryAdapter(mModuleRegistryProvider));
packages.add(new LauncherSessionPackage());
return packages;
}
LauncherSessionPackage
LauncherSessionPackage defines the package interface.
public class LauncherSessionPackage implements ReactPackage {
@Nonnull
@Override
public List<ViewManager> createViewManagers(@Nonnull ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules( ReactApplicationContext reactContext ) {
List<NativeModule> modules = new ArrayList<>();
modules.add( new LauncherSessionProvider(reactContext) );
return modules;
}
}
LauncherSessionProvider
LauncherSessionProvider is the code that talks to Launcher to get the Session contents. The main method within the LauncherSessionProvider is ‘getSession’.
import com.bluefletch.launcherprovider.LauncherProviderHelper;
import com.bluefletch.launcherprovider.Session;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import javax.annotation.Nonnull;
public class LauncherSessionProvider extends ReactContextBaseJavaModule {
private class ExposedSession extends Object {
};
public LauncherSessionProvider(@Nonnull ReactApplicationContext reactContext) {
super(reactContext);
}
@Nonnull
@Override
public String getName() {
return "LauncherSessionProvider";
}
@ReactMethod
public void getSession(Callback sessionCallback) {
Log.d("LauncherProvider", "getSession");
try {
if ( sessionCallback != null ) {
WritableMap map = Arguments.createMap();
Session session = internalGetSession();
if ( session != null ) {
map.putString(Session.LOCATION, session.get(Session.LOCATION));
map.putString(Session.ROLE, session.get(Session.ROLE));
map.putString(Session.USER_ID, session.get(Session.USER_ID));
map.putString(Session.USERNAME, session.get(Session.USERNAME));
map.putString(Session.EXTENSION, session.get(Session.EXTENSION));
map.putString("accessToken", LauncherProviderHelper.getExtendedAttribute( getReactApplicationContext(), "accessToken") );
map.putString("idToken", LauncherProviderHelper.getExtendedAttribute( getReactApplicationContext(), "idToken") );
map.putString("refreshToken", LauncherProviderHelper.getExtendedAttribute( getReactApplicationContext(), "refreshToken") );
} else {
Log.e("LauncherProvider", "getSession, Session not available" );
}
sessionCallback.invoke(map);
} else {
Log.e("LauncherProvider", "getSession, Callback not provided" );
}
} catch ( Exception e ) {
Log.e("LauncherProvider", "getSession error ", e);
}
}
private Session internalGetExtendAttributes() {
return LauncherProviderHelper.getCurrentSession( getReactApplicationContext() );
}
private Session internalGetSession() {
return LauncherProviderHelper.getCurrentSession( getReactApplicationContext() );
}
}
React Code in Detail
Here are code peices to get the Session information.
LauncherSessionProvider.js
Add the Launcher Provider script file to the React project. The file contents are just to import the bridge logic.
/**
* This exposes the Launcher Session Provider
*
* Refer to https://facebook.github.io/react-native/docs/native-modules-android
*/
import {NativeModules} from 'react-native';
module.exports = NativeModules.LauncherSessionProvider;
App.js
Example code to read the session information.
import LauncherSessionProvider from './LauncherSessionProvider';
populatSession = () => {
LauncherSessionProvider.getSession((session)=>{
console.log(`Session userName:${session.userName}`);
console.log(`Session userId:${session.userId}`);
console.log(`Session role:${session.role}`);
console.log(`Session location:${session.location}`);
console.log(`Session extension:${session.extension}`);
this.setState({
session:session
})
});
}
Full Example App.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View} from 'react-native';
import LauncherSessionProvider from './LauncherSessionProvider';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu -- what is going on?',
});
type Props = {};
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
loaded: true,
error: null,
session: null
};
console.log("APP constructor");
this.populatSession();
}
populatSession = () => {
LauncherSessionProvider.getSession((session)=>{
console.log(`Session userName:${session.userName}`);
console.log(`Session userId:${session.userId}`);
console.log(`Session role:${session.role}`);
console.log(`Session location:${session.location}`);
console.log(`Session extension:${session.extension}`);
this.setState({
session:session
})
});
}
render() {
console.log('start of render');
let userName='not set';
if ( this.state.session && this.state.session.userName ) {
userName = this.state.session.userName;
console.log(`RENDER Session userName:${userName}`);
}
console.log('done with session');
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
<Text style={styles.instructions}>UserName :{userName}</Text>
<Text style={styles.instructions}>do you see the session stuff</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});