mehery_sender 0.1.1
mehery_sender: ^0.1.1 copied to clipboard
A Flutter package to send device tokens to a server.
PushApp-Flutter SDK #
A lightweight Flutter package for push notifications, custom in-app messages (popup, banner, PiP, inline, tooltip), event tracking, and session handling for your Flutter apps.
What Your App Must Add (Quick Checklist) #
Your Flutter app should include all of the following:
- Firebase config files:
- Android:
android/app/google-services.json - iOS:
ios/Runner/GoogleService-Info.plist
- Android:
- Push capability on iOS and foreground notification handling in
AppDelegate.swift(see platform guides) - SDK initialization at startup: create a
Pushappinstance and callinitializeAndSendToken() - Firebase background handler registered in
main()(meSendFirebaseMessagingBackgroundHandler) so background receipts behave consistently - User identity and tracking calls where they match your user journey:
Pushapp.loginPushapp.initPage(page context for in-app surfaces)Pushapp.sendEventPushapp.createOrUpdateCustomerProfile(after login, recommended)
- Optional session geo reporting (
Pushapp.postSessionGeo) afterlogin(SDK persistssession_idwhendevice/linkreturns it); you must pass real location fields viaPushSessionGeoData BuildContextfor in-app UI viasetInAppNotificationbefore expecting overlays- Optional:
navigatorObserverswithmeSendRouteObserverfor route-based page events - Inline/tooltip widgets (
MeSendWidget,registerWidget,MeSendTooltipWrapper) only if you use those surfaces
📦 Installation #
Add the dependency to your app’s pubspec.yaml:
dependencies:
mehery_sender: ^0.1.0
Then install packages:
flutter pub get
For iOS, install CocoaPods dependencies:
cd ios && pod install && cd ..
Step-by-Step Setup (Flutter) #
1) Add Firebase files #
- Android: place
google-services.jsoninandroid/app/ - iOS: add
GoogleService-Info.plistto your Runner target
2) iOS push setup #
Enable Push Notifications in Xcode and add foreground handling:
import UserNotifications
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
if #available(iOS 14.0, *) {
completionHandler([.banner, .sound, .badge])
} else {
completionHandler([.alert, .sound, .badge])
}
}
See IOSREADME.md for Live Activities and extended iOS integration.
3) Register background messaging (recommended) #
In main(), before runApp:
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:mehery_sender/mehery_sender.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.onBackgroundMessage(meSendFirebaseMessagingBackgroundHandler);
runApp(const MyApp());
}
4) Initialize SDK at app startup #
Create one shared Pushapp instance. Pass your full app / channel id (same format as the Ionic SDK appId), for example demo_1751694691225:
- Tenant (subdomain for
https://<tenant>.pushapp...) = substring before the first_→demo - Channel id sent to APIs = the entire string →
demo_1751694691225
Legacy identifiers using a $ separator (tenant$channel) are still accepted.
import 'package:mehery_sender/mehery_sender.dart';
final pushapp = Pushapp(
identifier: 'demo_1751694691225',
sandbox: false,
);
await pushapp.initializeAndSendToken();
initializeAndSendToken() registers the device token with the backend (FCM on Android; platform-appropriate flow on iOS).
API hosts (https://<tenant>.pushapp.<tld>):
sandbox |
Host TLD |
|---|---|
false |
.net (production) |
true |
.ai (client sandbox) |
For internal Mehery development against .co.in, pass developmentHost: true (not for production app builds).
5) Provide context for in-app notifications #
Before showing popup/banner/PiP style surfaces:
pushapp.setInAppNotification(context);
6) Link user/session + events #
await pushapp.login('user_123');
pushapp.initPage('home');
await pushapp.sendEvent('button_clicked', {
'source': 'welcome_screen',
'method': 'google',
});
7) Optional: route observer for navigation events #
Attach the observer included on your Pushapp instance:
MaterialApp(
navigatorObservers: [pushapp.meSendRouteObserver],
// ...
);
8) Update customer profile (recommended after login) #
final headers = await pushapp.getDeviceHeaders();
final deviceId = headers['X-Device-ID'] ?? '';
final code = 'user_123_$deviceId';
await pushapp.createOrUpdateCustomerProfile(
code: code,
additionalInfo: {'city': 'Mumbai', 'plan': 'free'},
cohorts: {'segment': 'trial'},
completion: (success) {
// handle result
},
);
9) Session geo (optional) #
Sends POST /pushapp/api/session/geo on your tenant host. The SDK adds session_id automatically after login when device/link returns a session (otherwise the call returns false).
You supply geoIP by building PushSessionGeoData from GPS, platform locale, IP lookup, or your backend — the SDK does not invent coordinates.
geoIP JSON shape (also see PushSessionGeoData in Dart):
| Field | Type | What you provide |
|---|---|---|
geoIP.ip |
string |
IPv4 for this session/device (from your network stack or server). |
geoIP.location.lat |
number |
Latitude, decimal degrees (WGS‑84). |
geoIP.location.lng |
number |
Longitude, decimal degrees (WGS‑84). |
geoIP.country.iso_code |
string |
Country ISO code (e.g. IN, US). |
geoIP.country.name |
string |
Country display name. |
geoIP.region.iso_code |
string |
Region/state ISO code (e.g. MH, NY). |
geoIP.region.name |
string |
Region/state display name. |
geoIP.city.name |
string |
City name. |
geoIP.area.name |
string |
Area or neighborhood / locality name. |
Example
final geo = PushSessionGeoData(
ip: '203.0.113.10',
lat: 19.07609,
lng: 72.87771,
countryIsoCode: 'IN',
countryName: 'India',
regionIsoCode: 'MH',
regionName: 'Maharashtra',
cityName: 'Mumbai',
areaName: 'Parel',
);
final ok = await pushapp.postSessionGeo(geo);
10) Optional: inline + tooltip in-app placements #
🎨 Inline placeholder (MeSendWidget)
Embeds HTML/WebView-driven inline content for a given placeholder id:
MeSendWidget(
placeholderId: 'my_placeholder_id',
meSend: pushapp,
height: 200,
width: double.infinity,
)
💬 Tooltip anchor (registerWidget)
Wraps a child widget so tooltips can anchor to it (uses the SDK tooltip pipeline):
pushapp.registerWidget(
placeholderId: 'my_tooltip_target',
child: YourButton(),
);
💬 Tooltip wrapper (MeSendTooltipWrapper)
Alternative wrapper for tooltip-style surfaces:
MeSendTooltipWrapper(
placeholderId: 'my_tooltip_target',
meSend: pushapp,
child: YourButton(),
)
📋 API Reference #
Core / lifecycle #
Pushapp({required String identifier, bool sandbox, bool developmentHost})
Creates the SDK client.
Parameters:
identifier(string, required): App id — e.g.demo_1751694691225. The channel id for APIs is this full string; the tenant subdomain is the substring before the first_(demo). If you still use the old formtenant$channel, that is supported for backward compatibility.sandbox(bool, optional):false→*.pushapp.net(production).true→*.pushapp.ai(client sandbox).developmentHost(bool, optional, defaultfalse): whentrue, uses*.pushapp.co.infor internal development (overridessandbox). Do not ship this to end-user production builds.
Future<void> initializeAndSendToken()
Requests notification permission where applicable, reads the device token, and registers it with the backend.
void setInAppNotification(BuildContext context)
Stores BuildContext used when rendering in-app notification UI.
Future<void> login(String userId)
Associates the device/session with a user.
Future<void> logout(String userId)
Delinks the user from the device on the server.
void initPage(String page)
Signals the current page name for in-app / analytics flows.
Future<void> sendEvent(String eventName, Map<String, dynamic> eventData)
Sends a custom event (POST to /pushapp/api/v1/event).
Future<Map<String, String>> getDeviceHeaders()
Returns device/app metadata headers (X-Device-ID, X-App-Version, platform fields, etc.) for authenticated calls.
Future<void> createOrUpdateCustomerProfile({...})
Creates or updates customer profile data (PUT /pushapp/api/v1/customer/profile).
Parameters:
code(string, required): Unique customer code (recommended:userId_deviceId).additionalInfo(map, required): Profile attributes.cohorts(map, required): Segmentation attributes.completion(callback, required): Called withtrue/falsefor success.
Session / geo #
PushSessionGeoData
Constructor fields (serialized under geoIP): ip, lat, lng, countryIsoCode, countryName, regionIsoCode, regionName, cityName, areaName — see Step 9 for the JSON mapping.
Future<bool> postSessionGeo(PushSessionGeoData geo)
Sends POST /pushapp/api/session/geo with:
session_id— persisted by the SDK afterloginwhendevice/linkreturns a session id.geoIP— fromgeo.toGeoIpJson()(yourPushSessionGeoData).
Returns true on HTTP 2xx, false if there is no stored session id or the request fails.
static Future<void> postPushReceiptToSlack(RemoteMessage message, String source)
Internal/diagnostic helper used by the provided background handler; not required for normal integration.
Placeholder / widget helpers #
void registerPlaceholderListener(...)
Registers a listener for placeholder content pushed over the socket/API path.
void unregisterPlaceholderListener(String placeholderId)
Removes the listener for a placeholder id.
Widget registerWidget({required String placeholderId, required Widget child})
Wraps child for tooltip registration via TooltipSdk.
Route observer #
MeSendRouteObserver (via pushapp.meSendRouteObserver)
NavigatorObserver that emits page-related events when attached to MaterialApp. Instantiated by the SDK and wired when you construct Pushapp.
🔧 Platform-Specific Notes #
Android #
- Minimum SDK: API 26+ recommended for notification channels (see AndroidREADME.md).
- Firebase: Apply
google-servicesGradle plugin and includegoogle-services.json. - ProGuard (if enabled): consider keeping SDK classes — for example:
-keep class com.mehery.** { *; }
iOS #
- Minimum: Align with your app’s deployment target; push setup follows standard Firebase/APNs configuration.
- Capabilities: Push Notifications (and Background Modes if you use background delivery).
- Foreground notifications: Use
UNUserNotificationCenterDelegateas in Step 2. - Live Activities: See IOSREADME.md (iOS 16.1+ for ActivityKit features).
📄 Example Implementation #
See the example/ directory for a sample app:
- Firebase initialization
Pushappconstruction andinitializeAndSendToken- Login/logout triggers
Session geo: after login, call postSessionGeo(PushSessionGeoData(...)) with real location fields (see Step 9).
🏷️ Version #
Current package version: 0.1.0 (see pubspec.yaml).
💬 Support #
- Repository: mehery_sender_flutter
- Issues: GitHub Issues
- Platform guides: AndroidREADME.md, IOSREADME.md
📝 License #
MIT