A Firebase Cloud Messaging (FCM) SDK for Android with built-in cross-promotion support. This SDK simplifies FCM integration and provides automatic handling of notifications and cross-promotion campaigns.
- Firebase Cloud Messaging Integration - Easy setup and token management
- Cross-Promotion Support - Automatic handling of package name-based cross-promotion campaigns
- Smart Notification Handling - Built-in notification display with image loading
- Token Management - Automatic token refresh and listener support
- Simple API - Clean, easy-to-use interface for quick integration
- Image Support - Automatic image loading for rich notifications
- WorkManager Integration - Efficient background processing for notification images
This SDK requires Firebase to be properly integrated in your Android application. Before using this SDK, ensure the following:
- Create a Firebase project in the Firebase Console
- Add your Android app to the Firebase project
- Download the
google-services.jsonfile from Firebase Console
Place the downloaded google-services.json file in your app module's root directory (app/google-services.json).
Add the Google Services plugin to your project-level build.gradle.kts:
buildscript {
dependencies {
classpath("com.google.gms:google-services:x.y.z")
}
}Apply the plugin in your app-level build.gradle.kts:
plugins {
id("com.google.gms.google-services")
}The SDK requires the following dependencies to be added to your build.gradle.kts:
SDK library
dependencies {
implementation("com.github.Funsol-Projects:FunNotify-SDK:v1.0.1")
}Other libraries
dependencies {
// WorkManager for background processing
implementation("androidx.work:work-runtime-ktx")
// Picasso for image loading
implementation("com.squareup.picasso:picasso")
// Firebase Messaging
implementation(platform("com.google.firebase:firebase-bom"))
implementation("com.google.firebase:firebase-messaging")
}Note: Use version catalogs or dependency management to specify versions rather than hardcoding them. The SDK is compatible with recent stable versions of these libraries.
In your Application class:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Initialize FCM SDK
val fcmManager = FunFCM()
fcmManager.setup(this, "your-topic-name")
// Optional: Listen for token updates
fcmManager.setTokenListener { token ->
Log.d("FCM", "FCM Token: $token")
// Send token to your server
sendTokenToServer(token)
}
}
}In your AndroidManifest.xml:
<application>
android:name=".MyApplication"/>
</application><service
android:name="com.funsol.fcm.FunFirebaseMessagingService"
android:directBootAware="true"
android:exported="true"
tools:node="replace">
<intent-filter android:priority="-500">
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<receiver
android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND"
tools:node="replace">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>That's it! The SDK will automatically handle incoming FCM messages and display notifications.
val fcmManager = FunFCM()
fcmManager.getToken(
onSuccess = { token ->
Log.d("FCM", "FCM Token: $token")
// Send token to your server
sendTokenToServer(token)
},
onFailure = { exception ->
Log.e("FCM", "Failed to get token", exception)
}
)val fcmManager = FunFCM()
// Subscribe to a topic (done automatically in setup)
fcmManager.setup(context, "topic-name")
// Unsubscribe from a topic
fcmManager.removeSubscription("topic-name")The SDK automatically handles token refresh. Set a listener to be notified:
fcmManager.setTokenListener { token ->
// New token received
Log.d("FCM", "New token: $token")
sendTokenToServer(token)
}
// Remove listener
fcmManager.setTokenListener(null)The SDK expects FCM messages in data-only format. Send messages to a topic or specific device token.
{
"message": {
"topic": "[STRING] com.example.fcmtest",
"data": {
"icon": "[STRING] YOUR_ICON_URL",
"title": "[STRING] YOUR_TITLE",
"short_desc": "[STRING] YOUR_DESCRIPTION",
"long_desc": "[STRING] YOUR_DESCRIPTION",
"feature": "[STRING] FEATURE_IMAGE_URL",
"package": "[STRING] PACKAGE_FOR_PROMOTION / OWN_PACKAGE",
"crossPromotion": "[BOOLEAN] -> {PROMOTION ENABLES -> AD ATTRIBUTE} false",
"genericStyle": "[BOOLEAN] -> {CUSTOM OR GENERIC NOTIFICATION STYLE} true",
"payload": "{\"icon\":\"https://static.vecteezy.com/...png\",\"feature\":\"https://static.vecteezy.com/...png\",\"package\":\"com.tinder\",\"crossPromotion\":false,\"genericStyle\":false,\"cta\":\"Swipe Now!\",\"rating\":4.9}"
}
}
}All attributes in the data object are sent as strings. Here's what each attribute does:
| Attribute | Required | Type | Description |
|---|---|---|---|
| icon | Yes | String (URL) | URL to the notification icon image. This will be displayed in the notification. |
| title | Yes | String | The main title text displayed in the notification. |
| short_desc | Yes | String | Short description text shown in the collapsed notification view. |
| long_desc | No | String | Long description text (currently not displayed, reserved for future use). |
| feature | No | String (URL) | URL to a feature image for rich notifications. This image will be loaded asynchronously and displayed in the expanded notification. |
| package | Yes | String | Package name of the app to open when the notification is clicked. If the app is installed, it opens directly. If not installed, it opens the Play Store page. |
| crossPromotion | No | String (Boolean) | Set to "true" to use cross-promotion notification style with custom layout. Set to "false" or omit for standard notification style. |
| genericStyle | No | String (Boolean) | Set to "true" to use generic notification style (standard Android notification with image support). Set to "false" or omit for custom cross-promotion style. |
| payload | No | String (JSON) | Custom JSON string containing additional data. This payload will be passed to your app when the notification is clicked. You can retrieve it from the intent. |
The payload field allows you to send custom data with the notification. When a user clicks the notification, you can retrieve this payload from the intent in your activity.
Retrieving Payload in Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Retrieve payload from intent
val payload = intent.getStringExtra(ARG_PAYLOAD)
if (payload != null) {
// Parse JSON payload
try {
val jsonObject = JSONObject(payload)
val icon = jsonObject.optString("icon")
val feature = jsonObject.optString("feature")
val packageName = jsonObject.optString("package")
val cta = jsonObject.optString("cta")
val rating = jsonObject.optDouble("rating")
// Use the payload data as needed
Log.d("Payload", "CTA: $cta, Rating: $rating")
} catch (e: Exception) {
Log.e("Payload", "Failed to parse payload: ${e.message}")
}
}
}
}Payload Example:
{
"icon": "https://example.com/icon.png",
"feature": "https://example.com/feature.png",
"package": "com.app",
"crossPromotion": false,
"genericStyle": false,
"cta": "Swipe Now!",
"rating": 4.9
}Set crossPromotion: "true" and genericStyle: "false" for a custom cross-promotion notification layout with:
- Custom RemoteViews layout
- Icon and feature image support
- Special styling for promotional content
Set genericStyle: "true" for a standard Android notification with:
- Standard notification layout
- Large icon support
- Big picture style for expanded view
- Optional "AD" prefix in title (when
crossPromotion: "true")
The SDK automatically handles cross-promotion based on the package field:
- If app is installed: Opens the app directly when notification is clicked
- If app is not installed: Opens Play Store page to install the app
The package field in the FCM message determines which app to promote or open.
Main interface for FCM operations.
setup(context: Context, topic: String)- Initialize SDK and subscribe to topicremoveSubscription(topic: String)- Unsubscribe from a topicsetTokenListener(listener: FcmTokenListener?)- Set token update listenergetToken(onSuccess: (String) -> Unit, onFailure: (Exception) -> Unit)- Get current token
Implementation of FcmManager. Use this class to interact with the SDK.
val fcmManager = FunFCM()Interface for receiving token updates.
interface FcmTokenListener {
fun onTokenReceived(token: String)
}- Verify Firebase integration is complete:
- Ensure
google-services.jsonis present inapp/directory - Confirm Google Services plugin is applied in build files
- Check that Firebase dependencies are properly configured
- Ensure
- Verify notification permissions are granted (Android 13+)
- Check logcat for error messages
- Ensure the FCM message uses data-only format (not notification payload)
- Verify all required fields (
icon,title,short_desc,package) are present
- Verify Firebase integration:
- Ensure
google-services.jsonis correctly placed and configured - Check that Firebase Messaging dependency is included
- Verify Google Services plugin is applied
- Ensure
- Verify internet connection
- Check logcat for Firebase errors
- Ensure
setup()is called in Application class
- Verify
packagefield is present in FCM message - Check that package name is correct
- Test with a valid package name
- Ensure
crossPromotionfield is set to"true"string
- Verify image URLs are accessible
- Check internet connection
- Images are loaded asynchronously via WorkManager - allow time for loading
- Check logcat for image loading errors
If you're using ProGuard, add these rules to your proguard-rules.pro:
# FunNotify SDK
-dontwarn org.conscrypt.Conscrypt
-dontwarn org.conscrypt.OpenSSLProvider
-dontwarn java.lang.invoke.StringConcatFactory
-keep class com.funsol.fcm.FunFCM { *; }
For issues and questions, please open an issue on GitHub.
- Initial release
- FCM integration
- Cross-promotion support
- Token management
- Image loading for notifications
- WorkManager integration
- Payload support for custom data
Copyright (c) 2025 Funsol Technologies Pvt Ltd
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.