Skip to content

๐Ÿ“ฑ Mobile Engineer - Complete Guide

Mobile Engineers are responsible for developing native mobile applications for iOS and Android platforms, integrating the Appgain Mobile SDK, and ensuring optimal user experiences across mobile devices.

๐ŸŽฏ Role Overview

Primary Responsibilities

  • Native App Development: iOS (Swift/Objective-C) and Android (Kotlin/Java) development
  • SDK Integration: Integrate and configure Appgain Mobile SDK
  • Push Notifications: Implement push notification systems
  • Deep Linking: Set up smart deep links and URL handling
  • Performance Optimization: Ensure smooth app performance and battery efficiency
  • Cross-Platform Consistency: Maintain consistent user experience across platforms

Key Technologies

  • iOS Development: Swift, Objective-C, Xcode, iOS SDK
  • Android Development: Kotlin, Java, Android Studio, Android SDK
  • Appgain Mobile SDK: Core SDK for both platforms
  • Firebase: Push notifications and analytics
  • React Native: Cross-platform development (optional)
  • Flutter: Cross-platform development (optional)

๐Ÿ› ๏ธ Development Environment Setup

iOS Development Prerequisites

# Install Xcode from App Store
# Install iOS Simulator
# Install CocoaPods
sudo gem install cocoapods

# Install Carthage (alternative to CocoaPods)
brew install carthage

Android Development Prerequisites

# Install Android Studio
# Install Android SDK
# Install Java Development Kit (JDK)
# Configure environment variables
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools

Project Setup

# Clone mobile repositories
git clone https://github.com/appgain/ios-app.git
git clone https://github.com/appgain/android-app.git
git clone https://github.com/appgain/react-native-app.git

# Install dependencies
cd ios-app && pod install
cd ../android-app && ./gradlew build
cd ../react-native-app && yarn install

๐Ÿ“ฑ Appgain Mobile SDK Integration

Core SDK Features

  • User Management: User registration, authentication, and profile management
  • Push Notifications: Firebase-based push notification system
  • Smart Deep Links: Dynamic deep linking with fallback URLs
  • Analytics: User behavior tracking and conversion analytics
  • Campaign Management: In-app campaign delivery and tracking
  • Social Media Integration: Social sharing and engagement tracking

Platform-Specific SDKs

Android SDK

  • Documentation: Android SDK Installation Guide
  • Version: Latest stable release
  • Dependencies: Firebase, Retrofit, RxJava, Glide
  • Features: Background processing, battery optimization, custom push receivers

iOS SDK

  • Documentation: iOS SDK Installation Guide
  • Version: Latest stable release
  • Dependencies: Firebase, Alamofire, SDWebImage
  • Features: Background app refresh, silent notifications, rich media support

React Native SDK

  • Documentation: React Native SDK Guide
  • Version: Latest stable release
  • Features: Cross-platform compatibility, JavaScript bridge

Flutter SDK

  • Documentation: Flutter SDK Installation Guide
  • Version: Latest stable release (^0.0.10)
  • Features: Cross-platform development, deferred deep linking, marketing automation

๐Ÿš€ Flutter Project Structure Guide

This guide outlines our standard process for setting up and maintaining Flutter projects at Appgain, including tools, architecture, git flow, CI/CD, and best practices.

๐Ÿ“ฆ Project Setup

Create New Project

  • Use the latest stable Flutter SDK.
  • Project package name must start with:

    com.appgain.<appName>
    

  • Example:

    flutter create --org com.appgain.myapp myapp
    cd myapp
    flutter pub get
    

๐Ÿ’ป IDE Plugin Setup

Install the following IDE plugins (in VS Code or Android Studio):

Plugin Name Description
Bloc State management tooling (flutter_bloc)
Dart Dart language support
Flutter Flutter SDK integration
Flutter Intl Internationalization tools
.env Highlighting for environment variables
GitLive Git history, merge, and team insight

๐Ÿงฑ Project Architecture

We support two main architectures depending on project size and complexity: MVVM and Clean Architecture. Both are applied using a modular, feature-based folder structure.

โœ… MVVM Architecture (Default)

Applied to small and medium-sized projects.

Structure:

lib/
โ””โ”€โ”€ features/
    โ””โ”€โ”€ <feature_name>/
        โ”œโ”€โ”€ data/
        โ”‚   โ”œโ”€โ”€ datasources/
        โ”‚   โ”‚   โ”œโ”€โ”€ local/
        โ”‚   โ”‚   โ””โ”€โ”€ remote/
        โ”‚   โ”œโ”€โ”€ models/
        โ”‚   โ””โ”€โ”€ repo/
        โ”œโ”€โ”€ presentation/
        โ”‚   โ”œโ”€โ”€ cubit/ (or bloc/)
        โ”‚   โ”œโ”€โ”€ screens/
        โ”‚   โ””โ”€โ”€ widgets/

  • data: Contains models, local and remote data sources, and repository implementation.
  • presentation: Holds Cubit or Bloc, UI screens, and reusable widgets.

๐Ÿงผ Clean Architecture (For Large & Scalable Projects)

Recommended for larger codebases requiring better separation of concerns.

Structure:

lib/
โ””โ”€โ”€ features/
    โ””โ”€โ”€ <feature_name>/
        โ”œโ”€โ”€ domain/
        โ”‚   โ”œโ”€โ”€ entities/
        โ”‚   โ”œโ”€โ”€ repositories/ (abstract definitions)
        โ”‚   โ””โ”€โ”€ usecases/
        โ”œโ”€โ”€ data/
        โ”‚   โ”œโ”€โ”€ models/
        โ”‚   โ”œโ”€โ”€ datasources/
        โ”‚   โ”‚   โ”œโ”€โ”€ local/
        โ”‚   โ”‚   โ””โ”€โ”€ remote/
        โ”‚   โ”œโ”€โ”€ repo/ (implements domain layer repos)
        โ”‚   โ””โ”€โ”€ mappers/
        โ”œโ”€โ”€ presentation/
        โ”‚   โ”œโ”€โ”€ cubit/ (or bloc/)
        โ”‚   โ”œโ”€โ”€ screens/
        โ”‚   โ””โ”€โ”€ widgets/

  • domain: Pure Dart layer with no Flutter dependencies. Contains abstract repositories, entities, and use cases.
  • data: Implements the domain layer. Models are not extended from entities but mapped via mappers to ensure SRP (Single Responsibility Principle).
  • presentation: Manages UI and state.

Here are the most used and recommended packages across Appgain projects:

  • flutter_bloc, get_it, injectable, easy_localization
  • dio, pretty_dio_logger, logger
  • flutter_screenutil, shimmer_animation, flutter_spinkit
  • hive, hive_flutter, json_serializable, freezed
  • flutter_svg, flutter_dotenv, fluttertoast, toastification
  • intl, intl_phone_number_input, pull_to_refresh
  • go_router, awesome_notifications, image_picker
  • upgrader, cupertino_icons, animated_custom_dropdown

๐Ÿ” Git Flow Strategy

We follow a structured Git Flow branching model:

Branch Types:

  • feature/xxx: New features
  • fix/xxx: Bug fixes
  • hotfix/xxx: Urgent production issues
  • release/xxx: Release candidate for testing

Main Branches:

  • develop: All features merged here after review/testing.
  • main or master: Final production release.
  • A release is tagged here after successful deployment.

๐Ÿ’ฌ Commit Message Rules

Each commit should follow this format:

<TYPE>: <short description>

Allowed Types:

  • FEAT: New feature
  • FIX: Bug fix
  • CHORE: Tooling, config, refactor (non-feature/fix)

โœ… Limit one commit to a maximum of 10 files.

โš™๏ธ CI/CD Integration with Codemagic

After development is done:

๐Ÿ”— Codemagic Setup

  • Connect your GitLab project to Codemagic.
  • Configure workflows for release testing and production deployment.

๐Ÿงช Firebase Distribution

  • Deploy release candidates to Firebase for QA testing.

๐Ÿ“ฆ Production Deployment

  • Final versions go to:
  • โœ… Google Play Store
  • โœ… Apple App Store

๐Ÿ› ๏ธ Pre-Build Script (for codegen projects)

Add the following to Codemagic > Pre-build script if you use code generation (Freezed, JsonSerializable, Injectable, etc.):

flutter clean
rm pubspec.lock
rm ios/Podfile.lock
flutter pub get

dart run build_runner build --delete-conflicting-outputs

dart run intl_utils:generate # or any alternative localization generator

cd ios
pod repo update
pod install

๐Ÿงพ Code Generation & Git Ignore

If using code generation, be sure to ignore generated files:

.gitignore additions:

# generated files
*.g.dart
*.freezed.dart
*.config.dart
*.gen.dart
*.auto_mappr.dart
**/generated
**/gen
**/.fvm

โœ… Final Notes

  • Use build_runner for generating models and helpers.
  • Keep architecture clean and modular.
  • Always test before merging or tagging release builds.

๐Ÿ”ง Android SDK Integration

Setup Requirements

  • Android Studio: Latest version
  • Appgain Account: Project ID and API Key
  • Firebase Project: Google Server API Key and configuration
  • Android Package Name: Unique app identifier

Installation Steps

1. Firebase Setup

# Create Firebase project
# Download google-services.json
# Add to app/ directory
# Configure build.gradle files

2. Gradle Configuration

// Project-level build.gradle
allprojects {
    repositories {
        maven { url "https://sdk.appgain.io/repository/maven-releases/" }
        google()
        jcenter()
    }
}

// App-level build.gradle
dependencies {
    implementation 'io.appgain.sdk:appgain-android:5.0.0'
    implementation platform('com.google.firebase:firebase-bom:31.0.1')
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-messaging'
    implementation 'com.google.android.gms:play-services-ads-lite:21.3.0'
    implementation 'com.google.android.gms:play-services-location:21.0.0'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.2.20'
    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.11.0'
    implementation 'com.google.android.exoplayer:exoplayer:2.19.1'
    implementation 'com.github.bumptech.glide:glide:4.15.1'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1'
}

3. Application Class Setup

public class AppController extends MultiDexApplication implements LifecycleObserver {

    @Override
    public void onCreate() {
        super.onCreate();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
        Appgain.enableLog();

        // Initialize Appgain SDK
        boolean trackAdvertisingId = true;
        Appgain.initialize(getApplicationContext(), "APPGAIN_PROJECT_ID", "APPGAIN_API_KEY", trackAdvertisingId, new AppgainDataCallback<Void>(){
            @Override
            public void onSuccess(Void data) {
                Log.d("Appgain", "init success");
            }

            @Override
            public void onFailure(BaseResponse failure) {
                Log.e("Appgain", "Error:" + failure.getMessage());
            }
        });
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onAppBackgrounded() {
        Appgain.onAppBackgrounded();
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onAppForegrounded() {
        Appgain.onAppForegrounded();
    }
}

4. Push Notification Setup

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

<application>
    <service android:name="io.appgain.sdk.controller.AppgainMessagingService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT"/>
        </intent-filter>
    </service>

    <meta-data
        android:name="com.parse.push.notification_icon"
        android:resource="@drawable/ic_app_notfication" />

    <receiver
        android:name=".MyPushReceiver"
        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>
</application>

5. Custom Push Receiver

public class MyPushReceiver extends AppgainPushReceiver {
    @Override
    protected void onReceive(Context context, ReceiveStatus receiveStatus, Intent intent) {
        // Custom push handling logic
    }

    @Override
    protected void onPushNotificationReceived(Context context, ReceiveStatus receiveStatus, Intent intent, PushDataReceiveModel pushDataReceiveModel) {
        super.onPushNotificationReceived(context, receiveStatus, intent, pushDataReceiveModel);

        // Handle push notification data
        String attachment = pushDataReceiveModel.getAttachment();
        String alert = pushDataReceiveModel.getAlert();
        String url = pushDataReceiveModel.getUrl();
        String campaignName = pushDataReceiveModel.getCampaignName();
        String campaignId = pushDataReceiveModel.getCampaignId();
    }
}

๐ŸŽฏ Flutter SDK Integration

Setup Requirements

  • Flutter SDK: Latest stable version
  • Appgain Account: Project ID and API Key
  • Firebase Project: Configuration for both platforms
  • iOS Bundle Identifier: Unique app identifier
  • Android Package Name: Unique app identifier

Installation Steps

1. Add Flutter Dependency

# Add Appgain SDK to pubspec.yaml
flutter pub add appgain_sdk
# pubspec.yaml
dependencies:
  appgain_sdk: ^0.0.10
  flutter:
    sdk: flutter

2. Import and Initialize SDK

import 'package:appgain_sdk/appgain_sdk.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Initialize Appgain SDK
    Appgain().initAppgainSDK(
      appId: 'YOUR_APP_ID',
      apiKey: 'YOUR_API_KEY'
    );

    return MaterialApp(
      title: 'Flutter App',
      home: MyHomePage(),
    );
  }
}

3. Deferred Deep Linking

// Match deep links after app installation
Appgain().matchLink().then((result) {
  if (result != null) {
    // Handle deep link data
    String smartLinkUrl = result['smart_link_url'];
    String smartLinkId = result['smart_link_id'];
    String smartLinkName = result['smart_link_name'];
    String matchType = result['match_type'];

    // Access extra data
    Map<String, dynamic> extraData = result['extra_data'];
    String userId = extraData['userId'];
    Map<String, dynamic> params = extraData['params'];

    // Handle parameters (e.g., coupon codes)
    String coupon = params['coupon'];

    // Navigate to appropriate screen
    if (coupon != null) {
      // Navigate to coupon screen
    }
  }
});

4. Marketing Automation

// Fire automation without personalization
await Appgain().fireAutomator(
  triggerPoint: 'YOUR_TRIGGER_POINT_NAME'
);

// Fire automation with personalization
var personalizationData = {
  'name': 'John',
  'cartName': 'Sports',
  'key': 'value'
};

await Appgain().fireAutomatorWithPersonalization(
  triggerPoint: 'YOUR_TRIGGER_POINT_NAME',
  personalizationMap: personalizationData
);

5. Revenue Tracking

// Track purchase transactions
await Appgain().addPurchase(
  productName: 'Premium Subscription',
  amount: 99.99,
  currency: 'USD'
);

6. Custom Events Tracking

// Log custom events
await Appgain().logEvent(
  type: 'user_action',
  action: 'registration',
  extras: {
    'source': 'email',
    'campaign': 'winter_2024',
    'user_type': 'new'
  }
);

7. User Attributes Management

// Update user attributes
var updatedData = {
  'userEmail': 'user@example.com',
  'phone': '+1234567890',
  'subscription': 'premium',
  'lastLogin': DateTime.now().toIso8601String()
};

await Appgain().updateUser(data: updatedData);

8. Get User ID

// Retrieve Appgain user ID
Appgain().getUserId().then((userId) {
  print('Appgain User ID: $userId');
});

9. Notification Channels

// Enable/disable notification channels
await Appgain().enableReceiveNotification(
  channel: 'email',
  isEnabled: true
);

await Appgain().enableReceiveNotification(
  channel: 'phone',
  isEnabled: true
);

iOS-Specific Configuration

1. AppDelegate Setup

@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)

    // Register for remote notifications
    registerForRemoteNotification()

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

2. Network Security Configuration

<!-- Info.plist -->
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

3. Rich Notifications Setup

// NotificationService.swift
import UserNotifications
import Appgain_Rich

class NotificationService: UNNotificationServiceExtension {
  var contentHandler: ((UNNotificationContent) -> Void)?
  var bestAttemptContent: UNMutableNotificationContent?

  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

    if let bestAttemptContent = bestAttemptContent {
      AppgainRich.didReceive(request, andNotificationContent: bestAttemptContent, withContentHandler: contentHandler)
      contentHandler(bestAttemptContent)
    }
  }
}

4. Apple IDFA Tracking

<!-- Info.plist -->
<key>NSUserTrackingUsageDescription</key>
<string>Privacy of our platform users is extremely important and we at Customer App are committed to protecting the same. Your personal information is collected only to understand your journey within the platform and as a part of the search process.</string>
import AppTrackingTransparency

func applicationDidBecomeActive(_ application: UIApplication) {
  if #available(iOS 14, *) {
    ATTrackingManager.requestTrackingAuthorization { status in
      switch status {
        case .authorized:
          print("enable tracking")
        case .denied:
          print("disable tracking")
        default:
          print("disable tracking")
      }
    }
  }
}

Android-Specific Configuration

1. Gradle Configuration

// android/app/build.gradle
dependencies {
  implementation 'io.appgain.sdk:appgain-android:5.0.0'
  implementation platform('com.google.firebase:firebase-bom:31.0.1')
  implementation 'com.google.firebase:firebase-analytics'
  implementation 'com.google.firebase:firebase-messaging'
}

2. Firebase Setup

<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

<application>
  <service android:name="io.appgain.sdk.controller.AppgainMessagingService">
    <intent-filter>
      <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
  </service>
</application>

Testing and Debugging

1. SDK Test App

  • Flutter Test App: Available in SDK repository
  • Test Features: Deep linking, push notifications, analytics, conversions

2. Debug Commands

// Enable debug logging
Appgain().enableLog();

// Check SDK version
String version = Appgain().getSDKVersion();
print('SDK Version: $version');

3. Common Issues & Solutions

Deep Links Not Working: - Verify URL scheme configuration - Check fallback URLs - Test with different scenarios - Validate link creation

Push Notifications Not Working: - Verify Firebase configuration - Check APNs certificate (iOS) - Ensure proper permissions - Test with SDK test app

Analytics Not Tracking: - Check network connectivity - Verify API key configuration - Enable debug logging - Check user permissions

๐ŸŽ iOS SDK Integration

Setup Requirements

  • Xcode: Latest version
  • Appgain Account: Project ID and API Key
  • Firebase Project: APNs certificate and configuration
  • iOS Bundle Identifier: Unique app identifier

Installation Steps

1. CocoaPods Setup

# Podfile
platform :ios, '12.0'

target 'YourApp' do
  use_frameworks!

  pod 'AppgainSDK', '~> 5.0.0'
  pod 'Firebase/Analytics'
  pod 'Firebase/Messaging'
  pod 'Firebase/RemoteConfig'
end

2. AppDelegate Setup

import UIKit
import AppgainSDK
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Configure Firebase
        FirebaseApp.configure()

        // Initialize Appgain SDK
        Appgain.initialize(projectId: "APPGAIN_PROJECT_ID", apiKey: "APPGAIN_API_KEY") { result in
            switch result {
            case .success:
                print("Appgain SDK initialized successfully")
            case .failure(let error):
                print("Appgain SDK initialization failed: \(error)")
            }
        }

        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Appgain.setDeviceToken(deviceToken)
    }

    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Failed to register for remote notifications: \(error)")
    }
}

3. Push Notification Handling

import UserNotifications

extension AppDelegate: UNUserNotificationCenterDelegate {

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.alert, .badge, .sound])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        // Handle notification tap
        let userInfo = response.notification.request.content.userInfo
        Appgain.handleNotificationResponse(userInfo)
        completionHandler()
    }
}
// Android
SmartDeepLinkCreator smartDeepLinkCreator = new SmartDeepLinkCreator.Builder()
    .withName("Page name")
    .withAndroid("Primary URL", "Fallback URL")
    .withIos("Primary URL", "Fallback URL")
    .withWeb("Web URL")
    .withSocialMediaTitle("title")
    .withSocialMediaDescription("Description...")
    .withSocialMediaImage("URL")
    .build();

Appgain.createSmartLink(smartDeepLinkCreator, new AppgainDataCallback<String>() {
    @Override
    public void onSuccess(String link) {
        Log.d("createSmartLink", "success: " + link);
    }

    @Override
    public void onFailure(BaseResponse failure) {
        Log.e("createSmartLink", "Error:" + failure.getMessage());
    }
});
// iOS
let smartLinkCreator = SmartDeepLinkCreator()
    .withName("Page name")
    .withAndroid(primaryURL: "Primary URL", fallbackURL: "Fallback URL")
    .withIos(primaryURL: "Primary URL", fallbackURL: "Fallback URL")
    .withWeb(url: "Web URL")
    .withSocialMediaTitle("title")
    .withSocialMediaDescription("Description...")
    .withSocialMediaImage("URL")

Appgain.createSmartLink(smartLinkCreator) { result in
    switch result {
    case .success(let link):
        print("Smart link created: \(link)")
    case .failure(let error):
        print("Smart link creation failed: \(error)")
    }
}

๐Ÿ“Š Analytics & Conversion Tracking

User Management

// Android - Get User ID
Appgain.getUserId(new AppgainDataCallback<String>() {
    @Override
    public void onSuccess(String userId) {
        Log.d("UserID", userId);
    }
    @Override
    public void onFailure(BaseResponse errorResponse) {
        Log.e("UserID", "Error: " + errorResponse.getMessage());
    }
});
// iOS - Get User ID
Appgain.getUserId { result in
    switch result {
    case .success(let userId):
        print("User ID: \(userId)")
    case .failure(let error):
        print("Failed to get user ID: \(error)")
    }
}

Conversion Tracking

// Android - Record Conversion
Appgain.recordConversion("action", 100, "campaignName", "campaignId", new AppgainDataCallback<Void>() {
    @Override
    public void onSuccess(Void data) {
        Log.d("recordConversion", "success");
    }

    @Override
    public void onFailure(BaseResponse failure) {
        Log.e("recordConversion", "Error:" + failure.getMessage());
    }
});
// iOS - Record Conversion
Appgain.recordConversion(action: "action", value: 100, campaignName: "campaignName", campaignId: "campaignId") { result in
    switch result {
    case .success:
        print("Conversion recorded successfully")
    case .failure(let error):
        print("Failed to record conversion: \(error)")
    }
}

Notification Channels

// Android - Update Notification Channels
Appgain.updateNotificationChannels("email", "phone", new AppgainDataCallback<Void>() {
    @Override
    public void onSuccess(Void data) {
        Log.d("NotificationChannels", "success");
    }

    @Override
    public void onFailure(BaseResponse failure) {
        Log.e("NotificationChannels", "Error:" + failure.getMessage());
    }
});

๐Ÿงช Testing & Debugging

SDK Test Apps

  • Android Test App: Available in SDK repository
  • iOS Test App: Available in SDK repository
  • Test Features: Push notifications, deep links, analytics, conversions

Debug Commands

# Android - Enable SDK Logging
Appgain.enableLog();

# iOS - Enable SDK Logging
Appgain.enableLogging()

# Check SDK Version
Appgain.getSDKVersion()

Common Issues & Solutions

Push Notifications Not Working

  • Verify Firebase configuration
  • Check APNs certificate (iOS)
  • Ensure proper permissions
  • Test with SDK test app
  • Verify URL scheme configuration
  • Check fallback URLs
  • Test with different scenarios
  • Validate link creation

Analytics Not Tracking

  • Check network connectivity
  • Verify API key configuration
  • Enable debug logging
  • Check user permissions

๐Ÿš€ Deployment Process

Pre-Release Checklist

  • SDK integration tested
  • Push notifications working
  • Deep links functional
  • Analytics tracking properly
  • Battery optimization configured
  • App store guidelines compliance

Release Process

  1. Code Review: Pull request review and approval
  2. Testing: Comprehensive testing on real devices
  3. Build: Create production builds
  4. App Store Submission: Submit to App Store and Google Play
  5. Monitoring: Monitor crash reports and analytics

Post-Release Monitoring

  • Crash Reports: Monitor app stability
  • Analytics: Track user engagement
  • Push Delivery: Monitor notification delivery rates
  • Performance: Monitor app performance metrics

๐Ÿ“š Learning Path

Week 1: Foundation

  • Complete mobile development fundamentals
  • Set up development environment
  • Understand Appgain Mobile SDK architecture
  • Learn platform-specific development

Week 2: SDK Integration

  • Integrate Android SDK
  • Integrate iOS SDK
  • Set up push notifications
  • Configure deep linking

Week 3: Advanced Features

  • Implement custom push receivers
  • Set up analytics tracking
  • Create smart deep links
  • Optimize app performance

Week 4: Production

  • Deploy to app stores
  • Monitor and maintain
  • Optimize for scale
  • Share knowledge with team

๐ŸŽฅ Video Resources & Tutorials

Mobile SDK Training Videos

Appgain SDK Training Video 1

Appgain SDK Training Video 2

SDK Handover

SDK Test Apps

Web SDK

๐ŸŽฏ Quick Navigation


๐Ÿ“ฑ Mobile Engineers create native and cross-platform mobile applications that deliver exceptional user experiences on iOS and Android devices.

โ† Back to Home | โ† Previous: Common Knowledge

Ask Chehab GPT