ecsdk-android-expo
v2.0.1
Published
Expo module for ECSDK-Android (ELERTS See Say Now SDK)
Maintainers
Readme
ecsdk-android-expo
Expo module for ECSDK-Android (ELERTS "See Say Now" SDK) - Complete security and incident reporting solution for React Native apps.
📋 Table of Contents
✨ Features
- ✅ Client Registration - Register users with the ECSDK system
- ✅ User Login/Logout - Manage user sessions with saved tokens
- ✅ Profile Management - Update user information
- ✅ Organization Management - Join and manage organizations
- ✅ Report Submission - Submit incident reports with photos and location
- ✅ Message Center - View alerts and notifications
- ✅ Push Notifications - Firebase Cloud Messaging for real-time alerts
- ✅ Emergency Calling - Call emergency services with dispatch notification
- ✅ Profile Screen - Built-in user profile UI
- ✅ Notification Customization - Customize notification icons and colors
- ✅ TypeScript Support - Full type definitions
- ✅ Config Plugin - Automated native configuration
Platform Support: Android only (API 23+)
📦 Installation
npm install ecsdk-android-expo @react-native-firebase/app @react-native-firebase/messaging
# or
yarn add ecsdk-android-expo @react-native-firebase/app @react-native-firebase/messagingRequired Peer Dependencies:
@react-native-firebase/app- Firebase core (required for Firebase initialization)@react-native-firebase/messaging- Firebase Cloud Messaging (required for push notifications)
Why are Firebase dependencies required?
While this module includes native Firebase messaging support, the React Native Firebase packages are required because:
- They initialize Firebase in the React Native context
- They process the
google-services.jsonconfiguration during build - They enable FCM token generation and management
- They handle foreground notification reception
The module's native code depends on Firebase being properly initialized by these packages.
Note: The ECSDK-Android library is already included as a dependency. You don't need to add it to your build.gradle.
⚡ Setup
The config plugin automatically configures all native Android files including ECSDK initialization. No manual native code editing required!
Step 1: Add Plugin to Config
app.config.js (with environment variables):
export default {
expo: {
name: "My App",
plugins: [
[
"ecsdk-android-expo",
{
ecsdkApiKey: process.env.ECSDK_API_KEY,
googleMapsApiKey: process.env.GOOGLE_MAPS_API_KEY,
googleServicesFile: "./google-services.json",
productName: "PROVIDED BY ELERTS",
appName: "My App Name",
shortDisplayName: "MyApp",
},
],
],
},
};Config Options
| Option | Required | Default | Description |
| -------------------- | -------- | ---------------------- | ----------------------------------------------- |
| ecsdkApiKey | Yes | - | Your ECSDK API key from ELERTS |
| googleMapsApiKey | Yes | - | Google Maps API key (required for map features) |
| googleServicesFile | No | - | Path to google-services.json (for FCM) |
| productName | No | "PROVIDED BY ELERTS" | Product name shown in ECSDK UI |
| appName | No | - | Your app name (optional) |
| shortDisplayName | No | - | Short display name for your app |
Step 2: Configure Firebase
Automatic Setup (Recommended)
Place your google-services.json in your project root and configure the plugin:
{
"plugins": [
[
"ecsdk-android-expo",
{
...
"googleServicesFile": "./google-services.json"
...
}
]
]
}Getting Your FCM Server Key for ELERTS
To enable push notifications, you need to provide your FCM Server Key to ELERTS:
Step 1: Get Your FCM Server Key
- Go to Firebase Console
- Select your project
- Click the gear icon (⚙️) → Project settings
- Go to the Cloud Messaging tab
- Scroll to Cloud Messaging API (Legacy)
- Copy the Server key value
Step 2: Provide to ELERTS
Contact ELERTS support with:
- Your ECSDK API Key
- Your FCM Server Key
- Your app's package name (e.g.,
com.yourcompany.yourapp)
Important Notes:
- Keep your FCM Server Key secure and never commit it to version control
- The FCM Server Key allows ELERTS to send push notifications to your app
- Without providing this key to ELERTS, push notifications will not work
Step 3: Set Up GitHub Authentication
Set environment variables for GitHub authentication.
For local development:
export GPR_USER=your-github-username
export GPR_API_KEY=your-personal-access-tokenFor EAS Build, add to eas.json:
{
"build": {
"production": {
"env": {
"GPR_USER": "your-github-username",
"GPR_API_KEY": "your-token"
}
}
}
}Step 4: Build and Run
npx expo prebuild --clean
npx expo run:androidDone! The config plugin handles everything:
- ✅ AndroidManifest.xml configuration (including FCM service)
- ✅ String resources setup
- ✅ ECSDK initialization in MainApplication
- ✅ Firebase Messaging Service registration
- ✅ Auto-copy google-services.json (if path provided)
Skip to API Reference to start using the SDK.
📱 Quick Start Summary
- Install packages:
npm install ecsdk-android-expo @react-native-firebase/app @react-native-firebase/messaging - Add config plugin to
app.config.jswith your API keys - Place
google-services.jsonin project (plugin auto-copies) - Set GitHub credentials for ECSDK library access
- Run:
npx expo prebuild --clean && npx expo run:android - Register client and join organization
- Provide FCM Server Key to ELERTS support
- Start receiving push notifications!
📖 API Reference
Import
import { ECSDK, ECOrganizationData, ECClientData } from "ecsdk-android-expo";Client Management
registerClient(userData)
Register a new client with the ECSDK system. Must be called before using other features.
Parameters:
{
deviceId?: string; // Unique device ID (auto-generated if not provided)
firstName?: string; // User's first name
lastName?: string; // User's last name
email?: string; // User's email
phone?: string; // User's phone number
}Returns: Promise<ECClientData>
{
token: string; // Save this token to your backend!
}Example:
const clientData = await ECSDK.registerClient({
deviceId: "unique-device-id",
firstName: "John",
lastName: "Doe",
email: "[email protected]",
phone: "+1234567890",
});
// IMPORTANT: Save this token!
console.log("Token:", clientData.token);updateClient(userData)
Update the client's profile information.
Parameters:
{
firstName?: string;
lastName?: string;
email?: string;
phone?: string;
}Returns: Promise<void>
Example:
await ECSDK.updateClient({
firstName: "Jane",
lastName: "Smith",
email: "[email protected]",
phone: "+1987654321",
});User Login/Logout Management
Important for apps with user login systems: If your app has user authentication, you must save the ELERTS client token on your server with each user's data. When a user logs back in, retrieve their token and restore their ELERTS session.
login(clientToken)
Login a user with their saved ELERTS client token. Call this when a user logs into your app to restore their ELERTS session.
Parameters:
clientToken: string- The ELERTS client token retrieved from your server
Returns: void
Example:
// Typical login flow:
async function handleUserLogin(username, password) {
// 1. Authenticate user with your backend
const user = await yourAuthAPI.login(username, password);
// 2. Retrieve the ELERTS token saved for this user
const elertsToken = user.elertsClientToken;
// 3. Login to ELERTS
ECSDK.login(elertsToken);
// User can now submit reports and receive messages
}Important Notes:
- The ELERTS token should be saved to your server when the user first registers with
registerClient() - Upon login, retrieve this token from your server and pass it to
login() - If you want to allow non-logged-in users to send reports, use an ELERTS webform instead
logout()
Logout the current user and clear their ELERTS session. Call this when a user logs out of your app.
Returns: void
Example:
async function handleUserLogout() {
// Clear ELERTS session
ECSDK.logout();
// Then clear your app's session
await yourAuthAPI.logout();
}Note: After logout, the user will not be able to submit reports or receive ELERTS messages until they log back in.
getClientToken()
Get the current ELERTS client token. Returns null if no user is logged in.
Returns: string | null
Example:
const token = ECSDK.getClientToken();
if (token) {
console.log("User is logged in to ELERTS");
// Optionally save token to your server if not already saved
await saveTokenToServer(currentUserId, token);
} else {
console.log("No user logged in to ELERTS");
}Use Cases:
- Check if a user is currently logged in
- Retrieve the token to save to your server
- Verify login/logout operations
Complete Login Flow Example
import { ECSDK } from "ecsdk-android-expo";
// First-time registration
async function registerNewUser(userData) {
// 1. Register with ECSDK
const clientData = await ECSDK.registerClient({
deviceId: `device-${Date.now()}`,
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.email,
phone: userData.phone,
});
// 2. Save the ELERTS token to your server
await yourAPI.saveUserData({
userId: userData.userId,
elertsClientToken: clientData.token, // IMPORTANT!
...userData
});
// User is now registered and logged in
}
// Returning user login
async function loginExistingUser(username, password) {
// 1. Authenticate with your backend
const user = await yourAPI.login(username, password);
// 2. Retrieve the saved ELERTS token
const elertsToken = user.elertsClientToken;
// 3. Login to ELERTS
if (elertsToken) {
ECSDK.login(elertsToken);
console.log("Logged in to ELERTS");
} else {
console.warn("No ELERTS token found for user");
}
}
// User logout
async function logoutUser() {
// 1. Logout from ELERTS
ECSDK.logout();
// 2. Clear your app's session
await yourAPI.logout();
console.log("User logged out");
}Organization Management
getOrganizationList()
Get all available organizations that the client can join.
Returns: Promise<ECOrganizationData[]>
Example:
const organizations = await ECSDK.getOrganizationList();
organizations.forEach((org) => {
console.log(`${org.name} (ID: ${org.id})`);
console.log(` Phone: ${org.phone}`);
});joinOrganizations(organizationIds)
Join one or more organizations. The first organization will be set as active.
Parameters:
organizationIds: string[]- Array of organization IDs
Returns: Promise<{ success: boolean }>
Example:
const orgs = await ECSDK.getOrganizationList();
if (orgs.length > 0) {
await ECSDK.joinOrganizations([orgs[0].id.toString()]);
console.log(`Joined ${orgs[0].name}`);
}setActiveOrganization(organizationId)
Set which organization is currently active.
Parameters:
organizationId: string- The organization ID
Returns: Promise<{ success: boolean }>
Example:
await ECSDK.setActiveOrganization("12345");getActiveOrganization()
Get the currently active organization.
Returns: Promise<ECOrganizationData | null>
Example:
const activeOrg = await ECSDK.getActiveOrganization();
if (activeOrg) {
console.log("Active:", activeOrg.name);
console.log("Phone:", activeOrg.phone);
} else {
console.log("No active organization");
}Push Notifications (FCM)
Permission Handling
Important: On Android 13+ (API 33+), you must request the POST_NOTIFICATIONS permission from the user to receive push notifications.
The config plugin automatically adds this permission to your AndroidManifest.xml, but you need to request it at runtime:
import { Platform, PermissionsAndroid } from "react-native";
async function requestNotificationPermission() {
if (Platform.OS === "android" && Platform.Version >= 33) {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
);
return granted === PermissionsAndroid.RESULTS.GRANTED;
}
return true; // Permission not required on older versions
}
// Request permission before getting token or registering
await requestNotificationPermission();Notes:
- FCM token can be retrieved without permission, but notifications won't be received
- Permission is not required on Android 12 and below
- The example app demonstrates complete permission handling
getFCMToken()
Get the current Firebase Cloud Messaging token.
Returns: Promise<string>
Example:
const fcmToken = await ECSDK.getFCMToken();
console.log("FCM Token:", fcmToken);updateFCMToken(token?)
Manually update the FCM token with the ELERTS server.
Note: This is done automatically by the FirebaseMessagingService, but you can call it manually if needed.
Parameters:
token?: string- FCM token (optional, will get current token if not provided)
Returns: Promise<{ success: boolean }>
Example:
// Automatic - just call without parameters
await ECSDK.updateFCMToken();
// Or with a specific token
const token = await ECSDK.getFCMToken();
await ECSDK.updateFCMToken(token);getStoredFCMToken()
Get the FCM token stored in local preferences.
Returns: string | null
Example:
const storedToken = ECSDK.getStoredFCMToken();
if (storedToken) {
console.log("Stored token:", storedToken);
}Notification Customization
setSmallNotificationIcon(resourceName)
Set the small notification icon (appears in status bar).
Parameters:
resourceName: string- Name of drawable resource (e.g., "notification_icon")
Example:
// Icon must exist in android/app/src/main/res/drawable/
ECSDK.setSmallNotificationIcon("notification_icon");setSmallNotificationIconColor(color)
Set the tint color for the small notification icon.
Parameters:
color: string- Hex color (#RRGGBB or #AARRGGBB)
Example:
ECSDK.setSmallNotificationIconColor("#2196F3");
// With alpha transparency
ECSDK.setSmallNotificationIconColor("#802196F3");setLargeNotificationIcon(base64Image)
Set the large notification icon from a base64-encoded image.
Parameters:
base64Image: string- Base64 image string (without data:image prefix)
Example:
import * as FileSystem from "expo-file-system";
// Convert image to base64
const base64 = await FileSystem.readAsStringAsync(imageUri, {
encoding: FileSystem.EncodingType.Base64,
});
ECSDK.setLargeNotificationIcon(base64);configureNotificationIcons(config)
Configure all notification icon properties at once.
Parameters:
{
smallIconResourceName?: string;
smallIconColor?: string;
largeIconBase64?: string;
}Example:
ECSDK.configureNotificationIcons({
smallIconResourceName: "notification_icon",
smallIconColor: "#2196F3",
largeIconBase64: base64Icon,
});UI Components
showReportActivity()
Display the ECSDK incident report screen.
⚠️ Requires an active organization.
Example:
try {
ECSDK.showReportActivity();
} catch (error) {
console.error("No active organization");
}showMessageList()
Display the message list screen with alerts and notifications.
Example:
ECSDK.showMessageList();showCallPrompt()
Display emergency call dialog. Sends notification to dispatch console.
Example:
ECSDK.showCallPrompt();showProfileScreen()
Display the built-in user profile screen.
Example:
ECSDK.showProfileScreen();TypeScript Types
type ECUserData = {
deviceId?: string;
firstName?: string;
lastName?: string;
email?: string;
phone?: string;
};
type ECClientData = {
token: string;
};
type ECOrganizationData = {
id: number;
name: string;
phone: string;
phoneTitle: string;
};
type FCMTokenResponse = {
success: boolean;
};
type NotificationIconConfig = {
smallIconResourceName?: string;
smallIconColor?: string;
largeIconBase64?: string;
};💡 Complete Example
import React, { useEffect, useState } from "react";
import { View, Button, Alert } from "react-native";
import { ECSDK, ECOrganizationData } from "ecsdk-android-expo";
export default function App() {
const [isRegistered, setIsRegistered] = useState(false);
const [activeOrg, setActiveOrg] = useState<ECOrganizationData | null>(null);
useEffect(() => {
initializeECSDK();
}, []);
async function initializeECSDK() {
try {
// 1. Request notification permission (Android 13+)
if (Platform.OS === "android" && Platform.Version >= 33) {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
);
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
console.warn("Notification permission denied");
}
}
// 2. Register client
const clientData = await ECSDK.registerClient({
deviceId: `device-${Date.now()}`,
});
// Save the token to your backend!
console.log("Client Token:", clientData.token);
setIsRegistered(true);
// 3. Update profile
await ECSDK.updateClient({
firstName: "John",
lastName: "Doe",
email: "[email protected]",
phone: "+1234567890",
});
// 4. Setup push notifications
const fcmToken = await ECSDK.getFCMToken();
console.log("FCM Token:", fcmToken);
await ECSDK.updateFCMToken();
// 5. Customize notifications (optional)
ECSDK.configureNotificationIcons({
smallIconColor: "#2196F3",
});
// 6. Get and join organization
const organizations = await ECSDK.getOrganizationList();
if (organizations.length > 0) {
// Join first organization
await ECSDK.joinOrganizations([organizations[0].id.toString()]);
// Get active organization
const org = await ECSDK.getActiveOrganization();
setActiveOrg(org);
Alert.alert("Success", `Ready to use ECSDK with ${org?.name}`);
} else {
Alert.alert("Error", "No organizations available. Check your API key.");
}
} catch (error: any) {
Alert.alert("Initialization Error", error.message);
console.error("Init error:", error);
}
}
return (
<View style={{ flex: 1, justifyContent: "center", padding: 20 }}>
<Button
title="Submit Report"
onPress={() => ECSDK.showReportActivity()}
disabled={!activeOrg}
/>
<Button
title="View Messages"
onPress={() => ECSDK.showMessageList()}
disabled={!isRegistered}
/>
<Button
title="Call Police"
onPress={() => ECSDK.showCallPrompt()}
disabled={!activeOrg}
/>
<Button
title="View Profile"
onPress={() => ECSDK.showProfileScreen()}
disabled={!isRegistered}
/>
</View>
);
}🐛 Troubleshooting
"Peer dependency not installed" warnings
Solution:
Make sure you've installed the required Firebase peer dependencies:
npm install @react-native-firebase/app @react-native-firebase/messagingThese are required for the module to function properly. See the Installation section for details.
Push notifications not working
Solution:
Verify Firebase setup:
google-services.jsonis inandroid/app/- Firebase dependencies are installed (
@react-native-firebase/appand@react-native-firebase/messaging) - App package name matches Firebase project
Check FCM Server Key:
- You provided the FCM Server Key to ELERTS support
- The key is from the correct Firebase project
- Use the "Server key" from Cloud Messaging API (Legacy)
Test FCM directly:
- Use Firebase Console → Cloud Messaging → Send test message
- If this works, the issue is with ELERTS configuration
- If this fails, check your Firebase setup
Check permissions (Android 13+):
<!-- AndroidManifest.xml --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>Verify token registration:
const token = await ECSDK.getFCMToken(); console.log("Token:", token); // Should not be null const stored = ECSDK.getStoredFCMToken(); console.log("Stored:", stored); // Should match
Build fails with "Could not resolve com.elerts.libraries:elertsui"
Solution: Check GitHub authentication. See the setup documentation for details on configuring GitHub credentials.
"Unable to resolve host" or Network errors
Solution:
Clean and rebuild:
cd android ./gradlew clean cd .. npx expo run:androidRestart emulator: Cold boot your Android emulator
Test on physical device: Network issues are often emulator-specific
"No active organization" error
Solution: Join an organization first
const orgs = await ECSDK.getOrganizationList();
await ECSDK.joinOrganizations([orgs[0].id.toString()]);App crashes on startup
Solution: Verify ECSDK is initialized in your MainApplication class
class MainApplication : Application() {
private lateinit var ecuisdk: ECUISDK
override fun onCreate() {
super.onCreate()
ecuisdk = ECUISDK(this) // Make sure this is here
}
}Config plugin not applying changes
Solution:
npx expo prebuild --clean
npx expo run:androidTypeScript errors
Solution: Make sure you're importing types correctly
import { ECSDK, ECOrganizationData, ECClientData } from "ecsdk-android-expo";📄 License
MIT
🤝 Support
- SDK Issues: Contact ELERTS support
- Module Issues: GitHub Issues
- API Key: Contact ELERTS to get your API key
🙏 Credits
- ECSDK-Android SDK by ELERTS
- Built with Expo Modules
- Created for the React Native community
Version: 1.2.0
Made for the React Native community 🚀
