How to Integrate the Device Data Collector into Flutter Applications

Flutter is a named channel for communicating with platform plugins using asynchronous method calls. Method calls are encoded into binary before being sent, and binary results received are decoded into Dart values. The MethodCodec used must be compatible with the one used by the platform plugin.

To integrate the Mobile SDKs into a hybrid Flutter application, there are three main steps:

  1. iOS Integration

  2. Android Integration

  3. Platform Selection Integration

Integrating the Device Data Collector iOS SDK to Flutter Hybrid Applications

Provide native support for your solution by integrating the iOS SDK into your Flutter application. This allows you to use our services without having to create API calls.

Integration Steps for iOS (include SDK in project)

There are three ways to integrate iOS SDK with Flutter:

  1. Go to Flutter Project and then iOS. Open .xcworkspace(if pod is there)/.xcodeproj.

  2. For CocoaPods integration, if you receive an error similar to the sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation proceed with the following methods to resolve it.

    1. Method 1: Choose the target, go to Build Phases, select Link Binary With Libraries, and then remove all libPods.a files. Open Terminal and then direct to your project. Run pod install. Clean and build the project.

    2. Method 2: Open the Terminal. Direct to your project and then run: pod deintegrate –verbose and pod install –verbose.

    3. Method 3: Add two User-Defined Settings: [to the left = to the right] Run PODS_ROOT = ${SRCROOT}/Pods and PODS_PODFILE_DIR_PATH = ${SRCROOT}/.

Integration Steps for iOS (create wrapper)

Swift

  1. A Runner-Bridging-header.h file is created automatically. Open this and write the following import statements:

          #import "GeneratedPluginRegistrant.h"
          #import "KDataCollector.h"
          #import "KountAnalyticsViewController.h"
        
  2. In the Appdelegate.swift file, update the merchantID field with the merchant ID that was assigned to you. In addition, use the KEnvironment.test environment when running tests, and KEnvironment.prod when releasing running in production.

        KDataCollector.shared().locationCollectorConfig = KLocationCollectorConfig.requestPermissionKDataCollector.shared().debug = true
        KDataCollector.shared().merchantID = "900900" // Insert your valid merchant ID
        KDataCollector.shared().environment = KEnvironment.test
        
        KountAnalyticsViewController().setEnvironmentForAnalytics(KDataCollector.shared().environment)
        
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet 
        collectChannel = FlutterMethodChannel(name: "DataCollector", binaryMessenger: controller.binaryMessenger)
        collectChannel.setMethodCallHandler({[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
            // Note: this method is invoked on the UI thread.
            if call.method == "collect" {
                            self?.callCollect(result: result)
                         }
                        else if call.method == "getSessionID" {
                           self?.callGetSessionID(result: result)
                         }
                         else {
                            result(FlutterMethodNotImplemented)
                            return
                         }
        })
        
  3. Create a private function, callCollect() which takes the result as an argument. In this function, invoke the collector using either the the supplied sessionID KountAnalyticsViewController.getAppSessionID(), your own sessionID, or @"".

    Do not forget to send the sessionID used here back to your servers. You need to use it when making API calls to evaluate this transaction/event. Analytics are not available for hybrid apps, so ensure the analyticsSwitch is set to False. This example shows the callback function which will be returned upon completion. Update them as needed for your application.

        private func callCollect(result: @escaping FlutterResult) {
        KountAnalyticsViewController().collect(KountAnalyticsViewController.getAppSessionID(), analyticsSwitch:false) {
          (sessionID, success, error) in
            if (success) {
              result("Collection Successful")
              print("Collection Successful")
            }
            else {
                if((error) != nil) {
                  print("Collection failed with error",error?.localizedDescription as Any)
                }else {
                  print("Collection failed without error")
                }
                result(FlutterError(code: "UNAVAILABLE" ,message:error?.localizedDescription, details: nil))
            }
          }
        }
                         
        
        private func callGetSessionID(result: @escaping FlutterResult) {
          result(KountAnalyticsViewController.getAppSessionID())
        }
        

Objective-C

  1. Open AppDelegate.m and add the following code.

        #import "KDataCollector.h"
        #import "KountAnalyticsViewController.h"
        
  2. In the Appdelegate.m file, write the following code snippet. Update the merchantID field with the merchant ID that was assigned to you. In addition, use the KEnvironmentTest environment when running tests, and KEnvironmentProduction when releasing running in production.

        [[KDataCollector sharedCollector] setDebug:YES];
        // TODO Set your Merchant ID
        [[KDataCollector sharedCollector] setMerchantID:@"900900"];
        // TODO Set the location collection configuration
        [[KDataCollector sharedCollector] setLocationCollectorConfig:KLocationCollectorConfigRequestPermission];
        // For a released app, you'll want to set this to KEnvironmentProduction
        [[KDataCollector sharedCollector] setEnvironment:KEnvironmentTest];
        [[KountAnalyticsViewController sharedInstance] setEnvironmentForAnalytics: [KDataCollector.sharedCollector environment]];
        FlutterViewController *controller = [[FlutterViewController alloc] init];
        controller = (FlutterViewController*)self.window.rootViewController;
        FlutterMethodChannel *collectChannel = [FlutterMethodChannel methodChannelWithName:@"DataCollector" binaryMessenger:controller.binaryMessenger];
        [collectChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
            if ([call.method isEqual:@"collect"]) {
                [self callCollect:result];
            }
            else if ([call.method isEqual:@"getSessionID"]) {
                [self callGetSessionID:result];
            }
            else {
                result(FlutterMethodNotImplemented);
            }
        }];
        
  3. Create a private function, callCollect() which takes result as argument and is being called in above code snippet. In this function, you must invoke the collector using either the Kount Supplied sessionID KountAnalyticsViewController.getAppSessionID, your own sessionID, or @"".

    Do not forget to send the sessionID used here back to your servers. You will need to use it when making API calls to evaluate this transaction/event. Analytics are not available for hybrid apps, so ensure the analyticsSwitch is set to False. This example shows the callback function which will be returned upon completion. Update them as needed for your application.

        - (void)callCollect:(_Nonnull FlutterResult)result {
            [[KountAnalyticsViewController sharedInstance] collect:@"" analyticsSwitch:NO completion:^(NSString * _Nonnull sessionID, BOOL success, NSError * _Nullable error) {
                    if(success) {
                        result(@"Collection Successful");
                        NSLog(@"Collection Successful");
                    }
                    else {
                        if (error != nil) {
                            NSLog(@"Collection failed with error:%@",error.description);
                        }
                        else {
                            NSLog(@"Collection failed without error");
                        }
                        result([FlutterError errorWithCode:@"UNAVAILABLE" message:error.localizedDescription details:nil]);
                    }
            }];
        }
    
        - (void)callGetSessionID:(_Nonnull FlutterResult)result {
            result([KountAnalyticsViewController getAppSessionID]);
        }
        

If you get a build fail error like this ld: library not found for -lKountDataCollector” “clang: error: linker command failed with exit code 1 (use -v to see invocation), then follow the steps below.

  1. Click the Plus (+) button.

  2. Select KountDataCollector.xcframework.

  3. Click Add.

  1. Click on your project in the project navigator to open your project settings.

  2. Select your target, and then open the General tab.

  3. Scroll to Frameworks, Libraries, and then Embedded Content Settings.

  4. On the newly-added KountDataCollector.xcframework, select Do Not Embed.

  5. If you do not see KountDataCollector.xcframework, you must add it manually:

Integrating the Device Data Collector Android SDK to Flutter Hybrid Apps

Integrate the Device Data Collector Android SDK into your Flutter application to collect additional end-user information. This assists in detecting suspicious devices and preventing fraud.

Integration Steps for Android (include in project)

There are two project integration options. We recommend using the Gradle option if you do not have a preference.

  1. How to Integrate the Device Data Collector into Mobile Apps using Android Gradle.

  2. How to Integrate the Device Data Collector into Android Applications using the Library JAR.

    Note

    If android:allowbackup attribute is false in your <application> tag, add tools:replace="android:allowBackup" to your application tag.

Integration Steps for Android (create wrapper)

  1. In the main activity of your application, initialize the collector and assign the merchant ID you received. Optionally, you can provide a session ID if you need to generate your own (if not, the SDK generates one for you). You must send this session ID back to your servers in order to make calls to the API. Add the following initialization in your MainActivity:

        import com.kount.api.analytics.AnalyticsCollector
        import com.kount.api.analytics.AnalyticsConstants
        import com.kount.api.analytics.Analytics
         ....
        override fun onCreate(savedInstanceState: Bundle?) { 
            ...
            private val CHANNEL = "DataCollector" // Name for method channel
            // REQUIRED SECTION
            AnalyticsCollector.setMerchantId("999999")
            // END REQUIRED SECTION
            
            //Set below flags to true to enable devicedata and device fingerprint data collection.
            AnalyticsConstants.collectDeviceDataForSession=true
            AnalyticsConstants.collectDeviceFingerprintDataForSession=true
        
            //For production need to add AnalyticsCollector.ENVIRONMENT_PRODUCTION .
            AnalyticsCollector.setEnvironment(AnalyticsCollector.ENVIRONMENT_TEST)
    
            // OPTIONAL SESSION_ID SECTION
            val deviceSessionID = UUID.randomUUID().toString()
            AnalyticsCollector.setSessionId(deviceSessionID)
            //END OPTIONAL SESSION_ID SECTION
        //Method Channel name must be same as the one used in .dart file for invoking this method.
            MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            // Note: this method is invoked on the UI thread.
            if (call.method == "collectData") {
              collectData()
            }
          }
        }
        
  2. Create a private function, collectData().

    private fun collectData() {
        AnalyticsCollector.collectDeviceDataForSession(this@MainActivity, {sessionId ->
        Log.d("TAG", "success completed with sessionId $sessionId")
        Log.d("TAG", "DDC STATUS is :" + AnalyticsCollector.getCollectionStatus()?.name)
      },{ sessionId, error ->
        Log.d("TAG", " failed with sessionId $error, $sessionId")
        Log.d("TAG", "DDC STATUS is :" + AnalyticsCollector.getCollectionStatus()?.name)
      })
    }
        
  3. To support Location Collection in Android API 23 and above, add the following permissions to your main activity with the onCreate method.

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
           if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) {
               ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), AnalyticsCollector.REQUEST_PERMISSION_LOCATION)
           } 
           else {
               ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), AnalyticsCollector.REQUEST_PERMISSION_LOCATION)
           }
        }
        

    Note

    While preferred, not all apps are approved in the app store to use the ACCESS_FINE_LOCATION. If your app has been rejected for having this permission, replace ACCESS_FINE_LOCATION (uses GPS) with ACCESS_COARSE_LOCATION (uses cellular triangulation).

Platform Selection Integration in Flutter App

  1. In the Flutter application, go to main.dart and add the following code snippet.

        import 'dart:io' show Platform;
        
        class _MyHomePageState extends State<MyHomePage> { 
        static const method_channel='DataCollector' 
          static const platform = const MethodChannel(method_channel);  
          String _collectionStatus = 'Collect Data';
        
          Future<void> _startCollection() async {    
            String collectionStatus="NOT_STARTED";    
            try {
               if(Platform.isAndroid){        
                  await platform.invokeMethod('collectData');      
               }
               else if(Platform.isIOS){        
                  final String result = await platform.invokeMethod('collect');        
                  collectionStatus = '$result.';      
               }
            } on PlatformException catch (e) {      
                collectionStatus = "Did not find method '${e.message}'.";    
              }
            setState(() {      
              _collectionStatus = collectionStatus; 
              }); 
            }
            
            @override  Widget build(BuildContext context) {   
                return Scaffold(      
                  appBar: AppBar(       
                   title: Text(widget.title),      
                  ),      
                  body: Center(        
                    child: Column(         
                       mainAxisAlignment: MainAxisAlignment.center,          
                        children: <Widget>[            
                          ElevatedButton(
                            child: Text('Collect'),              
                            onPressed: _startCollection,            
                          ),            
                          Text(_collectionStatus),          
                        ],        
                    ),      
                  )    
                );  
            }}
        
  2. Run the Flutter app.

    The app should capture the data points for the Device Data Collector in both iOS and Android platforms.

Was this article helpful?
0 out of 0 found this helpful