securiti_consent_sdk 1.130.0 copy "securiti_consent_sdk: ^1.130.0" to clipboard
securiti_consent_sdk: ^1.130.0 copied to clipboard

A Flutter plugin for managing user consent preferences and compliance with privacy regulations. Integrates with Securiti's Consent Management Platform.

example/lib/main.dart

import 'package:consent_sdk_plugin/cmp_sdk_options.dart';
import 'package:consent_sdk_plugin/models/cmp_sdk_logger_level.dart';
import 'package:consent_sdk_plugin/models/consent_status.dart';
import 'package:consent_sdk_plugin/models/post_consents_request.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:developer' as developer;
import 'dart:io' show Platform;

import 'package:flutter/services.dart';
import 'package:consent_sdk_plugin/consent_sdk_plugin.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';
  String _latestResult = 'No method called yet';
  static const EventChannel _eventChannel = EventChannel('ai.securiti.consent_sdk_plugin/isSDKReady');
  final _consentSdkPlugin = ConsentSdkPlugin();
  bool _isSDKReady = false;
  final ScrollController _scrollController = ScrollController();

  @override
  void initState() {
    super.initState();
    initPlatformState();

    String appURL = 'your iOS App URL';
    String cdnURL = 'Your iOS CDN URL';
    String tenantID = 'Your iOS Tenant ID';
    String appID = 'Your iOS App ID';
    String locationCode = 'iOS Location Code';

    if (Platform.isAndroid) {
      appURL = 'your Android App URL';
      cdnURL = 'Your Android CDN URL';
      appID = 'Your Android App ID';
      locationCode = 'Android Location Code';
    }

    CmpSDKOptions options = CmpSDKOptions(
      appURL: appURL,
      cdnURL: cdnURL,
      tenantID: tenantID,
      appID: appID,
      testingMode: true,
      loggerLevel: CmpSDKLoggerLevel.debug,
      consentsCheckInterval: 60,
      subjectId: 'flutterSubject',
      languageCode: 'en',
      locationCode: locationCode,
    );

    _consentSdkPlugin.setupSDK(options.toMap());
    _eventChannel.receiveBroadcastStream().listen((event) {
      setState(() {
        _isSDKReady = event as bool;
        if (_isSDKReady) {
            _consentSdkPlugin.presentConsentBanner();
        }
      });
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      platformVersion =
          await _consentSdkPlugin.getPlatformVersion() ?? 'Unknown platform version';
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });
  }

  // Convert any Dart object to a JSON-formatted string efficiently
  String _formatJsonForDisplay(dynamic obj, {int depth = 0, int maxDepth = 3}) {
    // Limit recursion depth for performance
    if (depth > maxDepth) {
      return obj.toString();
    }
    
    String indent = '  ' * depth;
    String childIndent = '  ' * (depth + 1);
    
    if (obj == null) {
      return 'null';
    } else if (obj is Map) {
      if (obj.isEmpty) return '{}';
      
      List<String> pairs = [];
      obj.forEach((key, value) {
        String formattedValue = _formatJsonForDisplay(value, depth: depth + 1, maxDepth: maxDepth);
        pairs.add('$childIndent"$key": $formattedValue');
      });
      
      return '{\n${pairs.join(',\n')}\n$indent}';
    } else if (obj is List) {
      if (obj.isEmpty) return '[]';
      
      List<String> items = [];
      for (var item in obj) {
        items.add('$childIndent${_formatJsonForDisplay(item, depth: depth + 1, maxDepth: maxDepth)}');
      }
      
      return '[\n${items.join(',\n')}\n$indent]';
    } else if (obj is String) {
      // Escape quotes and use proper JSON string formatting
      return '"${obj.replaceAll('"', '\\"')}"';
    } else if (obj is num || obj is bool) {
      // Numbers and booleans can be represented directly
      return obj.toString();
    } else {
      // Try to use toJson if available, or default to toString()
      try {
        if (obj is dynamic && obj.toJson != null) {
          return _formatJsonForDisplay(obj.toJson(), depth: depth, maxDepth: maxDepth);
        }
      } catch (_) {}
      
      // Last resort
      return '"${obj.toString().replaceAll('"', '\\"')}"';
    }
  }
  
  void _updateResult(String methodName, dynamic result) {
    // If it's a list, split it into smaller chunks for displaying
    if (result is List && result.length > 0) {
      // Special handling for complex collections
      List<Map<String, dynamic>> formattedItems = [];
      
      for (var i = 0; i < result.length; i++) {
        var item = result[i];
        
        // Create a simplified format with special handling for models
        if (item is dynamic && item.toJson != null) {
          try {
            formattedItems.add(item.toJson());
            continue;
          } catch (_) {}
        }
        
        if (item is Map) {
          formattedItems.add(Map<String, dynamic>.from(item));
        } else {
          // Wrap non-map items in a simple container
          formattedItems.add({'value': item.toString()});
        }
      }
      
      // Apply JSON formatting for the entire list
      final jsonOutput = _formatJsonForDisplay(formattedItems);
      
      setState(() {
        _latestResult = "$methodName result: (${result.length} items)\n$jsonOutput";
      });
    } 
    // If result has toJson method, use that
    else if (result != null && result is dynamic) {
      try {
        if (result.toJson != null) {
          final jsonOutput = _formatJsonForDisplay(result.toJson());
          setState(() {
            _latestResult = "$methodName result:\n$jsonOutput";
          });
          return;
        }
      } catch (_) {}
      
      // Fall back to generic JSON formatter
      final jsonOutput = _formatJsonForDisplay(result);
      setState(() {
        _latestResult = "$methodName result:\n$jsonOutput";
      });
    }
    else {
      // For null or simple types
      setState(() {
        _latestResult = "$methodName result:\n${result ?? 'null'}";
      });
    }
    
    // No need to log the entire output which can be very large
    developer.log("$methodName executed successfully");
  }

  Future<void> _getBannerConfig() async {
    try {
      final config = await _consentSdkPlugin.getBannerConfig();
      developer.log("getBannerConfig result type: ${config.runtimeType}");
      
      if (config == null) {
        _updateResult('getBannerConfig', 'null - No banner config available');
        return;
      }
      
      // Use the complete BannerConfig model with toJson
      _updateResult('getBannerConfig', config);
    } catch (e) {
      _updateResult('getBannerConfig', 'Error: $e');
    }
  }

  Future<void> _getConsentByPurposeId() async {
    try {
      // First, get the list of purposes to find a valid purposeId
      final purposes = await _consentSdkPlugin.getPurposes();
      if (purposes.isEmpty) {
        _updateResult('getConsentByPurposeId', 'No purposes available to check consent');
        return;
      }
      
      // Get the first purpose ID
      final purposeId = purposes.first.purposeId;
      final purposeName = purposes.first.purposeName?['en'] ?? 'Unknown';
      developer.log("Getting consent for purpose ID: $purposeId");
      
      final status = await _consentSdkPlugin.getConsent(purposeId ?? 1);
      developer.log("getConsentByPurposeId result type: ${status.runtimeType}");
      
      // Format result with full purpose details
      final result = {
        'purpose_id': purposeId,
        'purpose_name': purposeName,
        'consent_status': status.value,
        'enum_value': status.toString(),
        'purpose_details': purposes.first.toJson(),
      };
      
      _updateResult('getConsentByPurposeId', result);
    } catch (e) {
      _updateResult('getConsentByPurposeId', 'Error: $e');
    }
  }
  
  Future<void> _getConsentByPermissionId() async {
    try {
      // First, get the list of permissions to find a valid permissionId
      final permissions = await _consentSdkPlugin.getPermissions();
      if (permissions.isEmpty) {
        _updateResult('getConsentByPermissionId', 'No permissions available to check consent');
        return;
      }
      
      // Get the first permission ID or use a standard Android permission
      final permission = permissions.first;
      final permissionId = permission.permissionId ?? "android.permission.CAMERA";
      final permissionName = permission.name ?? 'Unknown';
      developer.log("Getting consent for permission ID: $permissionId");
      
      final status = await _consentSdkPlugin.getConsent(permissionId);
      developer.log("getConsentByPermissionId result type: ${status.runtimeType}");
      
      // Format result with full permission details
      final result = {
        'permission_id': permissionId,
        'permission_name': permissionName,
        'consent_status': status.value,
        'enum_value': status.toString(),
        'permission_details': permission.toJson(),
      };
      
      _updateResult('getConsentByPermissionId', result);
    } catch (e) {
      _updateResult('getConsentByPermissionId', 'Error: $e');
    }
  }

  Future<void> _getPermissions() async {
    try {
      final permissions = await _consentSdkPlugin.getPermissions();
      
      // Pass the full permissions list directly
      _updateResult('getPermissions', permissions);
    } catch (e) {
      _updateResult('getPermissions', 'Error: $e');
    }
  }

  Future<void> _getPurposes() async {
    try {
      final purposes = await _consentSdkPlugin.getPurposes();
      developer.log("getPurposes result type: ${purposes.runtimeType}, isEmpty: ${purposes.isEmpty}");
      if (!purposes.isEmpty) {
        developer.log("First purpose type: ${purposes.first.runtimeType}");
      }
      
      // Pass the full purposes list directly
      _updateResult('getPurposes', purposes);
    } catch (e) {
      _updateResult('getPurposes', 'Error: $e');
    }
  }

  Future<void> _getSdksInPurpose() async {
    try {
      // First, get purposes to find a valid ID
      final purposes = await _consentSdkPlugin.getPurposes();
      if (purposes.isEmpty) {
        _updateResult('getSdksInPurpose', 'No purposes available to check SDKs');
        return;
      }
      
      // Get the first purpose ID or use default 1
      final purposeId = purposes.first.purposeId ?? 1;
      developer.log("Getting SDKs for purpose ID: $purposeId");
      
      final sdks = await _consentSdkPlugin.getSdksInPurpose(purposeId);
      
      // Format the result with full SDK details
      final formattedResult = {
        'purpose_id': purposeId,
        'purpose_name': purposes.first.purposeName?['en'] ?? 'Unknown',
        'sdks_count': sdks.length,
        'sdks': sdks,
      };
      
      _updateResult('getSdksInPurpose', formattedResult);
    } catch (e) {
      _updateResult('getSdksInPurpose', 'Error: $e');
    }
  }

  Future<void> _getSettingsPrompt() async {
    try {
      final settingsPrompt = await _consentSdkPlugin.getSettingsPrompt();
      
      if (settingsPrompt == null) {
        _updateResult('getSettingsPrompt', 'null - No settings prompt available');
        return;
      }
      
      // Settings prompt will be automatically formatted through toJson
      _updateResult('getSettingsPrompt', settingsPrompt);
    } catch (e) {
      _updateResult('getSettingsPrompt', 'Error: $e');
    }
  }

  Future<void> _setConsentForPurpose() async {
    try {
      // First, get the list of purposes to find a valid purposeId
      final purposes = await _consentSdkPlugin.getPurposes();
      if (purposes.isEmpty) {
        _updateResult('setConsentForPurpose', 'No purposes available to set consent');
        return;
      }
      
      // Get the first purpose ID
      final purposeId = purposes.first.purposeId;
      developer.log("Setting consent for purpose ID: $purposeId");
      
      await _consentSdkPlugin.setConsent(purposeId ?? 1, ConsentStatus.granted);
      _updateResult('setConsentForPurpose', 'Consent set to GRANTED for purpose ID: $purposeId');
    } catch (e) {
      _updateResult('setConsentForPurpose', 'Error: $e');
    }
  }
  
  Future<void> _setConsentForPermission() async {
    try {
      // First, get the list of permissions to find a valid permissionId
      final permissions = await _consentSdkPlugin.getPermissions();
      if (permissions.isEmpty) {
        _updateResult('setConsentForPermission', 'No permissions available to set consent');
        return;
      }
      
      // Get the first permission ID or use a standard Android permission
      final permissionId = permissions.first.permissionId ?? "android.permission.CAMERA";
      developer.log("Setting consent for permission ID: $permissionId");
      
      await _consentSdkPlugin.setConsent(permissionId, ConsentStatus.granted);
      _updateResult('setConsentForPermission', 'Consent set to GRANTED for permission ID: $permissionId');
    } catch (e) {
      _updateResult('setConsentForPermission', 'Error: $e');
    }
  }

  Future<void> _resetConsents() async {
    try {
      await _consentSdkPlugin.resetConsents();
      _updateResult('resetConsents', 'Consents reset successfully');
    } catch (e) {
      _updateResult('resetConsents', 'Error: $e');
    }
  }
  
  Future<void> _getAllConsents() async {
    try {
      // Get all purposes and their consent statuses
      final purposes = await _consentSdkPlugin.getPurposes();
      
      // Collect full purpose data with consent status
      List<Map<String, dynamic>> purposeData = [];
      // Limit to first 5 for performance
      int count = purposes.length > 5 ? 5 : purposes.length;
      
      for (var i = 0; i < count; i++) {
        var purpose = purposes[i];
        if (purpose.purposeId != null) {
          final consent = await _consentSdkPlugin.getConsent(purpose.purposeId!);
          final purposeName = purpose.purposeName?['en'] ?? 'Unknown';
          
          purposeData.add({
            'purpose_id': purpose.purposeId,
            'name': purposeName,
            'consent_status': consent.value,
            'purpose_data': purpose.toJson() // Include full purpose data
          });
        }
      }
      
      // Get all permissions and their consent statuses
      final permissions = await _consentSdkPlugin.getPermissions();
      List<Map<String, dynamic>> permissionData = [];
      
      // Limit to first 5 for performance
      count = permissions.length > 5 ? 5 : permissions.length;
      
      for (var i = 0; i < count; i++) {
        var permission = permissions[i];
        if (permission.permissionId != null) {
          final consent = await _consentSdkPlugin.getConsent(permission.permissionId!);
          final permissionName = permission.name ?? 'Unknown';
          
          permissionData.add({
            'permission_id': permission.permissionId,
            'name': permissionName, 
            'consent_status': consent.value,
            'permission_data': permission.toJson() // Include full permission data
          });
        }
      }
      
      // Format result as JSON with all available details
      final result = {
        'total_purposes': purposes.length,
        'total_permissions': permissions.length,
        'purposes': purposeData,
        'permissions': permissionData,
      };
      
      _updateResult('getAllConsents', result);
    } catch (e) {
      _updateResult('getAllConsents', 'Error: $e');
    }
  }


  Widget _buildMethodButton(String label, VoidCallback onPressed) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5),
      child: ElevatedButton(
        onPressed: _isSDKReady ? onPressed : null,
        child: Text(label),
      ),
    );
  }

  Widget _buildSDKMethodsList() {
    return Expanded(
      child: SingleChildScrollView(
        controller: _scrollController,
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // UI Methods
              const Padding(
                padding: EdgeInsets.only(top: 8, bottom: 8),
                child: Text('UI Methods', style: TextStyle(fontWeight: FontWeight.bold)),
              ),
              _buildMethodButton('Present Consent Banner', () {
                _consentSdkPlugin.presentConsentBanner();
                _updateResult('presentConsentBanner', 'Banner presented');
              }),
              _buildMethodButton('Open Preference Center', () {
                _consentSdkPlugin.presentPreferenceCenter();
                _updateResult('presentPreferenceCenter', 'Preference center opened');
              }),
              
              // Get Methods
              const Padding(
                padding: EdgeInsets.only(top: 16, bottom: 8),
                child: Text('Get Data Methods', style: TextStyle(fontWeight: FontWeight.bold)),
              ),
              _buildMethodButton('Get Banner Config', _getBannerConfig),
              _buildMethodButton('Get Permissions', _getPermissions),
              _buildMethodButton('Get Purposes', _getPurposes),
              _buildMethodButton('Get SDKs in Purpose', _getSdksInPurpose),
              _buildMethodButton('Get Settings Prompt', _getSettingsPrompt),
              
              // Consent Management Methods
              const Padding(
                padding: EdgeInsets.only(top: 16, bottom: 8),
                child: Text('Consent Management', style: TextStyle(fontWeight: FontWeight.bold)),
              ),
              _buildMethodButton('Get Consent by Purpose ID', _getConsentByPurposeId),
              _buildMethodButton('Get Consent by Permission ID', _getConsentByPermissionId),
              _buildMethodButton('Get All Consents', _getAllConsents),
              _buildMethodButton('Set Consent for Purpose', _setConsentForPurpose),
              _buildMethodButton('Set Consent for Permission', _setConsentForPermission),
              _buildMethodButton('Reset All Consents', _resetConsents),
            ],
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Consent SDK Example'),
        ),
        body: Column(
          children: [
            Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'Securiti\'s SDK is ${_isSDKReady ? "ready" : "not ready"}',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                      color: _isSDKReady ? Colors.green : Colors.red,
                    ),
                  ),
                  const SizedBox(height: 10),
                  Text('Platform: $_platformVersion'),
                  const Divider(),
                ],
              ),
            ),
            
            // List of SDK methods
            _buildSDKMethodsList(),
            
            // Results display with performance optimizations
            Container(
              height: 300, // Double the height to show more content
              margin: const EdgeInsets.all(16.0),
              padding: const EdgeInsets.all(8.0),
              decoration: BoxDecoration(
                border: Border.all(color: Colors.grey),
                borderRadius: BorderRadius.circular(8),
              ),
              // Use a ListView builder for optimal performance with large text
              child: Scrollbar(
                child: ListView.builder(
                  itemCount: 1,
                  itemBuilder: (context, index) {
                    return SelectableText(
                      _latestResult,
                      style: const TextStyle(
                        fontFamily: 'monospace',
                        fontSize: 11.0, // Smaller font for better performance
                        height: 1.2, // Tighter line height
                      ),
                    );
                  },
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
1
likes
0
points
518
downloads

Publisher

verified publishersecuriti.ai

Weekly Downloads

A Flutter plugin for managing user consent preferences and compliance with privacy regulations. Integrates with Securiti's Consent Management Platform.

Repository
View/report issues

Documentation

Documentation

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on securiti_consent_sdk

Packages that implement securiti_consent_sdk