Skip to content

Commit

Permalink
feat(android): support targetSdkVersion >= 31 (Android 12) (#185)
Browse files Browse the repository at this point in the history
* feat(android): update Firebase Messaging to 23

This is needed for compatibility with targetSdkVersion>=31. Without it,
push messages cause a crash on Android 12 due to missing
FLAG_MUTABLE/FLAG_IMMUTABLE on PendingIntent[0], notification trampoline
issue, and possibly other such reasons.

Note that Firebase has removed the FirbaseInstanceId class in favor of
FirbaseInstallations. To restore it for now, add the firebase-iid
dependency, see [2].

[0] https://developer.android.com/about/versions/12/behavior-changes-12#pending-intent-mutability
[1] https://developer.android.com/about/versions/12/behavior-changes-12#notification-trampolines
[2] https://firebase.google.com/support/release-notes/android#messaging_v22-0-0

* refactor(android): merge PushInstanceIDListenerService into FCMService

Since 1ae3428, when
`PushInstanceIDListenerService` was changed away from the deprecated
`FirebaseInstanceIdService` to use
`FirebaseMessagingService::onNewToken`, there is no longer a need to use
a separate service anymore. Further, the `INSTANCE_ID_EVENT` intent
filter is not needed.

* refactor(android): remove unneeded indirection on onNewToken

The callback gets the new token already, there is no need to fetch it
again.

* refactor(android): avoid using deprecated InstanceId methods

These have been deprecated in recent firebase-messaging releases.

* fix(android): specify pending intent mutability for targetSdkVersion>=31

See:
https://developer.android.com/guide/components/intents-filters#DeclareMutabilityPendingIntent

* fix(android): improve the error handling around Tasks.await

Tasks.await throws ExecutionException so it needs to be unwrapped for
the existing error handling to work, otherwise an IOException causes the
app to crash.
  • Loading branch information
bluetech committed Aug 20, 2022
1 parent 6bca515 commit c3fb5b8
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 62 deletions.
9 changes: 1 addition & 8 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,6 @@
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>

<service android:name="com.adobe.phonegap.push.PushInstanceIDListenerService" android:exported="true" >
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
</config-file>

<config-file target="config.xml" parent="/*">
Expand All @@ -71,7 +65,7 @@
</config-file>

<preference name="ANDROIDX_CORE_VERSION" default="1.6.+"/>
<preference name="FCM_VERSION" default="18.+"/>
<preference name="FCM_VERSION" default="23.+"/>

<framework src="androidx.core:core:$ANDROIDX_CORE_VERSION" />
<framework src="me.leolin:ShortcutBadger:1.1.22@aar"/>
Expand All @@ -81,7 +75,6 @@
<source-file src="src/android/com/adobe/phonegap/push/PushConstants.kt" target-dir="java/com/adobe/phonegap/push/"/>
<source-file src="src/android/com/adobe/phonegap/push/PushHandlerActivity.kt" target-dir="java/com/adobe/phonegap/push/"/>
<source-file src="src/android/com/adobe/phonegap/push/BackgroundHandlerActivity.kt" target-dir="java/com/adobe/phonegap/push/"/>
<source-file src="src/android/com/adobe/phonegap/push/PushInstanceIDListenerService.kt" target-dir="java/com/adobe/phonegap/push/"/>
<source-file src="src/android/com/adobe/phonegap/push/PushPlugin.kt" target-dir="java/com/adobe/phonegap/push/"/>
<source-file src="src/android/com/adobe/phonegap/push/BackgroundActionButtonHandler.kt" target-dir="java/com/adobe/phonegap/push/"/>
<source-file src="src/android/com/adobe/phonegap/push/PushDismissedHandler.kt" target-dir="java/com/adobe/phonegap/push/"/>
Expand Down
36 changes: 30 additions & 6 deletions src/android/com/adobe/phonegap/push/FCMService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ class FCMService : FirebaseMessagingService() {

private val messageMap = HashMap<Int, ArrayList<String?>>()

private val FLAG_MUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_MUTABLE
} else {
0
}
private val FLAG_IMMUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
}

/**
* Get the Application Name from Label
*/
Expand All @@ -62,6 +73,19 @@ class FCMService : FirebaseMessagingService() {
MODE_PRIVATE
)

/**
* Called when a new token is generated, after app install or token changes.
*
* @param token
*/
override fun onNewToken(token: String) {
super.onNewToken(token)
Log.d(TAG, "Refreshed token: $token")

// TODO: Implement this method to send any registration to your app's servers.
//sendRegistrationToServer(token);
}

/**
* Set Notification
* If message is empty or null, the message list is cleared.
Expand Down Expand Up @@ -448,7 +472,7 @@ class FCMService : FirebaseMessagingService() {
this,
requestCode,
notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
)
val dismissedNotificationIntent = Intent(
this,
Expand All @@ -467,7 +491,7 @@ class FCMService : FirebaseMessagingService() {
this,
requestCode,
dismissedNotificationIntent,
PendingIntent.FLAG_CANCEL_CURRENT
PendingIntent.FLAG_CANCEL_CURRENT or FLAG_IMMUTABLE
)

val mBuilder: NotificationCompat.Builder =
Expand Down Expand Up @@ -676,7 +700,7 @@ class FCMService : FirebaseMessagingService() {
this,
uniquePendingIntentRequestCode,
intent,
PendingIntent.FLAG_ONE_SHOT
PendingIntent.FLAG_ONE_SHOT or FLAG_MUTABLE
)
} else {
Log.d(TAG, "push receiver for notId $notId")
Expand All @@ -685,7 +709,7 @@ class FCMService : FirebaseMessagingService() {
this,
uniquePendingIntentRequestCode,
intent,
PendingIntent.FLAG_ONE_SHOT
PendingIntent.FLAG_ONE_SHOT or FLAG_MUTABLE
)
}
}
Expand All @@ -696,7 +720,7 @@ class FCMService : FirebaseMessagingService() {
pIntent = PendingIntent.getActivity(
this, uniquePendingIntentRequestCode,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
)
}

Expand All @@ -706,7 +730,7 @@ class FCMService : FirebaseMessagingService() {
pIntent = PendingIntent.getBroadcast(
this, uniquePendingIntentRequestCode,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent.FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE
)
}
}
Expand Down

This file was deleted.

36 changes: 23 additions & 13 deletions src/android/com/adobe/phonegap/push/PushPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import android.provider.Settings
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.google.firebase.iid.FirebaseInstanceId
import com.google.android.gms.tasks.Tasks
import com.google.firebase.messaging.FirebaseMessaging
import me.leolin.shortcutbadger.ShortcutBadger
import org.apache.cordova.*
Expand All @@ -25,6 +25,7 @@ import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
import java.util.*
import java.util.concurrent.ExecutionException

/**
* Cordova Plugin Push
Expand Down Expand Up @@ -442,7 +443,6 @@ class PushPlugin : CordovaPlugin() {
Context.MODE_PRIVATE
)
var jo: JSONObject? = null
var token: String? = null
var senderID: String? = null

try {
Expand All @@ -461,18 +461,21 @@ class PushPlugin : CordovaPlugin() {
Log.v(TAG, formatLogMessage("JSONObject=$jo"))
Log.v(TAG, formatLogMessage("senderID=$senderID"))

try {
token = FirebaseInstanceId.getInstance().token
} catch (e: IllegalStateException) {
Log.e(TAG, formatLogMessage("Firebase Token Exception ${e.message}"))
}

if (token == null) {
val token = try {
try {
token = FirebaseInstanceId.getInstance().getToken(senderID, PushConstants.FCM)
} catch (e: IllegalStateException) {
Log.e(TAG, formatLogMessage("Firebase Token Exception ${e.message}"))
Tasks.await(FirebaseMessaging.getInstance().token)
} catch (e: ExecutionException) {
throw e.cause ?: e
}
} catch (e: IllegalStateException) {
Log.e(TAG, formatLogMessage("Firebase Token Exception ${e.message}"))
null
} catch (e: ExecutionException) {
Log.e(TAG, formatLogMessage("Firebase Token Exception ${e.message}"))
null
} catch (e: InterruptedException) {
Log.e(TAG, formatLogMessage("Firebase Token Exception ${e.message}"))
null
}

if (token != "") {
Expand Down Expand Up @@ -612,7 +615,11 @@ class PushPlugin : CordovaPlugin() {
if (topics != null) {
unsubscribeFromTopics(topics)
} else {
FirebaseInstanceId.getInstance().deleteInstanceId()
try {
Tasks.await(FirebaseMessaging.getInstance().deleteToken())
} catch (e: ExecutionException) {
throw e.cause ?: e
}
Log.v(TAG, formatLogMessage("UNREGISTER"))

/**
Expand Down Expand Up @@ -640,6 +647,9 @@ class PushPlugin : CordovaPlugin() {
} catch (e: IOException) {
Log.e(TAG, formatLogMessage("IO Exception ${e.message}"))
callbackContext.error(e.message)
} catch (e: InterruptedException) {
Log.e(TAG, formatLogMessage("Interrupted ${e.message}"))
callbackContext.error(e.message)
}
}
}
Expand Down

0 comments on commit c3fb5b8

Please sign in to comment.