logdrop_flutter_sdk 3.0.4
logdrop_flutter_sdk: ^3.0.4 copied to clipboard
LogDrop Fluter SDK
LogDrop Flutter SDK #
Installation #
Minimum Requirements:
- Android 6.0
- iOS 14.0
flutter pub add logdrop_flutter_sdk
Integration #
Android #
Edit your android/build.gradle
buildscript {
repositories {
google()
mavenCentral()
maven(uri("https://artifactory.logdrop.io/repository/logdrop-gradle-plugin/"))
}
dependencies {
classpath("io.logdrop.gradle:plugin:1.1.2")
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url "https://artifactory.logdrop.io/repository/android-logdrop-sdk/" }
maven { url "https://artifactory.logdrop.io/repository/logdrop-gradle-plugin/" }
}
}
Edit your android/app/build.gradle (App Level):
apply plugin: "io.logdrop.gradle.plugin"
or
plugins {
... // other plugins
id("io.logdrop.gradle.plugin")
}
android {
...
defaultConfig {
buildConfigField("String", "LOGDROP_BASE_URL", "YOUR_SERVER_URL")
buildConfigField("String", "LOGDROP_APP_ID", "YOUR_APP_ID")
buildConfigField("boolean", "LOGDROP_LOGCAT_ENABLED", "true")
}
}
Create a file named logdrop-services.json under the android/app folder.
{
"base_url": "https://server.logdrop.io",
"projects": {
"YOUR_APP_PACKAGE_NAME": {
"app_id": "YOUR_APP_ID"
}
}
}
Edit your YourApp.kt file in the Android module of your Flutter project as follows
import android.app.Application
import com.logdrop_flutter_sdk.LogDropFlutter
import org.json.JSONArray
class YourApp : Application() {
override fun onCreate() {
super.onCreate()
//Add this
LogDropFlutter.initLogDrop(
logcatEnabled = BuildConfig.LOGDROP_LOGCAT_ENABLED,
appId = BuildConfig.LOGDROP_APP_ID,
baseUrl = BuildConfig.LOGDROP_BASE_URL,
context = this.applicationContext
)
}
}
iOS #
Add the following keys to your Info.plist file:
<key>LogDropBaseUrl</key>
<string>YOUR_API_URL</string>
<key>LogDropAppId</key>
<string>YOUR_APP_ID</string>
<key>LogDropLoggingEnabled</key>
<true/>
Update AppDelegate.swift
import Flutter
import UIKit
import UserNotifications
import logdrop_flutter_sdk
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
UNUserNotificationCenter.current().delegate = self
let infoDict = Bundle.main.infoDictionary
let appId = infoDict?["LogDropAppId"] as? String ?? ""
let baseUrl = infoDict?["LogDropBaseUrl"] as? String ?? ""
let loggingEnabled = infoDict?["LogDropLoggingEnabled"] as? Bool ?? true
LogDropFlutter.initialize(
appId: appId,
baseUrl: baseUrl,
loggingEnabled: loggingEnabled,
pushAppGroupSuiteName: "group.your.app.identifier" // Optional: required for rich push in extensions
)
application.registerForRemoteNotifications()
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
LogDropFlutter.onNewApnsToken(apnsToken: deviceToken)
}
override func application(
_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error
) {
print("Failed to register for remote notifications: \(error)")
}
override func application(
_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void
) {
LogDropFlutter.onRemoteMessageReceived(userInfo: userInfo)
completionHandler(.newData)
}
}
Rich push App Group #
LogDrop rich-push popup and internal-browser actions received by a Notification Service Extension must be shared with the main application:
- Add a Notification Service Extension target.
- Enable the App Groups capability on both
Runnerand the extension with the same identifier, such asgroup.your.app.identifier. - Pass that exact identifier to
pushAppGroupSuiteNamein both the main app initialization above and the extension configuration below. - Add LogDrop to the extension target in
ios/Podfile, then runpod install:
target 'LogDropNotificationServiceExtension' do
use_frameworks!
pod 'LogDrop', '2.1.8'
end
Use LogDrop's service-extension base class:
import LogDropSDK
final class NotificationService: LogDropNotificationServiceExtension {
override func logDropConfiguration() -> LogDropConfig? {
LogDropConfig.Builder()
.setBaseUrl("YOUR_BASE_URL")
.setPushAppGroupSuiteName("group.your.app.identifier")
.build()
}
}
The suite name must match exactly across the app configuration, extension configuration, and both targets' App Group entitlements.
Usage #
Initialize LogDrop in your main() function:
import 'package:flutter/material.dart';
import 'package:logdrop_flutter_sdk/logdrop_flutter.dart';
import 'package:your_app/main_app.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await LogDropFlutter.init();
runApp(const MyApp());
}
Logging Messages #
You can use the logging functions to send logs to the native side.
Each log function requires a tag and a message, and optionally a LogFlow object.
void main() {
// Log an error
LogDrop.logError(
tag: "LoginScreen",
message: "Login failed due to invalid credentials",
);
// Log a debug message
LogDrop.logDebug(
tag: "ApiClient",
message: "Request sent to /users endpoint",
);
// Log an info message
LogDrop.logInfo(
tag: "PaymentFlow",
message: "Payment initialized successfully",
);
// Log a warning message
LogDrop.logWarning(
tag: "ProfileUpdate",
message: "Profile picture is too large, compressing...",
);
// Using LogFlow
final flow = LogFlow(
name: "Checkout",
id: "flow-123",
customAttributes: {
"cartId": "cart-456",
"userId": "user-789",
},
);
LogDrop.logInfo(
tag: "CheckoutScreen",
message: "User started checkout flow",
logFlow: flow,
);
}
Push Notifications #
⚠️ Before using these functions, make sure you have requested notification permission on the device (both Android and iOS require explicit permission).
These methods should be called inside the push notification callbacks of your app:
import 'package:logdrop_flutter_sdk/logdropsdk.dart';
Future<void> setupPushNotifications() async {
// 1. Request notification permission from the user
// (example for FlutterFire Messaging, adapt to your push SDK)
await FirebaseMessaging.instance.requestPermission();
// 2. Listen for new push tokens (FCM)
FirebaseMessaging.instance.onTokenRefresh.listen((token) {
LogDrop.onNewFcmPushToken(token);
});
// 3. Handle incoming push notifications
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
final data = message.data.map((k, v) => MapEntry(k, v.toString()));
if (await LogDrop.isLogDropPush(data)) {
LogDrop.onRemoteMessageReceived(data);
}
});
// (For Huawei devices, use HMS push SDK and call onNewHmsPushToken)
}
Background Messages
For handling push notifications when the app is in the background or terminated, register a background message handler:
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
final data = message.data.map((k, v) => MapEntry(k, v.toString()));
if (await LogDrop.isLogDropPush(data)) {
LogDrop.onRemoteMessageReceived(data);
}
}
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await LogDropFlutter.init();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(
_firebaseMessagingBackgroundHandler,
);
runApp(const MyApp());
}
Android: LogDrop pushes use data-only FCM payloads. Always forward the message
datato LogDrop so the SDK can display notifications and trackpush_receivedandpush_clickedwithout duplicates.
Checking LogDrop Push & Showing Rich Push Popup
// Check if a notification is from LogDrop
final isLogDrop = await LogDrop.isLogDropPush(data);
// Show any pending rich-push popup (e.g. after app comes to foreground)
final result = await LogDrop.showPendingPushPopup();
// result: LogDropPopupShowResult.shown / .nothingToShow / .notInitialized
iOS APNs Registration (Fetch Logs)
If you are targeting iOS, silent push notifications for log retrieval require the APNs device token. Since APNs tokens are binary Data and handled natively by iOS, you must register the token inside your native AppDelegate.swift (see the iOS integration section above).
Deep Links #
Deep-link navigation in Flutter is handled by the application's routing layer. After the application receives a deep link, call the SDK's public method to track it:
import 'package:logdrop_flutter_sdk/logdropsdk.dart';
Future<void> handleDeepLink(Uri uri) async {
await LogDrop.trackDeepLink(uri.toString());
}
Built-in deep linking is enabled by default in Flutter 3.27 and later. If your application uses Flutter's routing for deep links, no additional native callback bridge is required. Call LogDrop.trackDeepLink after the application receives the link and navigates to the appropriate route.
Updating user #
void onUserLogin(String userId) {
// 4. When the user logs in or updates
LogDrop.userUpdate(userId);
}
Custom events #
Track an application-specific event with an optional JSON-compatible properties map. Event and property codes shown in the panel are managed by LogDrop.
await LogDrop.trackCustomEvent('purchase_completed', {
'coupon_code': 'SUMMER10',
'amount': 49.9,
'item_count': 2,
'is_first_order': true,
});
await LogDrop.trackCustomEvent('onboarding_completed');
Supported values are strings, numbers, booleans, null, nested maps, and lists.
Map keys must be strings. Convert DateTime instances to ISO-8601 strings before
passing them through the method channel:
await LogDrop.trackCustomEvent('product_viewed', {
'sku': 'LD-100',
'viewed_at': DateTime.now().toUtc().toIso8601String(),
'product': {'name': 'LogDrop Hoodie', 'price': 79.95},
'categories': ['merch', 'hoodies'],
'campaign': null,
});
Use stable event names and keep each property's type consistent. Do not place IDs or timestamps in an event name and do not reuse a LogDrop default event name. Reusing the same custom event name updates the same schema; changing the name creates a different custom event. If a property is later sent with another type, LogDrop keeps the event but marks a type conflict in the panel.
Limits and validation:
- Event and property names must not be empty and can contain up to 128 characters.
- One event can contain up to 100 top-level properties.
- The complete properties JSON can contain up to 16 KB in UTF-8.
- Property values must be JSON-compatible.
If validation fails, the native SDK rejects the complete event, logs the reason, and never silently truncates names, properties, or payloads. No event definition is required before tracking; the first valid event creates its schema in the LogDrop panel.
Custom user attributes #
Custom attributes can be used to target push notification segments. Setting attributes performs an additive upsert; attributes not included in the call are left unchanged.
await LogDrop.setCustomAttributes({
'plan': 'premium',
'country': 'TR',
});
await LogDrop.removeCustomAttribute('plan');
Attribute keys must match [A-Za-z0-9_-]+ and be at most 64 characters.
Values must be non-blank and at most 256 characters. A user can have at most 30
attributes. Invalid mutations are rejected as a whole by the native SDK.