Skip to main content
Integrate real-time push notifications into your Android app using Firebase Cloud Messaging (FCM) or Baidu Push (for China market) to ensure users never miss important updates.
Push notifications require proper FCM setup and valid server configuration. Test thoroughly before production deployment.

Prerequisites

Before implementing push notifications, ensure you have:

Firebase Project

Active Firebase project with FCM enabled

Google Services

google-services.json file in your app module

SDK Integration

social.plus Android SDK properly configured

Permissions

Required notification permissions declared

Setup Dependencies

Add the FCM dependency to your app-level build.gradle file:
dependencies {
    // social.plus FCM Push Notifications
    implementation 'com.github.AmityCo.Amity-Social-Cloud-SDK-Android:amity-push-fcm:6.x.x'
    
    // Firebase Cloud Messaging (if not already included)
    implementation 'com.google.firebase:firebase-messaging:23.4.0'
    implementation 'com.google.firebase:firebase-analytics:21.5.0'
}
Always use the latest version numbers. Check the releases page for current versions.

FCM Token Management

Retrieving FCM Token

Before initializing push notifications, obtain the FCM token that uniquely identifies each app instance:
import com.google.firebase.messaging.FirebaseMessaging
import com.amity.socialcloud.sdk.core.AmityFcm

class PushNotificationManager {
    
    fun initializePushNotifications() {
        FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
            if (!task.isSuccessful) {
                Log.w(TAG, "Fetching FCM registration token failed", task.exception)
                return@addOnCompleteListener
            }

            // Get new FCM registration token
            val token = task.result
            Log.d(TAG, "FCM Registration Token: $token")
            
            // Initialize Amity FCM with the token
            initAmityFcmNotification(token)
        }
    }
    
    private fun initAmityFcmNotification(fcmToken: String) {
        AmityFcm.create()
            .setup(fcmToken)
            .subscribe(
                onSuccess = {
                    Log.d(TAG, "FCM initialized successfully")
                },
                onError = { error ->
                    Log.e(TAG, "FCM initialization failed", error)
                }
            )
    }
    
    companion object {
        private const val TAG = "PushNotificationManager"
    }
}

Monitoring Token Changes

FCM tokens can change during the app lifecycle. Implement token monitoring:
import com.google.firebase.messaging.FirebaseMessagingService

class AmityFirebaseMessagingService : FirebaseMessagingService() {
    
    override fun onNewToken(token: String) {
        super.onNewToken(token)
        Log.d(TAG, "Refreshed token: $token")
        
        // Send token to your server if needed
        sendTokenToServer(token)
        
        // Update Amity SDK with new token
        updateAmityFcmToken(token)
    }
    
    private fun updateAmityFcmToken(token: String) {
        AmityFcm.create()
            .setup(token)
            .subscribe(
                onSuccess = {
                    Log.d(TAG, "FCM token updated successfully")
                },
                onError = { error ->
                    Log.e(TAG, "FCM token update failed", error)
                }
            )
    }
    
    private fun sendTokenToServer(token: String) {
        // Implement your server communication logic here
        // This is useful for sending targeted notifications from your backend
    }
    
    companion object {
        private const val TAG = "AmityFCMService"
    }
}
Don’t forget to register the service in your AndroidManifest.xml:
<application>
    <!-- Other components -->
    
    <service
        android:name=".AmityFirebaseMessagingService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
</application>

Handling Push Notifications

China Market Support (Baidu Push)

For apps targeting the Chinese market where Google Play Services are not available, use Baidu Push as an alternative.

Baidu Setup

Add Baidu dependency:
dependencies {
    // social.plus Baidu Push Notifications
    implementation 'com.github.AmityCo.Amity-Social-Cloud-SDK-Android:amity-push-baidu:6.x.x'
    
    // Baidu Push SDK
    implementation 'com.baidu:push:4.7.0'
}

Required Permissions

Add these permissions to your AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
    <!-- Baidu Push required permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    
    <application>
        <!-- Your app components -->
    </application>
</manifest>

Baidu Initialization

import com.amity.socialcloud.sdk.core.AmityBaidu

class BaiduPushManager {
    
    fun initializeBaiduPush(context: Context, apiKey: String) {
        AmityBaidu.create(context)
            .setup(apiKey)
            .subscribe(
                onSuccess = {
                    Log.d(TAG, "Baidu Push initialized successfully")
                },
                onError = { error ->
                    Log.e(TAG, "Baidu Push initialization failed", error)
                }
            )
    }
    
    companion object {
        private const val TAG = "BaiduPushManager"
    }
}
Priority System: social.plus SDK prioritizes FCM over Baidu. If Google Play Services are detected, Baidu Push will not be initialized.

Best Practices

Keep Tokens Updated: Always handle token refresh events and update the SDK with new tokens.
// Store token locally for backup
class TokenManager(private val context: Context) {
    private val prefs = context.getSharedPreferences("push_tokens", Context.MODE_PRIVATE)
    
    fun saveToken(token: String) {
        prefs.edit().putString("fcm_token", token).apply()
    }
    
    fun getStoredToken(): String? = prefs.getString("fcm_token", null)
    
    fun hasTokenChanged(newToken: String): Boolean {
        return getStoredToken() != newToken
    }
}
Robust Error Management: Implement comprehensive error handling for push notification failures.
class PushErrorHandler {
    fun handlePushError(error: Throwable) {
        when (error) {
            is FirebaseMessagingException -> handleFCMError(error)
            is SecurityException -> handlePermissionError()
            is NetworkException -> handleNetworkError()
            else -> handleGenericError(error)
        }
    }
    
    private fun handleFCMError(error: FirebaseMessagingException) {
        Log.e(TAG, "FCM Error: ${error.message}")
        // Implement retry logic
    }
    
    private fun handlePermissionError() {
        // Request notification permissions
    }
    
    private fun handleNetworkError() {
        // Retry when network is available
    }
}
Efficient Processing: Optimize notification handling for better performance.
class OptimizedNotificationHandler {
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    
    fun processNotification(data: Map<String, String>) {
        scope.launch {
            try {
                // Process in background thread
                val processedData = processNotificationData(data)
                
                // Switch to main thread for UI updates
                withContext(Dispatchers.Main) {
                    updateUI(processedData)
                }
            } catch (e: Exception) {
                Log.e(TAG, "Notification processing failed", e)
            }
        }
    }
}
Comprehensive Testing: Test push notifications thoroughly across different scenarios.
class PushNotificationTester {
    fun testPushNotification() {
        // Test with Firebase Console
        // Test with server-side sending
        // Test token refresh scenarios
        // Test offline/online scenarios
    }
    
    fun enableDebugLogging() {
        if (BuildConfig.DEBUG) {
            FirebaseMessaging.getInstance().isAutoInitEnabled = true
            // Enable verbose logging
        }
    }
}

Troubleshooting

Common Issues

Check these common causes:
  1. Invalid FCM Token: Verify token is correctly retrieved and sent to server
  2. App in Background: Ensure notification permissions are granted
  3. Network Issues: Check internet connectivity
  4. Server Configuration: Verify server-side FCM setup
  5. Token Refresh: Handle token updates properly
// Debug token issues
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        Log.d(TAG, "Current token: ${task.result}")
    } else {
        Log.e(TAG, "Token retrieval failed", task.exception)
    }
}
Baidu Push troubleshooting:
  1. API Key Validation: Ensure Baidu API key is correct
  2. Permissions: Verify all required permissions are declared
  3. Google Play Services: Check that GPS is properly disabled
  4. Network Access: Ensure app can access Baidu servers
SDK integration problems:
  1. Dependency Conflicts: Check for version conflicts
  2. ProGuard Rules: Add necessary keep rules for push classes
  3. Manifest Registration: Verify service registration in manifest
# social.plus Push SDK
-keep class com.amity.socialcloud.sdk.** { *; }
-keep class com.google.firebase.** { *; }
-keep class com.baidu.** { *; }