Intergrating Appgain SDK in your Flutter app

To integrate the Appgain SDK in your flutter app, you have to use the native SDK libraries, We will use the platform channels method, for more information about running native code in flutter apps please visit the flutter dev guide

For a flutter application integrated with Appgain SDK for ios and android please refer to our flutterTestApp

You will find some supporting file need to copy them to you app to make your integration more easily.

1- lib/Appgain.dart

What included inside it example:- This map data func taking it need to add your values replace default values

var data = {'appId':'value1','apiKey':'value1','configure':'value1'};

 Future initAppgainSDK(Map data) async {
    try {
      await appgainPlatform
          .invokeMethod(_initalizeAppgainSDK, data)
          .then((result) {
            //add what you like here
            print(result);
            TextFieldAlertDialog().showAlertDialog( result.toString());

      });
    } on PlatformException catch (e) {
      print(e.message);
    }
  }

Also in main.dart will find full using all funcationality of SDK and which keys required to sent for it.

Android Specific Instructions

  • At the very top of your Android project's app/build.gradle, add the following code to the very top of the file:
      implementation 'io.appgain:sdk:4.1.12'
      implementation 'com.google.firebase:firebase-messaging:20.2.0'
      implementation 'com.google.android.gms:play-services-ads-lite:18.1.0'
      implementation 'com.google.android.gms:play-services-location:17.0.0'
      implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
      implementation 'io.reactivex.rxjava2:rxjava:2.2.19'
      implementation 'com.squareup.retrofit2:converter-scalars:2.1.0'
      implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
      implementation 'com.android.support.constraint:constraint-layout:1.1.3'
      implementation 'com.squareup.retrofit2:retrofit:2.3.0'
      implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
      implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
      implementation 'com.google.android.exoplayer:exoplayer:2.7.2'
      implementation 'com.github.bumptech.glide:glide:4.10.0'
      annotationProcessor  'com.github.bumptech.glide:compiler:4.10.0'
      implementation 'com.google.firebase:firebase-messaging:20.1.0'
      implementation "androidx.lifecycle:lifecycle-runtime:2.2.0"
      implementation "androidx.lifecycle:lifecycle-process:2.2.0"
      implementation  'androidx.appcompat:appcompat:1.1.0'  
      implementation  'com.google.android.material:material:1.1.0-beta01'  
      implementation  'androidx.legacy:legacy-support-core-ui:1.0.0'
  • also make sure that multiDex is enabled:
    android{
        multiDexEnabled = true
    }
  • and in the end of your file add the following line
   apply plugin: 'com.google.gms.google-services'
  • open your project/build.gradle file and add following line under dependencies
 dependencies {  
    classpath 'com.google.gms:google-services:4.2.0'  
 }

Push Notification setup

firbase project settings


  • Go to Cloud Messaging tab and copy SenderID and Legacy server key

cloud settings


  • Open Appgain Dashboard
  • Go to Project Setting > Advanced Setting > Platforms
  • Navigate to Android push tab
  • enter your SenderID and Server key

Appgain Android Push settings

  • Create a new class that extends from AppgainPushReceiver class
class PushReceiver : AppgainPushReceiver() {
    override fun onReceive(context: Context?, receiveStatus: ReceiveStatus?, intent: Intent?) {

    }
}
  • Open manifest.xml file and add the following lines:
    <receiver
            android:name=".PushReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="com.parse.push.intent.RECEIVE" />
                <action android:name="com.parse.push.intent.DELETE" />
                <action android:name="com.parse.push.intent.OPEN" />
            </intent-filter>
        </receiver>


        <service
            android:name="io.appgain.sdk.controller.AppgainMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
  • In your android application class, implement LifecycleObserver interface and add the follwing lines
class FlutterTestApp : FlutterApplication(), LifecycleObserver {
    override fun onCreate() {

        super.onCreate()
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this)
    }
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onAppBackgrounded() {
        Appgain.onAppBackgrounded()
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onAppForegrounded() {
        Appgain.onAppForegrounded()
    }
}
  • Then in the MainActivity class, add the following
private val CHANNEL = "com.Appgain.io/AppgainSDK"


    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {
            // Note: this method is invoked on the main thread.
            call, result ->
            when(call.method){
                "logEvent" -> {
                    val action: String = call.argument<String>("action")?:""
                    val event: String = call.argument<String>("event")?:""
                    val extras: HashMap<String, String> = call.argument<HashMap<String, String>>("extras")?: hashMapOf()
                    val bundle = Bundle()
                    for(key in extras.keys.toList()) {
                        bundle.putString(key, extras.get(key))
                    }
                    Appgain.logEvent(action, event, bundle, object : AppgainDataCallback<Void> {
                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }

                        override fun onSuccess(data: Void?) {
                            result.success(null)
                        }
                    })
                }
                "initSDK" -> {
                    val apiKey: String = call.argument<String>("apiKey")?:""
                    val appId: String = call.argument<String>("appId")?:""
                    Appgain.enableLog()
                    Appgain.initialize(this, appId, apiKey, true,
                            object : AppgainDataCallback<Void> {
                                override fun onFailure(failure: BaseResponse?) {
                                    result.error("", "", Gson().toJson(failure))

                                }

                                override fun onSuccess(data: Void?) {
                                    result.success(null)
                                }
                            }
                    )
                }
                "getUserID" -> {
                    val userId = Appgain.getUserId()
                    result.success(userId)
                }
                "matchLink" -> {
                    Appgain.matchLink(object : AppgainDataCallback<DeferredDeepLinkingResponse> {
                        override fun onSuccess(data: DeferredDeepLinkingResponse?) {
                            if (data != null) {
                                result.success(Gson().toJson(data))
                            }
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }

                    })
                }
                "fireAutomatorWithPersonalization" -> {
                    val triggerPoint: String = call.argument<String>("triggerPointName")?:""
                    val personalizationData: HashMap<String, String> = call.argument<HashMap<String, String>>("personalizationMap")?: hashMapOf()
                    Appgain.fireAutomator(triggerPoint, personalizationData, object : AppgainDataCallback<Void> {
                        override fun onSuccess(data: Void?) {
                            result.success(null)
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }

                    })
                }
                "fireAutomator" -> {
                    val triggerPoint: String = call.argument<String>("triggerPointName")?:""
                    Appgain.fireAutomator(triggerPoint, HashMap<String, String>(), object : AppgainDataCallback<Void> {
                        override fun onSuccess(data: Void?) {
                            result.success(null)
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }

                    })
                }
                "setuserId" -> {
                    val userId: String = call.argument<String>("userId")?:""
                    Appgain.updateUserId(userId, object : AppgainDataCallback<String> {
                        override fun onSuccess(data: String?) {
                            result.success(data)
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }

                    })
                }
                "addPurchase" -> {
                    val productName: String = call.argument<String>("productName")?:""
                    val amount: Double = call.argument<Double>("amount")?:0.0
                    val currency: String = call.argument<String>("curruncy")?:""
                    Appgain.logPurchase(productName, amount.toFloat(), currency, object : AppgainDataCallback<Void> {
                        override fun onSuccess(data: Void?) {
                            result.success(null)
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }
                    })
                }
                "enableReciveNotification" -> {
                    val enable: Boolean = call.argument<Boolean>("enable")?:true
                    val channel: String = call.argument<String>("type")?:""
                    Appgain.enableNotifications(enable, channel, object : AppgainDataCallback<Void> {
                        override fun onSuccess(data: Void?) {
                            result.success(null)
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }
                    })
                }
                "addNotificationChannel" -> {
                    val channel: String = call.argument<String>("notificationType")?:""
                    val data: String = call.argument<String>("item")?:""
                    Appgain.createNotificationChannel(channel, data, object : AppgainDataCallback<Void> {
                        override fun onSuccess(data: Void?) {
                            result.success(null)
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }
                    })
                }
                "updateUser" -> {
                    val userData = call.argument<HashMap<String, String>>("userData")?: hashMapOf()
                    Appgain.updateUserData(userData, object : AppgainDataCallback<Void> {
                        override fun onSuccess(data: Void?) {
                            result.success(null)
                        }

                        override fun onFailure(failure: BaseResponse?) {
                            result.error("", "", Gson().toJson(failure))
                        }
                    })
                }
                else -> {
                    result.notImplemented()
                }
            }
        }
    }

For more info about all the methods in the Appgain SDK. please, refer to our native guides for android and ios

iOS Specific Instructions

Installation

1- Add appgain pod to your generated project from flutter

pod 'Appgain'

2- Add

#import "Appgain.h"

To file <!project name!>-Bridging-Header.h

3- Add pod configuration for your pod installation inside generate file Debug.xcconfig

#include "Pods/Target Support Files/Pods-<!your-project-name!>/Pods-<!your-project-name!>.debug.xcconfig"

4- Add those inside Release.xcconfig

#include "Pods/Target Support Files/Pods-<!your-project-name!>/Pods-<!your-project-name!>.release.xcconfig"

#include "Pods/Target Support Files/Pods-<!your-project-name!>/Pods-<!your-project-name!>.profile.xcconfig"

5- Copy theses file to your project from demo app.

AppDelegate+Flutter+Extension.swift

AppDelegate+Notifications+Extension.swift

6- How we start with this code Inside AppDelegate.swift

@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        let controller = self.window.rootViewController as! FlutterViewController

        //add and link Appgain SDK
        linkAppgainNativeCode(controller: controller)

        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }  
}

7- How use it in flutter

Inside Appgain.dart

you will find all funcationality available form our sdk

For Example


//MARK: logPurchaseForItem
//this data have you sent for this func included with default value 
just need to change values and leave key as it


//productName (String)
//currency (String)
//amount (String)


// var data = {'productName':'value','curruncy':'value','amount':22};


  Future addPurchase(Map data) async {
    try {
      await appgainPlatform
          .invokeMethod(_logNewPurchase, data)
          .then((result) {
        //add what you like here
        print(result);
        TextFieldAlertDialog().showAlertDialog( result.toString());

      });
    } on PlatformException catch (e) {
      print(e.message);
    }
  }

PushNotificationSetup

Add Appgain Rich Notification

Quide for native Rich Notification

1- Add target for rich notification

2- Add pod of rich push for two target

  pod 'Appgain-Rich'

3- Add pod configuration for your pod installation inside generate file Debug.xcconfig

#include "Pods/Target Support Files/Pods-<!your-content-extention-name!>/Pods-<!your-content-extention-name!>.debug.xcconfig"

#include "Pods/Target Support Files/Pods-<!your-service-extention-name!>/Pods-<!your-service-extention-name!>.debug.xcconfig"

4- Add those inside Release.xcconfig

//extention of service

#include "Pods/Target Support Files/Pods-<!your-service-extention-name!>/Pods-<!your-service-extention-name!>.release.xcconfig"

#include "Pods/Target Support Files/Pods-<!your-service-extention-name!>/Pods-<!your-service-extention-name!>.profile.xcconfig"

//extention of content

#include "Pods/Target Support Files/Pods-<!your-content-extention-name!>/Pods-<!your-content-extention-name!>.release.xcconfig"

#include "Pods/Target Support Files/Pods-<!your-content-extention-name!>/Pods-<!your-content-extention-name!>.profile.xcconfig"