Pulse Monitoring for Flutter

Plugin Flutter untuk monitoring sesi, crash, error, HTTP, screen, event, dan informasi in-app dari dashboard Pulse. Versi plugin 0.1.6 tersedia di pub.dev. Plugin menggunakan SDK native Android dan iOS 0.1.1.

Pemilik: Idris — idris3097@gmail.com.

Tentang Pulse

Pulse adalah dashboard untuk memantau dan mengelola aplikasi mobile Android dan iOS dari satu tempat. Plugin ini menghubungkan aplikasi Flutter Anda ke dashboard tersebut.

Di dashboard Pulse Contoh
Monitoring Crash-free sessions, error dan crash per issue, request HTTP, perangkat aktif, pemakaian fitur
Informasi in-app Maintenance, popup fitur baru, dan banner per aplikasi, platform, dan versi build
Push & distribusi Kirim notifikasi FCM ke aplikasi, topic, atau token; bagikan build ke tester Firebase App Distribution
Statistik toko Download dan instalasi dari Google Play Console dan App Store Connect
Versi aplikasi Riwayat rilis dan force update

Mulai dalam tiga langkah:

  1. Daftar dan buat workspace.
  2. Hubungkan project Firebase di Pengaturan → Kredensial, lalu salin workspace key dari Pengaturan → Workspace.
  3. Pasang plugin ini dan panggil PulseMonitoring.start() dengan workspace key tersebut (lihat Instalasi dan Inisialisasi).

Panduan lengkap integrasi SDK: pulse-mobile-monitoring.vercel.app/docs.

SDK Pulse lainnya

Pulse juga tersedia untuk aplikasi native. Gunakan salah satu, sesuai teknologi aplikasi Anda:

Platform Package Instalasi
Flutter pulse_monitoring di pub.dev, versi 0.1.6 flutter pub add pulse_monitoring
Android (Kotlin/Java) io.github.mhmadidris:pulse-monitoring di Maven Central, versi 0.1.2 implementation("io.github.mhmadidris:pulse-monitoring:0.1.2")
iOS (Swift) PulseMonitoring 0.1.2, XCFramework melalui CocoaPods pod 'PulseMonitoring', :podspec => 'https://pulse-mobile-monitoring.vercel.app/sdk/ios/0.1.2/PulseMonitoring.podspec'

Aplikasi Flutter cukup memakai plugin ini; SDK Android dan iOS sudah dipasang otomatis oleh plugin.

Platform yang didukung

Platform Dukungan Persyaratan dan batasan
Android Ya Android 8.0 / API 26+, compileSdk 37+, Java 17. Perangkat dan emulator.
iOS Ya iOS 15+, CocoaPods dan Swift Package Manager. Perangkat arm64; simulator arm64 dan x86_64.
Web Belum Tidak ada implementasi monitoring web.
macOS, Windows, Linux Belum Tidak ada implementasi monitoring desktop.

Persyaratan Flutter: Flutter 3.41+ dan Dart >=3.11.0 <4.0.0. Pada platform yang belum didukung, start() tidak mengaktifkan monitoring.

Untuk compileSdk 37, gunakan Android Gradle Plugin 9.1.1+ dan Gradle yang kompatibel dengan versi AGP aplikasi. Lihat tabel kompatibilitas Android. Untuk iOS, gunakan Xcode yang kompatibel dengan Flutter dan binary Swift yang disertakan. Build simulator telah diverifikasi dengan Xcode 27.1. Plugin mendukung Swift Package Manager mulai versi 0.1.3, sekaligus mempertahankan dukungan CocoaPods untuk aplikasi yang belum bermigrasi.

Fitur dan cara pengumpulan

Fitur Cara penggunaan
Sesi dan metadata perangkat/aplikasi Otomatis setelah start().
Crash Android Uncaught JVM exceptions; crash NDK/sinyal belum ditangkap.
Crash iOS Diagnostics MetricKit; pengiriman mengikuti jadwal sistem Apple.
Error Flutter/Dart Teruskan melalui recordError() atau handler error aplikasi.
Metrik HTTP Dart Panggil recordHttp() dari HTTP client aplikasi. Tidak ada interceptor Dart otomatis.
Screen Pasang PulseNavigatorObserver pada Navigator, atau panggil trackScreen() secara manual.
Event bisnis Panggil trackEvent().
Maintenance Dengarkan maintenance dan tampilkan chip; detail dibuka dengan showMaintenance().
Informasi new feature/banner Feed dan presentasi informasi ditangani SDK native.
Push informasi Opsional; teruskan data FCM melalui handlePush(). Firebase dikonfigurasi aplikasi.
Notifikasi dashboard Kenali dengan isPulseNotification(), tap melalui handleNotificationTap() dan notificationLink().

UI kustom dan force update: mulai 0.1.4, aktifkan customInformation: true. SDK menyediakan feed lengkap dan requiredUpdate, menjalankan pemeriksaan versi, serta menyimpan statusnya. Aplikasi menggambar komponen UI; tidak perlu membuat HTTP client, cache, timer, atau subscription topik Pulse sendiri. Mode default mempertahankan popup native yang sudah ada.

1. Instalasi

Tambahkan dependency dari pub.dev:

dependencies:
  pulse_monitoring: ^0.1.6
flutter pub get

Pada aplikasi iOS yang menggunakan CocoaPods:

cd ios
pod install
cd ..

Flutter mendaftarkan plugin secara otomatis. Tidak perlu menambahkan SDK manual ke Gradle aplikasi, Podfile, MainActivity, atau AppDelegate. Untuk CocoaPods, folder ios/.symlinks/plugins/pulse_monitoring dikelola Flutter; jangan diedit atau dimasukkan ke Git.

Pada aplikasi yang mengaktifkan SwiftPM, Flutter memilih manifest plugin secara otomatis. Tidak perlu menambahkan package plugin secara manual melalui Xcode. Flutter dapat tetap menggunakan CocoaPods untuk plugin lain yang belum mendukung SwiftPM. Ikuti panduan SwiftPM Flutter untuk pengaturan aplikasi Anda.

Android mengambil dependency native dari Maven Central. Package Flutter membawa XCFramework iOS, sehingga pemasangan tidak memerlukan akses repository GitHub.

2. Inisialisasi

Ambil workspace key dari dashboard Pulse → Pengaturan → Workspace. Pastikan aplikasi terdaftar dengan package/bundle ID dan platform yang sesuai.

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:pulse_monitoring/pulse_monitoring.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Jika menggunakan Firebase, inisialisasikan Firebase terlebih dahulu.
  await PulseMonitoring.start(
    workspaceKey: const String.fromEnvironment('PULSE_WORKSPACE_KEY'),
    debug: kDebugMode,
    autoMaintenancePopups: false,
  );

  runApp(MaterialApp(
    navigatorObservers: [PulseNavigatorObserver()],
    home: const Scaffold(body: Center(child: Text('Home'))),
  ));
}
flutter run --dart-define=PULSE_WORKSPACE_KEY=pk_workspace_anda

Panggil start() sekali di main isolate, setelah Flutter binding siap dan sebelum mengirim event atau identitas user. Key kosong menonaktifkan inisialisasi; pastikan konfigurasi build production menyediakan key. Pelaporan sebelum SDK aktif diabaikan. await start() menunggu inisialisasi bridge, bukan konfirmasi data diterima server.

Opsi start() Default Kegunaan
workspaceKey Wajib Public workspace key dari dashboard.
baseUrl https://pulse-api-mobile.vercel.app/api/v1 Endpoint API lengkap, termasuk /api/v1, untuk server sendiri.
debug false Log diagnostik SDK; aktifkan saat pengembangan atau troubleshooting.
customInformation false Aktifkan controller Flutter dan pemeriksaan force update; matikan popup native otomatis.
autoMaintenancePopups false Aktifkan hanya jika ingin dialog maintenance otomatis.

Untuk dev dan production, gunakan workspace key serta endpoint yang sesuai dengan lingkungan masing-masing. --dart-define bukan penyimpanan secret; jangan masukkan credential admin, private key, atau token server ke aplikasi.

UI informasi kustom

Cukup public workspace key; alamat hosted Pulse sudah menjadi default:

await PulseMonitoring.start(
  workspaceKey: const String.fromEnvironment('PULSE_WORKSPACE_KEY'),
  customInformation: true,
);
final information = PulseMonitoring.information;

Controller tersedia setelah await start() pada Android/iOS. Jika inisialisasi atau platform tidak tersedia, nilainya dapat null. Dengarkan controller dengan ListenableBuilder atau addListener() dan render:

State/API Perilaku UI aplikasi
maintenance Chip persisten; ketuk untuk detail, tanpa modal otomatis.
banners Banner inline; dismissBanner(item) menyembunyikan selama proses berjalan.
nextFeature Dialog/carousel; panggil markSeen(item) setelah ditampilkan, sekali per revisi.
requiredUpdate Bottom sheet wajib; isDismissible: false, enableDrag: false, dan PopScope(canPop: false).
refresh() Refresh feed native dan versi, misalnya pull-to-refresh.

PulseInformationItem membawa halaman, gambar, CTA, prioritas, jadwal, dan revisi. PulseRequiredUpdate membawa versi, build, catatan rilis, dan URL toko. Aplikasi membuka storeUrl dan tetap mempertahankan sheet saat kembali dari toko sampai requiredUpdate null. Dahulukan force update dari pengumuman fitur; jangan menganggap berhasil membuka toko berarti aplikasi telah diperbarui.

SDK native tetap mengelola feed, cache informasi, targeting, expiry dan topik push. Controller Flutter memeriksa versi saat start, foreground, push dan setiap menit selama foreground, menyimpan kewajiban update per workspace/package/platform/build, dan menyimpan revisi fitur yang sudah dilihat. Kegagalan jaringan tidak menghapus update wajib yang sudah diketahui. Instalasi baru tanpa hasil cek sebelumnya belum dapat mengetahui kewajiban update saat offline; pembatasan operasi penting juga perlu ditegakkan server. Tidak ada dependency Firebase Dart baru; teruskan push melalui PulseMonitoring.handlePush(message.data) dari aplikasi.

Penarikan notifikasi (0.1.5+)

Backend Pulse dapat mengirim kontrol data-only type=information, action=retract, information_id, dan retired_revision. Kontrol ini tidak memiliki alert atau suara. SDK baru berlangganan topik kapabilitas pulse.<package>.<platform>.retract_v1 agar aplikasi lama tidak menerima kontrol yang belum dikenali. Sebelum menampilkan notifikasi lokal, teruskan data di callback FCM background:

@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
  if (await PulseMonitoring.handleBackgroundPush(message.data)) return;
  // Penanganan notifikasi aplikasi lainnya.
}

RemoteMessage dan Firebase berasal dari dependency Firebase aplikasi. Handler ini dapat berjalan sebelum PulseMonitoring.start() dan tidak meminta workspace key lagi. Gunakan juga sebelum penanganan foreground; handlePush() mengenali kontrol yang sama untuk alur foreground biasa. Jangan menampilkan notifikasi lokal untuk kontrol yang sudah ditangani.

Pada customInformation: true, bridge native menyaring revisi cache yang sudah ditarik dan controller melakukan rekonsiliasi notifikasi saat start, foreground, dan refresh. SDK hanya membersihkan notifikasi yang dipastikan tidak aktif dari respons feed valid, serta tidak menyamakan kegagalan API dengan feed kosong. Aplikasi perlu menutup sheet sendiri ketika item tidak lagi ada dalam controller. UI native lama/default dan paket standalone Android/iOS tetap memakai binary monitoring sebelumnya; jangan mengasumsikan popup native lama memiliki seluruh aturan penarikan UI kustom Flutter ini.

Android memakai tag pulse.info.<information_id>.<revision> dari backend dan NotificationManager.cancel(). Notifikasi Android lama tanpa tag tersebut tidak bisa dipetakan dengan aman. iOS mencocokkan payload information_id dan information_revision, lalu menghapus delivered/pending requests terkait. Notifikasi iOS legacy dengan ID yang cocok tetapi tanpa revisi diperlakukan sebagai revisi 0. Notifikasi lain dan revisi yang lebih baru tidak dihapus.

Penarikan merupakan best effort: perangkat offline, force-stop Android, atau pembatasan background/silent push iOS dapat menunda penarikan. Pada iOS, aktifkan Background Modes → Remote notifications, konfigurasi APNs/Firebase, dan teruskan handler background aplikasi. Backend menyimpan antrean penarikan terpisah agar penghapusan item tidak menghilangkan perintahnya. Data yang sudah dibaca pengguna tidak dapat dibatalkan. Tidak ada jaminan perangkat telah menghapus notifikasi hanya karena FCM menerima pesan.

3. Identitas user dan event

Sesudah login berhasil, gunakan ID internal yang stabil. Bersihkan identitas ketika logout agar event selanjutnya tidak terkait akun sebelumnya.

PulseMonitoring.setUser('user_123');

PulseMonitoring.trackEvent('document_sent', {
  'document_count': 2,
  'delivery_method': 'email',
  'success': true,
});

// Saat logout:
PulseMonitoring.setUser(null);

Gunakan nama event yang konsisten dan properties sederhana: string, angka, atau boolean. Hindari email, nama lengkap, isi dokumen, token, dan data sensitif lain.

Untuk screen, PulseNavigatorObserver membaca RouteSettings.name pada PageRoute. Pasang observer pada Navigator yang digunakan router aplikasi dan beri nama route. Jika router tidak memberikan nama, laporkan screen secara manual:

PulseMonitoring.trackScreen('document_detail');

Gunakan satu mekanisme pelaporan untuk screen yang sama agar tidak duplikat.

4. Error Flutter dan error yang ditangani aplikasi

Plugin tidak memasang handler error Flutter secara otomatis. Untuk error yang sudah ditangani, laporkan setelah aplikasi menentukan cara pemulihannya:

try {
  // Operasi aplikasi.
} catch (error, stack) {
  PulseMonitoring.recordError(error, stack);
  // Tampilkan pesan atau lakukan pemulihan sesuai alur aplikasi.
}

Untuk menghubungkan error global, pasang handler sekali setelah start(). Pertahankan handler yang sudah dipasang aplikasi atau Crashlytics:

import 'dart:ui' show PlatformDispatcher;
import 'package:flutter/foundation.dart' show FlutterError;
import 'package:pulse_monitoring/pulse_monitoring.dart';

void installPulseErrorHandlers() {
  final previousFlutterError = FlutterError.onError;
  FlutterError.onError = (details) {
    PulseMonitoring.recordError(details.exception, details.stack);
    if (previousFlutterError != null) {
      previousFlutterError(details);
    } else {
      FlutterError.presentError(details);
    }
  };

  final previousPlatformError = PlatformDispatcher.instance.onError;
  PlatformDispatcher.instance.onError = (error, stack) {
    PulseMonitoring.recordError(error, stack, fatal: true);
    return previousPlatformError?.call(error, stack) ?? false;
  };
}

Sesuaikan fatal dengan kebijakan error aplikasi. Jangan melaporkan exception yang sama berulang melalui catch, zone, dan handler global. Error dari isolate lain perlu diteruskan melalui mekanisme error isolate milik aplikasi. Lihat penanganan error Flutter.

5. Metrik HTTP

Tambahkan recordHttp() pada HTTP client/interceptor yang sudah dipakai aplikasi. Contoh berikut memakai package:http; tambahkan dependency http jika diperlukan.

import 'package:http/http.dart' as http;
import 'package:pulse_monitoring/pulse_monitoring.dart';

Future<http.Response> monitoredGet(http.Client client, Uri uri) async {
  final watch = Stopwatch()..start();
  try {
    final response = await client.get(uri).timeout(const Duration(seconds: 15));
    PulseMonitoring.recordHttp(
      method: 'GET',
      url: uri,
      status: response.statusCode,
      duration: watch.elapsed,
      responseBytes: response.bodyBytes.length,
    );
    return response;
  } catch (error) {
    PulseMonitoring.recordHttp(
      method: 'GET',
      url: uri,
      status: 0,
      duration: watch.elapsed,
      error: error.runtimeType.toString(),
    );
    rethrow;
  } finally {
    watch.stop();
  }
}

SDK membuang credentials URL, query string, dan fragment sebelum mengirim metrik melalui bridge. Path URL serta string error tetap perlu diperiksa oleh aplikasi; jangan memasukkan ID sensitif atau isi respons ke dalamnya. API recordHttp() tidak menerima request/response body atau header. Jangan membuat request monitoring kedua jika client aplikasi sudah melaporkan request yang sama. Gunakan kembali HTTP client milik aplikasi dan tutup client ketika service atau pemiliknya di-dispose, sehingga koneksi dapat dipakai kembali antar-request.

6. Maintenance chip

PulseMonitoring.maintenance menyediakan ValueNotifier<PulseMaintenance?>. Nilainya null ketika tidak ada maintenance aktif. Biarkan SDK mengelola notifier ini pada aplikasi production.

ValueListenableBuilder<PulseMaintenance?>(
  valueListenable: PulseMonitoring.maintenance,
  builder: (context, maintenance, child) {
    if (maintenance == null) return const SizedBox.shrink();
    return ActionChip(
      avatar: Icon(Icons.info_outline, color: maintenance.color),
      label: Text(maintenance.title),
      onPressed: PulseMonitoring.showMaintenance,
    );
  },
)

Import package:flutter/material.dart untuk widget di atas. Pertahankan autoMaintenancePopups: false jika memakai chip, sehingga maintenance tidak membuka dialog otomatis. Menekan chip membuka detail maintenance melalui SDK native. Untuk dialog otomatis, set autoMaintenancePopups: true saat inisialisasi.

7. Push informasi dengan Firebase (opsional)

Monitoring dasar tidak memerlukan Firebase. Untuk push, aplikasi perlu memasang serta mengonfigurasi firebase_core dan firebase_messaging, permission notifikasi, dan konfigurasi APNs/FCM sesuai platform. Setelah Firebase dan Pulse siap, teruskan pesan saat foreground dan saat notifikasi dibuka:

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:pulse_monitoring/pulse_monitoring.dart';

void routeMessage(RemoteMessage message) {
  if (PulseMonitoring.handlePush(message.data)) return;
  // Lanjutkan handler pesan aplikasi yang lain di sini.
}

Future<void> configurePulsePush() async {
  FirebaseMessaging.onMessage.listen(routeMessage);
  FirebaseMessaging.onMessageOpenedApp.listen(routeMessage);
  final initial = await FirebaseMessaging.instance.getInitialMessage();
  if (initial != null) routeMessage(initial);
}

handlePush() mengenali data type: information dan meminta SDK memperbarui feed informasi. Nilai true berarti pesan telah diteruskan, bukan konfirmasi popup sudah terlihat. Aturan maintenance tetap mengikuti autoMaintenancePopups. Daftarkan listener sekali dan batalkan subscription ketika pemiliknya di-dispose. Plugin ini digunakan dari main isolate; jangan memanggilnya langsung dari background isolate FCM. Untuk konfigurasi lengkap, ikuti panduan penerimaan pesan Firebase.

Notifikasi dari dashboard (0.1.6+)

Menu dashboard Push & distribusi → Kirim notifikasi mengirim notifikasi biasa (judul, isi, gambar opsional, dan link opsional) ke topik aplikasi pulse.<package>.<platform>.all. SDK sudah berlangganan topik tersebut setelah start(), sehingga aplikasi tidak perlu subscribe sendiri. Pesan ini ditandai dengan data pulse_type: notification; link yang dibuka saat notifikasi ditekan ada di data url (https atau deep link aplikasi).

Saat aplikasi di background atau tertutup, sistem menampilkan notifikasi ini sendiri. Saat aplikasi terbuka (foreground), tampilan notifikasi menjadi tugas aplikasi Flutter; plugin hanya mengenali pesannya.

iOS: aktifkan presentasi foreground sekali saat inisialisasi:

await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
  alert: true,
  badge: true,
  sound: true,
);

Android: tampilkan notifikasi lokal dengan flutter_local_notifications (contoh memakai API 20+; jsonEncode dari dart:convert, Platform dari dart:io) dari FirebaseMessaging.onMessage. Tetap panggil handlePush() lebih dulu untuk push informasi:

final localNotifications = FlutterLocalNotificationsPlugin();

void onForegroundMessage(RemoteMessage message) {
  if (PulseMonitoring.handlePush(message.data)) return;
  if (!PulseMonitoring.isPulseNotification(message.data)) {
    // Lanjutkan handler pesan aplikasi yang lain di sini.
    return;
  }
  final notification = message.notification;
  if (notification == null || !Platform.isAndroid) return;
  localNotifications.show(
    id: message.hashCode,
    title: notification.title,
    body: notification.body,
    notificationDetails: const NotificationDetails(
      android: AndroidNotificationDetails(
        'pulse_notifications',
        'Notifikasi',
        importance: Importance.high,
        priority: Priority.high,
      ),
    ),
    payload: jsonEncode(message.data),
  );
}

Saat notifikasi lokal ini ditekan, baca kembali payload (lihat onDidReceiveNotificationResponse pada initialize()) lalu teruskan datanya ke handler tap di bawah.

Tap. Tangani notifikasi yang dibuka melalui FirebaseMessaging.onMessageOpenedApp dan getInitialMessage():

void openPulseNotification(RemoteMessage message) {
  if (!PulseMonitoring.handleNotificationTap(message.data)) return;
  final link = PulseMonitoring.notificationLink(message.data);
  if (link != null) router.go(link.path); // atau launchUrl(link) untuk https
}

Future<void> configurePulseNotifications() async {
  FirebaseMessaging.onMessageOpenedApp.listen(openPulseNotification);
  final initial = await FirebaseMessaging.instance.getInitialMessage();
  if (initial != null) openPulseNotification(initial);
}

Jika aplikasi sudah memakai routeMessage() dari bagian push informasi, panggil openPulseNotification() setelah handlePush() mengembalikan false. handleNotificationTap() mencatat event pulse_notification_opened dengan properti has_url (tanpa URL atau teks notifikasi) dan mengembalikan true untuk notifikasi Pulse; plugin tidak melakukan navigasi. notificationLink() mengembalikan null bila link kosong atau bukan URI absolut yang valid.

Gambar. Android menampilkan gambar secara otomatis saat aplikasi di background. iOS memerlukan Notification Service Extension; ikuti panduan gambar notifikasi Firebase untuk Flutter. Notifikasi lokal foreground Android pada contoh di atas tidak memuat gambar.

Praktik integrasi yang disarankan

  • Mulai SDK sebelum mengirim event, lalu set user setelah session login tersedia.
  • Gunakan ID internal dan properties yang tidak memuat data sensitif.
  • Pertahankan handler error dan alur push aplikasi yang sudah ada; hindari laporan duplikat.
  • Gunakan observer route atau pelaporan screen manual sesuai router aplikasi.
  • Biarkan antrean dan retry SDK berjalan; jangan memanggil flush() pada setiap event.
  • Gunakan PulseMonitoring.flush() untuk meminta upload segera saat diperlukan. Pemanggilan ini tidak menunggu upload selesai atau menjamin server menerima data.
  • Validasi pengiriman melalui dashboard pada perangkat uji. Antrean offline memiliki batas kapasitas; SDK tidak menjamin pengiriman setiap event.
  • Uji Android release dengan minification aktif serta iOS pada perangkat fisik. Simulator saja tidak membuktikan penerimaan diagnostics MetricKit.

SDK menyertakan PrivacyInfo.xcprivacy pada framework iOS. Deklarasi privasi aplikasi perlu mencerminkan identitas user, event custom, dan data lain yang benar-benar dikirim. Diagnostics crash iOS mengikuti jadwal Apple dan tidak dijamin muncul saat launch berikutnya. Android belum menangkap crash NDK/sinyal. Gunakan crash reporter lain sesuai kebutuhan aplikasi.

Upgrade dan troubleshooting

Untuk memperbarui package yang sudah terpasang:

flutter pub upgrade pulse_monitoring
cd ios
pod update pulse_monitoring --no-repo-update
cd ..
Masalah Pemeriksaan
checkReleaseAarMetadata menyebut android-36 Gunakan plugin 0.1.2+ dan compileSdk aplikasi 37+. Periksa versi yang terpilih pada pubspec.lock.
SDK tidak mengirim data Pastikan workspace key terisi, endpoint dapat diakses, serta package/bundle ID terdaftar pada workspace yang benar.
Maintenance chip tidak muncul Pastikan konten published, jadwal aktif, target platform/package cocok, dan feed sudah diterima. Periksa juga ID flavor dev/prod.
Screen tidak tercatat Beri nama route atau panggil trackScreen() manual.
Error/HTTP Dart tidak tercatat Hubungkan handler error dan HTTP client seperti contoh di atas.
Error MissingPluginException setelah menambah dependency Hentikan aplikasi, jalankan pub get/Pods, lalu build ulang penuh; hot reload tidak mendaftarkan plugin native baru.
Push tidak muncul Periksa Firebase/APNs, permission, data type: information, serta forwarding pesan pada main isolate.
Crash iOS belum masuk dashboard Periksa diagnostics pada perangkat; pengiriman MetricKit dapat tertunda.

Versi native, contoh, dan lisensi

  • Plugin Flutter di pub.dev: 0.1.6.
  • Android native standalone: io.github.mhmadidris:pulse-monitoring:0.1.2 dari Maven Central.
  • iOS native standalone: XCFramework 0.1.2 melalui CocoaPods.
  • Contoh pemakaian: example/lib/main.dart.

Versi plugin dapat naik sendiri untuk perbaikan integrasi tanpa mengganti SDK native. Source implementasi Swift SDK, dSYM, dan archive Xcode tidak disertakan dalam package Flutter. Bridge Flutter dan binary iOS ikut tersedia pada pub.dev; repository GitHub dapat tetap private.

Penggunaan plugin dan binary iOS tunduk pada LICENSE. SDK Android native yang didistribusikan terpisah menggunakan Apache License 2.0. Hubungi idris3097@gmail.com untuk izin penggunaan atau pertanyaan integrasi.

Libraries

pulse_monitoring