Octopulse Flutter Plugin

Flutter plugin for OctoCX/Octopulse SDK - Android first implementation.

This plugin provides a bridge to the native Octopulse SDK, mirroring the React Native plugin API with full feature parity.

Requirements

Requirement Version
minSdkVersion 28 (Android 9+)
targetSdkVersion 34
compileSdkVersion 35
Kotlin 2.0.21
Flutter 3.3.0+
Dart 3.0.0+

Installation

flutter pub add octopulse_flutter

Or add to your pubspec.yaml:

dependencies:
  octopulse_flutter: ^2.2.4

From GitHub

dependencies:
  octopulse_flutter:
    git:
      url: https://github.com/Octolytics-SDK/octopulse_flutter.git
      ref: v2.2.4

Configuration File

Important: You must add the octopulse-config.json file provided by OctoCX to your project.

Place it in one of these locations:

your_app/
├── octopulse-config.json           ← Option 1: Project root
└── android/
    └── octopulse-config.json       ← Option 2: Android folder

This file contains your client credentials and is required for the SDK to function. Contact OctoCX to obtain your configuration file.

Android Setup

1. Update android/app/build.gradle

Ensure minSdk is 28 or higher:

android {
    defaultConfig {
        minSdk 28
        targetSdk 34
    }
}

2. Add Permissions to AndroidManifest.xml

The SDK works with basic permissions, but for full functionality (location-based features, network diagnostics), add these permissions to your android/app/src/main/AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
    <!-- Required for network diagnostics -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <!-- Required for location-based features -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    
    <!-- Required for phone state features -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
    <!-- Optional: Background location (if needed) -->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    
    <application>
        <!-- Your app configuration -->
    </application>
</manifest>

3. Carrier Privileges (Important)

Some SDK features require Carrier Privileges to function correctly:

  • registerDevice() - May require carrier privileges for full functionality
  • Network telemetry features
  • SIM-related operations

To enable Carrier Privileges:

  1. Generate your app's signing certificate SHA-1 and SHA-256 fingerprints
  2. Share these fingerprints with your carrier/OctoCX contact through a secure channel
  3. The carrier will provision your app's signature on their SIM cards
  4. Once provisioned, the SDK will automatically detect carrier privileges
# Get SHA-1 and SHA-256 fingerprints
keytool -list -v -keystore your-keystore.jks -alias your-alias

Usage

Import

import 'package:octopulse_flutter/octopulse_flutter.dart';

Basic Flow

// 1. Initialize the SDK
await OctopulseFlutter.initialize();

// 2. Check and request permissions
bool hasPerms = await OctopulseFlutter.hasMinimumPermissionsGranted();
if (!hasPerms) {
  await OctopulseFlutter.requestMinimumPermissions();
}

// 3. Register device (optional MSISDN)
await OctopulseFlutter.registerDevice('+1234567890');

// 4. Start monitoring
await OctopulseFlutter.start();

// 5. Check status
bool isStarted = await OctopulseFlutter.isdSdkStarted();
bool isRegistered = await OctopulseFlutter.isDeviceRegistered();

API Reference

Method Returns Description
initialize() Future<void> Initialize the SDK. Must be called first.
start() Future<void> Start SDK monitoring.
stop({bool withoutSync}) Future<void> Stop monitoring. Set withoutSync: true to skip data sync.
refresh() Future<void> Refresh SDK state.
updateConfigs() Future<void> Update configurations from server.
clearAllAppData() Future<void> Clear all SDK data.
isDeviceRegistered() Future<bool> Check if device is registered.
isdSdkStarted() Future<bool> Check if SDK is running.
isMonitoringSettingEnabled() Future<bool> Check if monitoring is enabled.
changeMonitoringSettingStatus(bool) Future<void> Enable/disable monitoring.
hasMinimumPermissionsGranted() Future<bool> Check if minimum permissions are granted.
registerDevice(String? msisdn) Future<String> Register device with optional phone number.
launchHelpActivity() Future<void> Open help/support screen.
launchAddMsisdnActivity(int) Future<void> Open MSISDN input screen.
requestMinimumPermissions() Future<String> Request required permissions from user.

Error Handling

All methods can throw PlatformException with these error codes:

Error Code Description
NO_ACTIVITY Method requires an Activity but none is available
NO_APP_CONTEXT Application context not available
NO_CONTEXT Context not available
INITIALIZE_ERROR SDK initialization failed
START_ERROR Failed to start SDK
STOP_ERROR Failed to stop SDK
REGISTER_DEVICE_ERROR Device registration failed
PERMISSION_DENIED User denied permissions
PERMISSION_IN_PROGRESS Permission request already in progress
CARRIER_PRIVILEGES_REQUIRED Operation requires carrier privileges
try {
  await OctopulseFlutter.registerDevice(msisdn);
} on PlatformException catch (e) {
  if (e.code == 'NO_ACTIVITY') {
    print('No activity available');
  } else if (e.code == 'CARRIER_PRIVILEGES_REQUIRED') {
    print('Carrier privileges needed');
  }
}

Troubleshooting

"NO_ACTIVITY" Error

This occurs when calling methods that require an Activity context (like launchHelpActivity, registerDevice, requestMinimumPermissions) but no Activity is attached.

Solution: Ensure you call these methods when the app is in the foreground and the Flutter Activity is active.

OEM Restrictions

Some Android OEMs (Xiaomi, Huawei, Oppo, Vivo, Samsung) have aggressive battery optimization that can kill background services.

Solutions:

  1. Guide users to disable battery optimization for your app
  2. Add your app to the "protected apps" list
  3. Request REQUEST_IGNORE_BATTERY_OPTIMIZATIONS permission

Permissions Not Granted

The SDK requires several permissions. If hasMinimumPermissionsGranted() returns false:

  1. Call requestMinimumPermissions() to show the permissions flow
  2. The SDK will request: Location, Phone State, and other required permissions
  3. Some permissions may require manual user action in Settings

SDK Not Starting

If start() fails or isdSdkStarted() returns false:

  1. Ensure initialize() was called first
  2. Check that minimum permissions are granted
  3. Verify device is registered (if required by your configuration)
  4. Check logcat for SDK-specific error messages

Validation Checklist

Use the example app to validate the plugin:

  1. Install example app on Android device (API 28+)
  2. Tap "Initialize" - should succeed
  3. Tap "Request Perms" - permissions dialog should appear
  4. Grant all requested permissions
  5. Verify "Min Perms" status chip turns green
  6. Enter MSISDN (optional) and tap "Register"
  7. Verify "Registered" status chip turns green
  8. Tap "Start" - should succeed
  9. Verify "Started" status chip turns green
  10. Tap "Launch Help" - help activity should open
  11. Tap "Stop" - should succeed
  12. Run "Smoke Test" - all steps should complete without crashes

Running Integration Tests

cd example
flutter test integration_test/plugin_integration_test.dart

Note: Integration tests have limitations:

  • Permissions require user interaction or mocks
  • Carrier privileges cannot be tested without provisioned SIM
  • Some tests may fail on emulators

Differences from React Native Plugin

This Flutter plugin maintains API parity with the React Native plugin. Key differences:

Aspect React Native Flutter
Bridge NativeModules + Promise MethodChannel + Future
Activity handling ReactApplicationContext ActivityAware interface
Package registration ReactPackage Automatic via pubspec.yaml
Coroutines Same (Kotlin) Same (Kotlin)

License

MIT License - see LICENSE file.

Libraries

octopulse_flutter