📱 Мобильные SDK

Официальные SDK для iOS (Swift) и Android (Kotlin/Java) с полной поддержкой всех возможностей InstantBase

🎯 Что вы получите
  • Нативный SDK для каждой платформы с оптимальной производительностью
  • Автоматическое управление сессиями и идентификаторами устройств
  • Автосохранение событий при отсутствии сети
  • Поддержка пуш-уведомлений и глубокой интеграции с устройством
  • Готовые методы для отслеживания экранов, покупок, ошибок

📱 iOS SDK (Swift)

iOS 13.0+
Swift 5.5+

Установка

// В Xcode: File → Add Packages...
// Вставьте URL репозитория:
https://github.com/instantbase/ios-sdk.git

// Или добавьте в Package.swift
dependencies: [
    .package(url: "https://github.com/instantbase/ios-sdk.git", from: "1.0.0")
]
# Podfile
platform :ios, '13.0'
use_frameworks!

target 'YourApp' do
  pod 'InstantBaseSDK', '~> 1.0.0'
end
# Скачайте последнюю версию SDK с GitHub
# Добавьте InstantBaseSDK.xcframework в проект
# В Build Settings → Other Linker Flags добавьте -ObjC

Инициализация

import UIKit
import InstantBaseSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Базовая инициализация
        InstantBase.configure(
            apiKey: "your_api_key",
            options: Configuration(
                environment: .production,
                debug: true,
                autoTrackScreen: true,
                autoTrackAppLifecycle: true,
                sessionTimeout: 30 // минут
            )
        )
        
        // Установка идентификатора пользователя (если есть)
        if let userId = getCurrentUserId() {
            InstantBase.shared.identify(userId: userId)
        }
        
        return true
    }
}

Конфигурация

Configuration Параметры конфигурации
Параметр Тип По умолчанию Описание
environment Environment .production .production или .development
debug Bool false Логирование в консоль
autoTrackScreen Bool true Автоотслеживание экранов
autoTrackAppLifecycle Bool true Отслеживание app_open/app_close
sessionTimeout Int 30 Минут неактивности для новой сессии
maxBatchSize Int 20 Размер батча для отправки
flushInterval Int 10 Интервал отправки (секунды)
let config = Configuration(
    environment: .development,
    debug: true,
    autoTrackScreen: true,
    autoTrackAppLifecycle: true,
    sessionTimeout: 15,
    maxBatchSize: 50,
    flushInterval: 5
)

InstantBase.configure(apiKey: "test_key", options: config)

Основные методы

track() Отправка события
import InstantBaseSDK

// Простое событие
InstantBase.shared.track(
    event: "button_tap",
    properties: [
        "button_id": "signup",
        "screen": "welcome"
    ]
)

// Событие с пользователем
InstantBase.shared.track(
    event: "purchase",
    properties: [
        "user_id": "user_123",
        "order_id": "ORD-001",
        "amount": 1499.99
    ],
    metadata: [
        "is_order": true,
        "funnel_sales_step": 4
    ]
)

// Анонимный пользователь (автоматически)
InstantBase.shared.track(
    event: "page_view",
    properties: [
        "page": "products"
    ]
)
identify() Идентификация пользователя
// При авторизации
InstantBase.shared.identify(
    userId: "user_123",
    traits: [
        "email": "user@example.com",
        "name": "Иван Петров",
        "plan": "premium"
    ]
)

// С метаданными атрибутов
InstantBase.shared.identify(
    userId: "user_123",
    traits: [
        "email": "user@example.com",
        "plan": "premium"
    ],
    metadata: [
        "plan": [
            "attribute_display_name": "Тариф",
            "attribute_category": "Подписка"
        ]
    ]
)
trackScreen() Отслеживание экрана
// Ручное отслеживание
InstantBase.shared.trackScreen(
    screenName: "ProductDetailViewController",
    screenTitle: "Товар",
    properties: [
        "product_id": "prod_123"
    ]
)

// Автоматически (если включено autoTrackScreen)
// SDK автоматически отслеживает появление ViewController'ов
alias() Связывание идентификаторов
// При входе в аккаунт
let anonymousId = InstantBase.shared.getAnonymousId()
InstantBase.shared.alias(previousId: anonymousId, newId: "user_123")
reset() Сброс пользователя
// При выходе из аккаунта
InstantBase.shared.reset()

// С новым anonymous_id
InstantBase.shared.reset(generateNewId: true)

Отслеживание покупок (StoreKit)

import StoreKit
import InstantBaseSDK

extension StoreKitManager {
    
    func handlePurchase(transaction: SKPaymentTransaction) {
        let product = transaction.payment.productIdentifier
        
        // Отслеживаем покупку
        InstantBase.shared.track(
            event: "iap_purchase",
            properties: [
                "product_id": product,
                "price": getPrice(for: product),
                "currency": "RUB"
            ],
            metadata: [
                "is_order": true,
                "event_display_name": "Покупка в приложении"
            ]
        )
        
        // Обновляем атрибуты пользователя
        InstantBase.shared.identify(traits: [
            "last_purchase": Date().ISO8601Format(),
            "total_purchases": getUserPurchaseCount()
        ])
    }
}

Отслеживание пуш-уведомлений

import UserNotifications
import InstantBaseSDK

class NotificationService: UNNotificationServiceExtension {
    
    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        
        // Пуш получен
        InstantBase.shared.track(
            event: "push_received",
            properties: [
                "campaign": request.identifier,
                "category": request.content.categoryIdentifier
            ]
        )
        
        // ... обработка пуша
    }
}

// В AppDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {
    
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        
        // Пуш открыт
        InstantBase.shared.track(
            event: "push_opened",
            properties: [
                "campaign": response.notification.request.identifier,
                "action": response.actionIdentifier
            ]
        )
        
        completionHandler()
    }
}

Отслеживание ошибок

import InstantBaseSDK

// Глобальный обработчик ошибок
NSSetUncaughtExceptionHandler { exception in
    InstantBase.shared.track(
        event: "crash",
        properties: [
            "reason": exception.reason ?? "unknown",
            "name": exception.name.rawValue,
            "stack": exception.callStackSymbols.joined(separator: "\n")
        ],
        metadata: [
            "event_display_name": "Краш",
            "event_color": "#dc3545"
        ]
    )
}

// Отслеживание ошибок API
URLSession.shared.dataTask(with: url) { data, response, error in
    if let error = error {
        InstantBase.shared.track(
            event: "network_error",
            properties: [
                "error": error.localizedDescription,
                "url": url.absoluteString
            ]
        )
    }
}.resume()

Интеграция с SwiftUI

import SwiftUI
import InstantBaseSDK

struct ProductView: View {
    let productId: String
    let productName: String
    
    @State private var appeared = false
    
    var body: some View {
        VStack {
            Text(productName)
            Button("Купить") {
                purchase()
            }
        }
        .onAppear {
            if !appeared {
                // Отслеживаем просмотр
                InstantBase.shared.trackScreen(
                    screenName: "ProductView",
                    screenTitle: productName,
                    properties: ["product_id": productId]
                )
                appeared = true
            }
        }
    }
    
    func purchase() {
        InstantBase.shared.track(
            event: "purchase",
            properties: [
                "product_id": productId,
                "product_name": productName
            ],
            metadata: ["is_order": true]
        )
    }
}

Оффлайн-режим

// SDK автоматически сохраняет события при отсутствии сети
// и отправляет их при восстановлении соединения

// Ручное управление
InstantBase.shared.setOffline(true)  // принудительно в оффлайн
InstantBase.shared.setOffline(false) // выход из оффлайна

// Проверка статуса
let isOffline = InstantBase.shared.isOffline
let unsentCount = InstantBase.shared.unsentEventsCount

// Принудительная отправка
InstantBase.shared.flush()

🤖 Android SDK (Kotlin/Java)

Android 5.0+ (API 21+)
Kotlin 1.5+

Установка

// build.gradle (project)
allprojects {
    repositories {
        mavenCentral()
        maven { url 'https://jitpack.io' }
    }
}

// build.gradle (app)
dependencies {
    implementation 'com.github.instantbase:android-sdk:1.0.0'
    implementation 'com.google.code.gson:gson:2.9.0'
    implementation 'com.squareup.okhttp3:okhttp:4.10.0'
}
<dependency>
    <groupId>com.github.instantbase</groupId>
    <artifactId>android-sdk</artifactId>
    <version>1.0.0</version>
</dependency>
# Скачайте AAR файл с GitHub
# Поместите в app/libs/
# Добавьте в build.gradle:
implementation files('libs/instantbase-sdk.aar')

Инициализация

import com.instantbase.InstantBase
import com.instantbase.Configuration

class MyApp : Application() {
    
    override fun onCreate() {
        super.onCreate()
        
        // Базовая инициализация
        InstantBase.initialize(
            context = this,
            apiKey = "your_api_key",
            configuration = Configuration(
                environment = Environment.PRODUCTION,
                debug = BuildConfig.DEBUG,
                autoTrackScreen = true,
                autoTrackAppLifecycle = true,
                sessionTimeout = 30,
                maxBatchSize = 20,
                flushInterval = 10
            )
        )
        
        // Установка идентификатора пользователя
        val userId = getCurrentUserId()
        if (userId != null) {
            InstantBase.getInstance().identify(userId)
        }
    }
}

Конфигурация

Configuration Параметры конфигурации
Параметр Тип По умолчанию Описание
environment Environment PRODUCTION PRODUCTION или DEVELOPMENT
debug Boolean false Логирование в Logcat
autoTrackScreen Boolean true Автоотслеживание экранов
autoTrackAppLifecycle Boolean true Отслеживание app_open/app_close
sessionTimeout Int 30 Минут неактивности для новой сессии
maxBatchSize Int 20 Размер батча для отправки
flushInterval Int 10 Интервал отправки (секунды)
val config = Configuration(
    environment = Environment.DEVELOPMENT,
    debug = true,
    autoTrackScreen = true,
    autoTrackAppLifecycle = true,
    sessionTimeout = 15,
    maxBatchSize = 50,
    flushInterval = 5
)

InstantBase.initialize(context = this, apiKey = "test_key", configuration = config)

Основные методы

track() Отправка события
import com.instantbase.InstantBase

// Kotlin
val ib = InstantBase.getInstance()

// Простое событие
ib.track(
    event = "button_tap",
    properties = mapOf(
        "button_id" to "signup",
        "screen" to "welcome"
    )
)

// Событие с метаданными
ib.track(
    event = "purchase",
    properties = mapOf(
        "user_id" to "user_123",
        "order_id" to "ORD-001",
        "amount" to 1499.99
    ),
    metadata = mapOf(
        "is_order" to true,
        "funnel_sales_step" to 4
    )
)

// Java
InstantBase.getInstance().track(
    "button_tap",
    new HashMap() {{
        put("button_id", "signup");
        put("screen", "welcome");
    }},
    null
);
identify() Идентификация пользователя
// Kotlin
ib.identify(
    userId = "user_123",
    traits = mapOf(
        "email" to "user@example.com",
        "name" to "Иван Петров",
        "plan" to "premium"
    )
)

// С метаданными
ib.identify(
    userId = "user_123",
    traits = mapOf(
        "email" to "user@example.com",
        "plan" to "premium"
    ),
    metadata = mapOf(
        "plan" to mapOf(
            "attribute_display_name" to "Тариф",
            "attribute_category" to "Подписка"
        )
    )
)

// Java
InstantBase.getInstance().identify(
    "user_123",
    new HashMap() {{
        put("email", "user@example.com");
        put("name", "Иван Петров");
    }},
    null
);
trackScreen() Отслеживание экрана
// Ручное отслеживание
ib.trackScreen(
    screenName = "ProductActivity",
    screenTitle = "Товар",
    properties = mapOf(
        "product_id" to "prod_123"
    )
)

// В Activity
override fun onResume() {
    super.onResume()
    InstantBase.getInstance().trackScreen(
        screenName = this::class.simpleName ?: "Unknown",
        screenTitle = title.toString()
    )
}
alias() Связывание идентификаторов
// При входе в аккаунт
val anonymousId = ib.getAnonymousId()
ib.alias(anonymousId, "user_123")
reset() Сброс пользователя
// При выходе
ib.reset()

// С новым anonymous_id
ib.reset(generateNewId = true)

Отслеживание покупок (Google Play Billing)

import com.android.billingclient.api.*
import com.instantbase.InstantBase

class BillingManager(private val context: Context) : PurchasesUpdatedListener {
    
    private val ib = InstantBase.getInstance()
    
    override fun onPurchasesUpdated(
        billingResult: BillingResult,
        purchases: MutableList?
    ) {
        if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
            for (purchase in purchases) {
                handlePurchase(purchase)
            }
        }
    }
    
    private fun handlePurchase(purchase: Purchase) {
        // Отслеживаем покупку
        ib.track(
            event = "iap_purchase",
            properties = mapOf(
                "product_id" to purchase.products.first(),
                "purchase_token" to purchase.purchaseToken,
                "order_id" to purchase.orderId
            ),
            metadata = mapOf(
                "is_order" to true,
                "event_display_name" to "Покупка в приложении"
            )
        )
        
        // Обновляем атрибуты
        ib.identify(traits = mapOf(
            "last_purchase" to System.currentTimeMillis(),
            "total_purchases" to getPurchaseCount()
        ))
    }
}

Отслеживание пуш-уведомлений (Firebase)

import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.instantbase.InstantBase

class MyFirebaseMessagingService : FirebaseMessagingService() {
    
    private val ib by lazy { InstantBase.getInstance() }
    
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        
        // Пуш получен
        ib.track(
            event = "push_received",
            properties = mapOf(
                "campaign" to remoteMessage.messageId,
                "title" to (remoteMessage.notification?.title ?: ""),
                "category" to (remoteMessage.notification?.channelId ?: "")
            )
        )
        
        // Показать уведомление...
    }
    
    override fun onNewToken(token: String) {
        super.onNewToken(token)
        
        // Обновляем FCM токен в профиле
        ib.identify(traits = mapOf(
            "fcm_token" to token,
            "push_enabled" to true
        ))
    }
}

// В Activity при клике на уведомление
Intent intent = getIntent();
if (intent.getExtras() != null) {
    InstantBase.getInstance().track(
        "push_opened",
        mapOf("campaign" to intent.getStringExtra("message_id")),
        null
    );
}

Отслеживание ошибок

import com.instantbase.InstantBase
import java.lang.Thread

class CustomExceptionHandler : Thread.UncaughtExceptionHandler {
    
    private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
    private val ib = InstantBase.getInstance()
    
    override fun uncaughtException(t: Thread, e: Throwable) {
        // Отслеживаем краш
        ib.track(
            event = "crash",
            properties = mapOf(
                "exception" to e.javaClass.simpleName,
                "message" to (e.message ?: ""),
                "stacktrace" to e.stackTraceToString()
            ),
            metadata = mapOf(
                "event_display_name" to "Краш",
                "event_color" to "#dc3545"
            )
        )
        
        // Принудительная отправка
        ib.flush()
        
        // Вызываем стандартный обработчик
        defaultHandler?.uncaughtException(t, e)
    }
}

// В Application.onCreate()
Thread.setDefaultUncaughtExceptionHandler(CustomExceptionHandler())

Интеграция с Jetpack Compose

import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import com.instantbase.InstantBase

@Composable
fun TrackScreen(
    screenName: String,
    screenTitle: String,
    properties: Map? = null
) {
    val lifecycleOwner = LocalLifecycleOwner.current
    val ib = InstantBase.getInstance()
    
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_RESUME) {
                ib.trackScreen(screenName, screenTitle, properties)
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}

@Composable
fun ProductScreen(productId: String, productName: String) {
    TrackScreen(
        screenName = "ProductScreen",
        screenTitle = productName,
        properties = mapOf("product_id" to productId)
    )
    
    Column {
        Text(productName)
        Button(onClick = { 
            InstantBase.getInstance().track(
                event = "purchase",
                properties = mapOf(
                    "product_id" to productId,
                    "product_name" to productName
                ),
                metadata = mapOf("is_order" to true)
            )
        }) {
            Text("Купить")
        }
    }
}

Оффлайн-режим

// SDK использует Room для локального хранения
// События автоматически сохраняются при отсутствии сети

// Проверка статуса
val isOffline = ib.isOffline
val unsentCount = ib.getUnsentEventsCount()

// Принудительная отправка
ib.flush()

// Ручное управление
ib.setOffline(true)  // перейти в оффлайн
ib.setOffline(false) // выйти из оффлайна

// Слушатель сети
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerNetworkCallback(
    NetworkRequest.Builder().build(),
    object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            ib.setOffline(false)
            ib.flush()
        }
        
        override fun onLost(network: Network) {
            ib.setOffline(true)
        }
    }
)

Общие возможности

📱 iOS

  • ✅ Swift Package Manager
  • ✅ CocoaPods
  • ✅ SwiftUI интеграция
  • ✅ StoreKit поддержка
  • ✅ UserNotifications
  • ✅ Background fetch
  • ✅ iCloud sync

🤖 Android

  • ✅ Gradle / Maven
  • ✅ Kotlin coroutines
  • ✅ Jetpack Compose
  • ✅ Google Play Billing
  • ✅ Firebase Cloud Messaging
  • ✅ WorkManager
  • ✅ Room persistence

Рекомендации для мобильных приложений

  • Включайте autoTrackScreen — это даст понимание популярности экранов
  • Отслеживайте версии приложения — чтобы видеть влияние обновлений
  • Используйте оффлайн-режим — события не потеряются при отсутствии сети
  • Настраивайте батчинг — для экономии трафика и батареи
  • Отслеживайте краши — критически важно для качества
  • Используйте пуш-трекинг — чтобы оценивать эффективность кампаний
⚠️ ВАЖНО: Для работы в продакшене обязательно используйте правильные API-ключи. В development используйте тестовые ключи. Никогда не храните ключи в коде — используйте secure storage или remote config.

Тестирование

// iOS - XCTest
func testTracking() {
    let expectation = expectation(description: "Event tracked")
    
    InstantBase.shared.track(event: "test_event") { result in
        switch result {
        case .success:
            expectation.fulfill()
        case .failure(let error):
            XCTFail("Failed: \(error)")
        }
    }
    
    wait(for: [expectation], timeout: 5.0)
}

// Android - JUnit
@Test
fun testTracking() = runBlockingTest {
    val job = launch {
        InstantBase.getInstance().track(
            event = "test_event",
            properties = mapOf("test" to true)
        )
    }
    
    job.join()
    // Проверяем, что событие сохранилось в БД
    assertTrue(InstantBase.getInstance().getUnsentEventsCount() > 0)
}

Что дальше?

📱 Примеры для игр

Аналитика для мобильных игр

Перейти →

📊 Знакомство с дашбордом

Как работать с полученными данными

Перейти →

Нужна помощь с мобильной интеграцией?

Напишите нам, и мы поможем настроить SDK под ваше приложение

support@instantbase.online Telegram