CMPush is a solution for customers that want to send push notifications to their apps by using phone numbers. The CM platform will look up the corresponding push token for the telephone number and send a push message. When a push message can't be delivered for some reason, CM will send the message by SMS (or another channel, if configured)
-
CMPush.updateToken(updateToken(context: Context, pushToken: String, callback: (success: Boolean, error: CMPushError?, installationId: String?) -> Unit))
now returns the installationID or aCMPushError
in the callback. Use the installationID to send push messages to your customers if the MSISDN OTP flow is not needed. The installationID can be added to the customer account for example. CallCMPush.unregisterMSISDN(context: Context, callback: (success: Boolean, error: CMPushError?) -> Unit)
when the user logs out. Don't performCMPush.updateMSISDN(context: Context, msisdn: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
before the installationID was received. -
CMPush.preRegister(context: Context, msisdn: String, sender: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
is deprecated and replaced withCMPush.updateMSISDN(context: Context, msisdn: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
. Use this call afterCMPush.updateToken(context: Context, pushToken: String, callback: (success: Boolean, error: CMPushError?, installationId: String?) -> Unit)
completed successfully to start OTP flow. -
CMPush.register(context: Context, pushToken: String, msisdn: String, otpCode: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
is deprecated and replaced withCMPush.updateOTP(context: Context, msisdn: String, otpCode: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
. Use this call to send the OTP code to the server. -
CMPush.pushReceived(context: Context, data: Map<String, String>, showNotification: Boolean = true, @DrawableRes notificationIcon: Int, notificationContentIntent: PendingIntent, callback: (success: Boolean, error: CMPushError?) -> Unit)
is deprecated and replaced withCMPush.pushReceived(context: Context, data: Map<String, String>, callback: ((success: Boolean, error: CMPushError?) -> Unit)? = null)
. -
Use
CMPush.unregisterMSISDN(context: Context, callback: (success: Boolean, error: CMPushError?) -> Unit)
to unregister an MSISDN instead ofCMPush.deleteRegistration()
-
CMPushError
is now a sealed class that contains more details.CMPushError.errorMessage
is nowCMPushError.message
. -
CMPush.isRegistered()
now checks if the SDK is registered with the CM server. UseCMPush.hasRegisteredMSISDN()
to check wether a MSISDN was registered to this account. -
Use
CMPush.installationID()
to retrieve the installationID (or null if not yet registered to CM server). Use the installationID to send push messages to your customers if the MSISDN OTP flow is not needed. -
Added support for action buttons. These buttons can also link to pages in the app. More info about this in de documentation below.
- If you haven't already, move the
CMPush.initialize()
to theonCreate()
method of yourApplication
class. This is for showing push notifications that come through Push Amplification. - In your FirebaseMessagingService, replace
CMPush.pushReceived(context: Context, data: Map<String, String>, showNotification: Boolean = true, @DrawableRes notificationIcon: Int, notificationContentIntent: PendingIntent, callback: (success: Boolean, error: CMPushError?) -> Unit)
withCMPush.pushReceived(context: Context, data: Map<String, String>, callback: ((success: Boolean, error: CMPushError?) -> Unit)? = null)
.notificationIcon
should be passed in theCMPush.initialize()
method. ThenotificationContentIntent
has also been moved to theCMPush.initialize()
. - Wait for
CMPush.updateToken(context: Context, pushToken: String, callback: (success: Boolean, error: CMPushError?, installationId: String?) -> Unit)
to return the installationID before startingCMPush.updateMSISDN(context: Context, msisdn: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
. If no MSISDN verification is needed, store the installationID in the customer account. - Replace your call to
CMPush.preRegister(context: Context, msisdn: String, sender: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
withCMPush.updateMSISDN(context: Context, msisdn: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
- Replace your call to
CMPush.register(context: Context, pushToken: String, msisdn: String, otpCode: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
withCMPush.updateOTP(context: Context, msisdn: String, otpCode: String, callback: (success: Boolean, error: CMPushError?) -> Unit)
- Replace your call to
CMPush.deleteRegistration()
withCMPush.unregisterMSISDN(context: Context, callback: (success: Boolean, error: CMPushError?) -> Unit)
- Replace your call to
CMPush.isRegistered()
withCMPush.hasRegisteredMSISDN()
-
Support for rich media in push notifications. Supported media are:
- "image/jpeg": JPG image (max 10MB)
- "image/png": PNG image (max 10MB)
-
Support for suggestions (actions) in push notifications. Supported actions are:
- OpenUrl: website url. The url will be opened in the browser of the user
- OpenAppPage: open a specific page in the app.
In the
Intent
of the launch activity, the page is stored in the extra's with keyCMPush.OPEN_APP_PAGE
.
-
Report preferred language to the CM server to be able to localize messages
-
Now also supports Push Notifications without SMS verification (OTP) flow.
- Initial release
Developers need to onboard at CM by providing a Firebase admin.json
The onboarding process at CM will return a unique applicationKey, that needs to be passed into the library.
To enable CMPush you need to add Firebase to your app and you have to add the CMPush library to your project. Next you have to add a PushReceiver that extends the FirebaseMessagingService. The CMPush library confirms and shows push messages and this functionality needs to be called from FirebaseMessagingService.
The first step of enabling push notifications is adding Firebase Cloud Messaging to your Android app and creating a custom FirebaseMessagingService
as described in the following tutorial:
Set up Firebase Cloud-Messaging
Add the JitPack repository to your root build.gradle
.
allprojects {
repositories {
google()
jcenter()
maven {
url 'https://jitpack.io'
}
}
}
Next, add the dependency to your app-level build.gradle
.
dependencies {
// CMPush Library
implementation 'com.github.CMDotCom:text-push-library-android:2.0.0'
}
Now perform a project sync
and the library is added to your Android project.
CMPush needs to be configured at application startup. Add CMPush.initialize()
to the onCreate
method of your Application
. It's important that this is done in the Application
and not in an Activity!
The initialize method requires a few parameters.
context
: So the library can use SharedPreferences to store configuration options.
applicationKey
: The applicationKey received from CM.
notificationIcon
: The icon (drawable res) that should be used for the notifications.
notificationIntent
: Intent
to specify which Activity
should be opened when a user interacts with a notification. Make sure your flags are correct. Usually FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TOP.
Since Android 8 notifications are linked to a notification channel
. You can read more about notification channels here:
Notification channel info
Because the library can also handle the showing of the push notifications, it needs a channelId
, channelName
and channelDescription
.
val startIntent = Intent(applicationContext, MainActivity::class.java)
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
startIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
CMPush.initialize(
context = this,
applicationKey = "<key>",
channelId = "CMPushAnnouncements",
channelName = "Announcements",
channelDescription = "Announcements of our latest products!",
notificationIcon = R.drawable.ic_launcher_foreground,
notificationIntent = startIntent
)
CMPushError is a sealed class that is returned by several API calls. It can be used to determine the cause of the error:
when (error){
CMPushError.NoMSISDN -> TODO()
CMPushError.NotInitialized -> TODO()
CMPushError.NotRegistered -> TODO()
CMPushError.Offline -> TODO()
is CMPushError.ServerError -> TODO()
}
To confirm / show the Firebase push messages in your app you need to implement some methods in your own FirebaseMessagingService
.
Incoming push messages will arrive in the onMessageReceived(remoteMessage: RemoteMessage)
.
To show the notification and confirm that a push message has been delivered the CMPush.pushReceived()
method has to be implemented in the onMessageReceived()
.
The CMPush library will create the notification for you.
class PushReceiver : FirebaseMessagingService() {
companion object {
const val TAG = "PushReceiver"
}
override fun onNewToken(token: String) {
CMPush.updateToken(
context = applicationContext,
pushToken = token,
callback = { success, error, _ ->
if (success) {
Log.d(TAG, "Successfully updated token!")
} else {
Log.e(TAG, "Failed to update token: $error")
}
}
)
}
/**
* Incoming push messages will arrive here. They aren't being shown to the user yet.
* The CMPush library will notify CM the message has been received and create the Notification
*/
override fun onMessageReceived(remoteMessage: RemoteMessage) {
// Notify CMPush library that a push message has been received
CMPush.pushReceived(
context = applicationContext,
data = remoteMessage.data,
callback = { success, error ->
Log.d(TAG, "Confirmed push: $success, $error")
}
)
super.onMessageReceived(remoteMessage)
}
}
Everytime the app starts, call CMPush.updateToken()
.
The library keeps track of the previously send pushToken / device info and checks if there are differences. If so it sends an update to CM. Thus, there is no need to keep track of the pushToken yourself!
If successful, an installationId
will be returned which you can use to send push messages to the app.
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
if (!task.isSuccessful) {
Log.w(TAG, "Fetching FCM registration token failed", task.exception)
return@OnCompleteListener
}
// Get new FCM registration token
val token = task.result ?: ""
CMPush.updateToken(
context = this@MainActivity,
pushToken = token,
callback = { success, error, installationId ->
if (success) {
// You can store the installationId together with your customer info
} else {
// Handle error
}
}
)
})
Use CMPush.updateMSISDN()
to trigger an OTP request for a phone number that was entered by end-user, used to link a phone number to this device.
CMPush.updateMSISDN(
context = requireContext(),
msisdn = view.input_phone_number.text.toString(),
callback = { success, error ->
if (success) {
// Store the phone number and navigate to a OTP input screen.
} else {
// Show an error to the user
}
}
)
Checks an OTP that user has received by SMS to link a phone number to this device.
CMPush.updateOTP(
context = requireContext(),
msisdn = phoneNumber,
otpCode = view.input_otp_code.text.toString(),
callback = { success, error ->
if (success) {
// Finish the setup
} else {
// Show an error to the user
}
}
)
To check if the app is registered for push notifications the CMPush.isRegistered()
method can be called. This will return a boolean true
if the app is registered.
CMPush.isRegistered(
context = requireContext()
)
To check if the user has a MSISDN linked the CMPush.hasMSISDNLinked()
method can be called. This will return a boolean true
if the user has linked a phone number.
CMPush.hasRegisteredMSISDN(
context = requireContext()
)
To unlink the MSISDN of a user, the CMPush.unregisterMSISDN()
can be called.
CMPush.unregisterMSISDN(
context = requireContext(),
callback = { success, error ->
Log.d("CMPush", "Unregistered MSISDN: $success, Error: $error")
}
)
To delete the entire device registration, the CMPush.deleteRegistration()
can be called.
Note that you should register the device again using CMPush.updateToken()
CMPush.deleteRegistration(
context = requireContext(),
callback = { success, error ->
Log.d("CMPush", "Unregistered: $success, Error: $error")
}
)