From 9cde9168ecd5f41bf0aa49b7d0deb2dc0217af43 Mon Sep 17 00:00:00 2001 From: a-maurice Date: Wed, 17 Jul 2024 14:11:52 -0700 Subject: [PATCH] Rewrite Messaging Swig logic to prefer handwritten public files (#1068) * Refactor the Messaging swig logic * Update readme, and random cleanup * Update readme.md --- docs/readme.md | 5 + messaging/CMakeLists.txt | 4 + messaging/src/FirebaseMessage.cs | 117 ++++++ messaging/src/FirebaseMessaging.cs | 186 +++++++++ messaging/src/FirebaseNotification.cs | 160 ++++++++ messaging/src/MessagingEventArgs.cs | 3 +- messaging/src/MessagingOptions.cs | 39 ++ messaging/src/swig/messaging.i | 542 ++------------------------ 8 files changed, 544 insertions(+), 512 deletions(-) create mode 100644 messaging/src/FirebaseMessage.cs create mode 100644 messaging/src/FirebaseMessaging.cs create mode 100644 messaging/src/FirebaseNotification.cs create mode 100644 messaging/src/MessagingOptions.cs diff --git a/docs/readme.md b/docs/readme.md index 159cb2d60..583631e59 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -71,6 +71,11 @@ Support Release Notes ------------- +### Upcoming release +- Changes + - Messaging: Deprecated the Dispose functions, as they are no longer + necessary for cleaning up memory. + ### 12.1.0 - Changes - General: Update to Firebase C++ SDK version 12.1.0. diff --git a/messaging/CMakeLists.txt b/messaging/CMakeLists.txt index faef43c35..f57df5544 100644 --- a/messaging/CMakeLists.txt +++ b/messaging/CMakeLists.txt @@ -23,7 +23,11 @@ set(firebase_messaging_swig # Firebase Messaging CSharp files set(firebase_messaging_src + src/FirebaseMessage.cs + src/FirebaseMessaging.cs + src/FirebaseNotification.cs src/MessagingEventArgs.cs + src/MessagingOptions.cs ) firebase_swig_add_library(firebase_messaging_swig diff --git a/messaging/src/FirebaseMessage.cs b/messaging/src/FirebaseMessage.cs new file mode 100644 index 000000000..daf6e1c1a --- /dev/null +++ b/messaging/src/FirebaseMessage.cs @@ -0,0 +1,117 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Collections.Generic; + +namespace Firebase.Messaging { + +/// @brief Data structure used to send messages to, and receive messages from, +/// cloud messaging. +public sealed class FirebaseMessage { + + internal static FirebaseMessage FromInternal(FirebaseMessageInternal other) { + if (other == null) return null; + + FirebaseMessage message = new FirebaseMessage(); + message.CollapseKey = other.collapse_key; + // Make a copy of the dictionary, to not rely on the C++ memory lasting around + message.Data = new Dictionary(other.data); + message.Error = other.error; + message.ErrorDescription = other.error_description; + message.From = other.from; + message.Link = Firebase.FirebaseApp.UrlStringToUri(other.link); + message.MessageId = other.message_id; + message.MessageType = other.message_type; + message.Notification = FirebaseNotification.FromInternal(other.notification); + message.NotificationOpened = other.notification_opened; + message.Priority = other.priority; + // Make a copy of the array, to not rely on the C++ memory lasting around + message.RawData = new byte[other.raw_data.Count]; + other.raw_data.CopyTo(message.RawData); + message.TimeToLive = System.TimeSpan.FromSeconds(other.time_to_live); + message.To = other.to; + return message; + } + + /// Gets the collapse key used for collapsible messages. + public string CollapseKey { get; private set; } + + /// Gets or sets the metadata, including all original key/value pairs. + /// Includes some of the HTTP headers used when sending the message. `gcm`, + /// `google` and `goog` prefixes are reserved for internal use. + public System.Collections.Generic.IDictionary Data { get; private set; } + + /// Gets the error code. Used in "nack" messages for CCS, and in responses + /// from the server. + /// See the CCS specification for the externally-supported list. + public string Error { get; private set; } + + /// Gets the human readable details about the error. + public string ErrorDescription { get; private set; } + + /// Gets the authenticated ID of the sender. This is a project number in most cases. + public string From { get; private set; } + + /// The link into the app from the message. + public System.Uri Link { get; private set; } + + /// Gets or sets the message ID. This can be specified by sender. Internally a + /// hash of the message ID and other elements will be used for storage. The ID + /// must be unique for each topic subscription - using the same ID may result + /// in overriding the original message or duplicate delivery. + public string MessageId { get; private set; } + + /// Gets the message type, equivalent with a content-type. + /// CCS uses "ack", "nack" for flow control and error handling. + /// "control" is used by CCS for connection control. + public string MessageType { get; private set; } + + /// Optional notification to show. This only set if a notification was + /// received with this message, otherwise it is null. + public FirebaseNotification Notification { get; private set; } + + /// Gets a flag indicating whether this message was opened by tapping a + /// notification in the OS system tray. If the message was received this way + /// this flag is set to true. + public bool NotificationOpened { get; private set; } + + /// Gets the priority level. Defined values are "normal" and "high". + /// By default messages are sent with normal priority. + public string Priority { get; private set; } + + /// Gets the binary payload. For webpush and non-json messages, this is the + /// body of the request entity. + public byte[] RawData { get; private set; } + + /// The Time To Live (TTL) for the message. + public System.TimeSpan TimeToLive { get; private set; } + + /// Gets or sets recipient of a message. + /// + /// For example it can be a registration token, a topic name, a IID or project + /// ID. + public string To { get; private set; } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose() { } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose(bool disposing) { } +} + +} // namespace Firebase.Messaging diff --git a/messaging/src/FirebaseMessaging.cs b/messaging/src/FirebaseMessaging.cs new file mode 100644 index 000000000..44e42ccd5 --- /dev/null +++ b/messaging/src/FirebaseMessaging.cs @@ -0,0 +1,186 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Firebase.Messaging { + +/// @brief Firebase Cloud Messaging API. +/// +/// Firebase Cloud Messaging allows you to send data from your server to your +/// users' devices, and receive messages from devices on the same connection +/// if you're using a XMPP server. +/// +/// The FCM service handles all aspects of queueing of messages and delivery +/// to client applications running on target devices. +public static class FirebaseMessaging { + + /// Enable or disable token registration during initialization of Firebase + /// Cloud Messaging. + /// + /// This token is what identifies the user to Firebase, so disabling this + /// avoids creating any new identity and automatically sending it to Firebase, + /// unless consent has been granted. + /// + /// If this setting is enabled, it triggers the token registration refresh + /// immediately. This setting is persisted across app restarts and overrides + /// the setting "firebase_messaging_auto_init_enabled" specified in your + /// Android manifest (on Android) or Info.plist (on iOS and tvOS). + /// + ///

By default, token registration during initialization is enabled. + /// + /// The registration happens before you can programmatically disable it, so + /// if you need to change the default, (for example, because you want to + /// prompt the user before FCM generates/refreshes a registration token on app + /// startup), add to your application’s manifest: + /// + /// @if NOT_DOXYGEN + /// + /// @else + /// @code + /// <meta-data android:name="firebase_messaging_auto_init_enabled" + /// android:value="false" /> + /// @endcode + /// @endif + /// + /// or on iOS or tvOS to your Info.plist: + /// + /// @if NOT_DOXYGEN + /// FirebaseMessagingAutoInitEnabled + /// + /// @else + /// @code + /// <key>FirebaseMessagingAutoInitEnabled</key> + /// <false/> + /// @endcode + /// @endif + public static bool TokenRegistrationOnInitEnabled { + get { + return FirebaseMessagingInternal.IsTokenRegistrationOnInitEnabled(); + } + set { + FirebaseMessagingInternal.SetTokenRegistrationOnInitEnabled(value); + } + } + + /// Enables or disables Firebase Cloud Messaging message delivery metrics + /// export to BigQuery. + /// + /// By default, message delivery metrics are not exported to BigQuery. Use + /// this method to enable or disable the export at runtime. In addition, you + /// can enable the export by adding to your manifest. Note that the run-time + /// method call will override the manifest value. + /// + /// @code + /// + /// @endcode + /// + /// @note This function is currently only implemented on Android, and has no + /// behavior on other platforms. + public static bool DeliveryMetricsExportedToBigQueryEnabled { + get { + return FirebaseMessagingInternal.DeliveryMetricsExportToBigQueryEnabled(); + } + set { + FirebaseMessagingInternal.SetDeliveryMetricsExportToBigQuery(value); + } + } + + /// @brief This creates a Firebase Installations ID, if one does not exist, and + /// sends information about the application and the device where it's running to + /// the Firebase backend. + /// + /// @return A task with the token. + public static System.Threading.Tasks.Task GetTokenAsync() { + return FirebaseMessagingInternal.GetTokenAsync(); + } + + /// @brief Deletes the default token for this Firebase project. + /// + /// Note that this does not delete the Firebase Installations ID that may have + /// been created when generating the token. See Installations.Delete() for + /// deleting that. + /// + /// @return A task that completes when the token is deleted. + public static System.Threading.Tasks.Task DeleteTokenAsync() { + return FirebaseMessagingInternal.DeleteTokenAsync(); + } + +#if DOXYGEN + /// Called on the client when a message arrives. + public static event System.EventHandler MessageReceived; +#else + public static event System.EventHandler MessageReceived { + add { + FirebaseMessagingInternal.MessageReceived += value; + } + remove { + FirebaseMessagingInternal.MessageReceived -= value; + } + } +#endif // DOXYGEN + +#if DOXYGEN + /// Called on the client when a registration token message arrives. + public static event System.EventHandler TokenReceived; +#else + public static event System.EventHandler TokenReceived { + add { + FirebaseMessagingInternal.TokenReceived += value; + } + remove { + FirebaseMessagingInternal.TokenReceived -= value; + } + } +#endif + + /// @brief Displays a prompt to the user requesting permission to display + /// notifications. + /// + /// The permission prompt only appears on iOS and tvOS. If the user has + /// already agreed to allow notifications, no prompt is displayed and the + /// returned future is completed immediately. + /// + /// @return A Task that completes when the notification prompt has been + /// dismissed. + public static System.Threading.Tasks.Task RequestPermissionAsync() { + return FirebaseMessagingInternal.RequestPermissionAsync(); + } + + /// @brief Subscribe to receive all messages to the specified topic. + /// + /// Subscribes an app instance to a topic, enabling it to receive messages + /// sent to that topic. + /// + /// @param[in] topic The name of the topic to subscribe. Must match the + /// following regular expression: `[a-zA-Z0-9-_.~%]{1,900}`. + public static System.Threading.Tasks.Task SubscribeAsync(string topic) { + return FirebaseMessagingInternal.SubscribeAsync(topic); + } + + /// @brief Unsubscribe from a topic. + /// + /// Unsubscribes an app instance from a topic, stopping it from receiving + /// any further messages sent to that topic. + /// + /// @param[in] topic The name of the topic to unsubscribe from. Must match the + /// following regular expression: `[a-zA-Z0-9-_.~%]{1,900}`. + public static System.Threading.Tasks.Task UnsubscribeAsync(string topic) { + return FirebaseMessagingInternal.UnsubscribeAsync(topic); + } +} + +} // namespace Firebase.Messaging diff --git a/messaging/src/FirebaseNotification.cs b/messaging/src/FirebaseNotification.cs new file mode 100644 index 000000000..647ab6740 --- /dev/null +++ b/messaging/src/FirebaseNotification.cs @@ -0,0 +1,160 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System.Collections.Generic; + +namespace Firebase.Messaging { + +/// @brief Data structure for parameters that are unique to the Android +/// implementation. +public sealed class AndroidNotificationParams { + internal static AndroidNotificationParams FromInternal(AndroidNotificationParamsInternal other) { + AndroidNotificationParams android = new AndroidNotificationParams(); + android.ChannelId = other.channel_id; + return android; + } + + /// The channel id that was provided when the message was sent. + public string ChannelId { get; private set; } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose() { } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose(bool disposing) { } +} + +/// Used for messages that display a notification. +/// +/// On android, this requires that the app is using the Play Services client +/// library. +public sealed class FirebaseNotification { + internal static FirebaseNotification FromInternal(FirebaseNotificationInternal other) { + FirebaseNotification notification = new FirebaseNotification(); + notification.Android = AndroidNotificationParams.FromInternal(other.android); + notification.Badge = other.badge; + notification.Body = other.body; + // Make a copy of the list, to not rely on the C++ memory lasting around + notification.BodyLocalizationArgs = new List(other.body_loc_args); + notification.BodyLocalizationKey = other.body_loc_key; + notification.ClickAction = other.click_action; + notification.Color = other.color; + notification.Icon = other.icon; + notification.Sound = other.sound; + notification.Tag = other.tag; + notification.Title = other.title; + // Make a copy of the list, to not rely on the C++ memory lasting around + notification.TitleLocalizationArgs = new List(other.title_loc_args); + notification.TitleLocalizationKey = other.title_loc_key; + return notification; + } + + /// Android-specific data to show. + public AndroidNotificationParams Android { get; private set; } + + /// Indicates the badge on the client app home icon. iOS and tvOS only. + public string Badge { get; private set; } + + /// Indicates notification body text. + public string Body { get; private set; } + + /// Indicates the string value to replace format specifiers in body string + /// for localization. + /// + /// On iOS and tvOS, this corresponds to "loc-args" in APNS payload. + /// + /// On Android, these are the format arguments for the string resource. For + /// more information, see [Formatting strings][1]. + /// + /// [1]: + /// https://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling + public System.Collections.Generic.IEnumerable BodyLocalizationArgs { get; private set; } + + /// Indicates the key to the body string for localization. + /// + /// On iOS and tvOS, this corresponds to "loc-key" in APNS payload. + /// + /// On Android, use the key in the app's string resources when populating this + /// value. + public string BodyLocalizationKey { get; private set; } + + /// The action associated with a user click on the notification. + /// + /// On Android, if this is set, an activity with a matching intent filter is + /// launched when user clicks the notification. + /// + /// If set on iOS or tvOS, corresponds to category in APNS payload. + public string ClickAction { get; private set; } + + /// Indicates color of the icon, expressed in \#rrggbb format. Android only. + public string Color { get; private set; } + + /// Indicates notification icon. Sets value to myicon for drawable resource + /// myicon. + public string Icon { get; private set; } + + /// Indicates a sound to play when the device receives the notification. + /// Supports default, or the filename of a sound resource bundled in the + /// app. + /// + /// Android sound files must reside in /res/raw/, while tvOS and iOS sound + /// files can be in the main bundle of the client app or in the + /// Library/Sounds folder of the app’s data container. + public string Sound { get; private set; } + + /// Indicates whether each notification results in a new entry in the + /// notification drawer on Android. If not set, each request creates a new + /// notification. If set, and a notification with the same tag is already + /// being shown, the new notification replaces the existing one in the + /// notification drawer. + public string Tag { get; private set; } + + /// Indicates notification title. This field is not visible on tvOS, iOS + /// phones and tablets. + public string Title { get; private set; } + + /// Indicates the string value to replace format specifiers in title string + /// for localization. + /// + /// On iOS and tvOS, this corresponds to "title-loc-args" in APNS payload. + /// + /// On Android, these are the format arguments for the string resource. For + /// more information, see [Formatting strings][1]. + /// + /// [1]: + /// https://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling + public System.Collections.Generic.IEnumerable TitleLocalizationArgs { get; private set; } + + /// Indicates the key to the title string for localization. + /// + /// On iOS and tvOS, this corresponds to "title-loc-key" in APNS payload. + /// + /// On Android, use the key in the app's string resources when populating this + /// value. + public string TitleLocalizationKey { get; private set; } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose() { } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose(bool disposing) { } +} + +} // namespace Firebase.Messaging diff --git a/messaging/src/MessagingEventArgs.cs b/messaging/src/MessagingEventArgs.cs index f2818d8e2..857b9588f 100644 --- a/messaging/src/MessagingEventArgs.cs +++ b/messaging/src/MessagingEventArgs.cs @@ -19,8 +19,9 @@ namespace Firebase.Messaging { /// Event argument for the MessageReceived event containing the message data. public sealed class MessageReceivedEventArgs : System.EventArgs { public MessageReceivedEventArgs(FirebaseMessage msg) { - this.Message = msg; + this.Message = msg; } + /// Message data passed to the MessageReceived event handler. public FirebaseMessage Message { get; set; } } diff --git a/messaging/src/MessagingOptions.cs b/messaging/src/MessagingOptions.cs new file mode 100644 index 000000000..aaf2ab578 --- /dev/null +++ b/messaging/src/MessagingOptions.cs @@ -0,0 +1,39 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Firebase.Messaging { + +/// @brief A class to configure the behavior of Firebase Cloud Messaging. +/// +/// This class contains various configuration options that control some of +/// Firebase Cloud Messaging's behavior. +public sealed class MessagingOptions { + public MessagingOptions() { } + + public bool SuppressNotificationPermissionPrompt { + get; set; + } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose() { } + + /// @deprecated No longer needed, will be removed in the future. + [System.Obsolete("No longer needed, will be removed in the future.")] + public void Dispose(bool disposing) { } +} + +} // namespace Firebase.Messaging diff --git a/messaging/src/swig/messaging.i b/messaging/src/swig/messaging.i index d58328335..1bf5a488b 100644 --- a/messaging/src/swig/messaging.i +++ b/messaging/src/swig/messaging.i @@ -8,7 +8,7 @@ // Swig Lint doesn't support C# //swiglint: disable -%module FirebaseMessaging +%module FirebaseMessagingInternal #ifdef USE_EXPORT_FIX // Generate a function that we can reference to force linker @@ -18,13 +18,11 @@ %{#include "app/src/export_fix.h"%} #endif -%pragma(csharp) moduleclassmodifiers="public sealed class" +%pragma(csharp) moduleclassmodifiers="internal sealed class" %feature("flatnested"); -%{ -#include "app/src/callback.h" -#include "messaging/src/include/firebase/messaging.h" -%} +// Change the default class modifier to internal, so that new classes are not accidentally exposed +%typemap(csclassmodifiers) SWIGTYPE "internal class" %import "app/src/swig/app.i" %include "app/src/swig/future.i" @@ -49,12 +47,15 @@ } %} +// Start of the code added to the C++ module file %{ #include #include +#include "app/src/callback.h" #include "app/src/include/firebase/internal/mutex.h" #include "app/src/log.h" +#include "messaging/src/include/firebase/messaging.h" namespace firebase { namespace messaging { @@ -237,34 +238,12 @@ void SendPendingEvents() { ListenerImpl::SendPendingEvents(); } -// Copy the notification out of a message. -void* MessageCopyNotification(void* message) { - firebase::messaging::Notification *notification = - static_cast(message)->notification; - firebase::messaging::Notification *notification_copy = nullptr; - if (notification) { - notification_copy = new firebase::messaging::Notification; - *notification_copy = *notification; - } - return notification_copy; -} - -// Copy the notification out of a message. -void* NotificationCopyAndroidNotificationParams(void* notification) { - firebase::messaging::AndroidNotificationParams *android = - static_cast(notification)->android; - firebase::messaging::AndroidNotificationParams *android_copy = nullptr; - if (android) { - android_copy = new firebase::messaging::AndroidNotificationParams; - *android_copy = *android; - } - return android_copy; -} - } // messaging } // firebase -%} +%} // End of code added to the C++ module file + +// Start of the code added to the C# module file %pragma(csharp) modulecode=%{ // Forwards message and token received events from ListenerImpl to // Listener.MessageReceivedDelegateMethod and @@ -315,8 +294,8 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { // Setup callbacks from ListenerImpl C++ class to this object. private Listener() { - FirebaseMessaging.SetListenerCallbacks(messageReceivedDelegate, - tokenReceivedDelegate); + FirebaseMessagingInternal.SetListenerCallbacks(messageReceivedDelegate, + tokenReceivedDelegate); } ~Listener() { Dispose(); } @@ -326,7 +305,7 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { lock (typeof(Listener)) { if (listener == this) { System.Diagnostics.Debug.Assert(app != null); - FirebaseMessaging.SetListenerCallbacks(null, null); + FirebaseMessagingInternal.SetListenerCallbacks(null, null); listener = null; app = null; } @@ -339,10 +318,12 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { private static int MessageReceivedDelegateMethod(System.IntPtr message) { return ExceptionAggregator.Wrap(() => { // Use a local copy so another thread cannot unset this before we use it. - var handler = FirebaseMessaging.MessageReceivedInternal; + var handler = FirebaseMessagingInternal.MessageReceivedInternal; if (handler != null) { + FirebaseMessageInternal messageInternal = new FirebaseMessageInternal(message, true); handler(null, new Firebase.Messaging.MessageReceivedEventArgs( - new FirebaseMessage(message, true))); + FirebaseMessage.FromInternal(messageInternal))); + messageInternal.Dispose(); return 1; } return 0; @@ -355,7 +336,7 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { private static void TokenReceivedDelegateMethod(string token) { ExceptionAggregator.Wrap(() => { // Use a local copy so another thread cannot unset this before we use it. - var handler = FirebaseMessaging.TokenReceivedInternal; + var handler = FirebaseMessagingInternal.TokenReceivedInternal; if (handler != null) { handler(null, new Firebase.Messaging.TokenReceivedEventArgs(token)); } @@ -380,10 +361,10 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { } else { Listener.Destroy(); } - FirebaseMessaging.SetListenerCallbacksEnabled( + FirebaseMessagingInternal.SetListenerCallbacksEnabled( messageReceivedSet, tokenReceivedSet); if (messageReceivedSet || tokenReceivedSet) { - FirebaseMessaging.SendPendingEvents(); + FirebaseMessagingInternal.SendPendingEvents(); } } } @@ -392,7 +373,7 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { private static Listener listener; // Create the listener and hold a reference. - static FirebaseMessaging() { + static FirebaseMessagingInternal() { listener = Listener.Create(); } @@ -400,101 +381,6 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { /// @return FirebaseApp instance referenced by this module. static Firebase.FirebaseApp App { get { return Listener.App; } } - private FirebaseMessaging() { } - - /// Enable or disable token registration during initialization of Firebase - /// Cloud Messaging. - /// - /// This token is what identifies the user to Firebase, so disabling this - /// avoids creating any new identity and automatically sending it to Firebase, - /// unless consent has been granted. - /// - /// If this setting is enabled, it triggers the token registration refresh - /// immediately. This setting is persisted across app restarts and overrides - /// the setting "firebase_messaging_auto_init_enabled" specified in your - /// Android manifest (on Android) or Info.plist (on iOS and tvOS). - /// - ///

By default, token registration during initialization is enabled. - /// - /// The registration happens before you can programmatically disable it, so - /// if you need to change the default, (for example, because you want to - /// prompt the user before FCM generates/refreshes a registration token on app - /// startup), add to your application’s manifest: - /// - /// @if NOT_DOXYGEN - /// - /// @else - /// @code - /// <meta-data android:name="firebase_messaging_auto_init_enabled" - /// android:value="false" /> - /// @endcode - /// @endif - /// - /// or on iOS or tvOS to your Info.plist: - /// - /// @if NOT_DOXYGEN - /// FirebaseMessagingAutoInitEnabled - /// - /// @else - /// @code - /// <key>FirebaseMessagingAutoInitEnabled</key> - /// <false/> - /// @endcode - /// @endif - public static bool TokenRegistrationOnInitEnabled { - get { - return FirebaseMessaging.IsTokenRegistrationOnInitEnabledInternal(); - } - set { - FirebaseMessaging.SetTokenRegistrationOnInitEnabledInternal(value); - } - } - - /// Enables or disables Firebase Cloud Messaging message delivery metrics - /// export to BigQuery. - /// - /// By default, message delivery metrics are not exported to BigQuery. Use - /// this method to enable or disable the export at runtime. In addition, you - /// can enable the export by adding to your manifest. Note that the run-time - /// method call will override the manifest value. - /// - /// @code - /// - /// @endcode - /// - /// @note This function is currently only implemented on Android, and has no - /// behavior on other platforms. - public static bool DeliveryMetricsExportedToBigQueryEnabled { - get { - return FirebaseMessaging.DeliveryMetricsExportToBigQueryEnabledInternal(); - } - set { - FirebaseMessaging.SetDeliveryMetricsExportToBigQueryInternal(value); - } - } - - /// @brief This creates a Firebase Installations ID, if one does not exist, and - /// sends information about the application and the device where it's running to - /// the Firebase backend. - /// - /// @return A task with the token. - public static System.Threading.Tasks.Task GetTokenAsync() { - return FirebaseMessaging.GetTokenInternalAsync(); - } - - /// @brief Deletes the default token for this Firebase project. - /// - /// Note that this does not delete the Firebase Installations ID that may have - /// been created when generating the token. See Installations.Delete() for - /// deleting that. - /// - /// @return A task that completes when the token is deleted. - public static System.Threading.Tasks.Task DeleteTokenAsync() { - return FirebaseMessaging.DeleteTokenInternalAsync(); - } - // NOTE: MessageReceivedEventArgs is defined in // firebase/messaging/client/unity/src/MessagingEventArgs.cs. #if DOXYGEN @@ -543,384 +429,21 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { } #endif // DOXYGEN -%} - -%typemap(cscode) firebase::messaging::Message %{ - /// The Time To Live (TTL) for the message. - /// - /// This field is only used for downstream messages received through - /// FirebaseMessaging.MessageReceived(). - public System.TimeSpan TimeToLive { - get { - return System.TimeSpan.FromSeconds(TimeToLiveInternal); - } - } - - private static System.DateTime UnixEpochUtc = - new System.DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); - - /// UTC time when the message was sent. - internal System.DateTime SentTime { - get { - return UnixEpochUtc.AddMilliseconds(SentTimeInternal); - } - } - - /// Optional notification to show. This only set if a notification was - /// received with this message, otherwise it is null. - /// - /// This field is only used for downstream messages received through - /// FirebaseMessaging.MessageReceived. - public FirebaseNotification Notification { - get { - System.IntPtr cPtr = - FirebaseMessaging.MessageCopyNotification(swigCPtr.Handle); - if (cPtr != System.IntPtr.Zero) { - return new FirebaseNotification(cPtr, true); - } - return null; - } - } - - /// The link into the app from the message. - /// - /// This field is only used for downstream messages. - public System.Uri Link { - get { - return Firebase.FirebaseApp.UrlStringToUri(LinkInternal); - } - } +%} // End of code added to the C# module file - /// Gets the binary payload. For webpush and non-json messages, this is the - /// body of the request entity. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public byte[] RawData { - get { - byte[] array = new byte[RawDataInternal.Count]; - RawDataInternal.CopyTo(array); - return array; - } - } -%} - -%typemap(cscode) firebase::messaging::Notification %{ - /// Android-specific data to show. - public AndroidNotificationParams Android { - get { - System.IntPtr cPtr = - FirebaseMessaging.NotificationCopyAndroidNotificationParams( - swigCPtr.Handle); - if (cPtr != System.IntPtr.Zero) { - return new AndroidNotificationParams(cPtr, true); - } - return null; - } - } -%} - -%typemap(csclassmodifiers) firebase::messaging::Message - "public sealed class"; -%rename(FirebaseMessage) firebase::messaging::Message; -%typemap(csclassmodifiers) firebase::messaging::Notification - "public sealed class"; -%rename(FirebaseNotification) firebase::messaging::Notification; - -%rename(IsTokenRegistrationOnInitEnabledInternal) - IsTokenRegistrationOnInitEnabled; -%rename(SetTokenRegistrationOnInitEnabledInternal) - SetTokenRegistrationOnInitEnabled; - -%rename(DeliveryMetricsExportToBigQueryEnabledInternal) - DeliveryMetricsExportToBigQueryEnabled; -%rename(SetDeliveryMetricsExportToBigQueryInternal) - SetDeliveryMetricsExportToBigQuery; - -%rename(GetTokenInternalAsync) - GetToken; -%rename(DeleteTokenInternalAsync) - DeleteToken; - -%typemap(csclassmodifiers) firebase::messaging::MessagingOptions - "public sealed class"; -%rename(SuppressNotificationPermissionPrompt) - suppress_notification_permission_prompt; - -%csmethodmodifiers firebase::messaging::IsTokenRegistrationOnInitEnabled() - "internal" -%csmethodmodifiers firebase::messaging::SetTokenRegistrationOnInitEnabled(bool) - "internal" - -%csmethodmodifiers firebase::messaging::DeliveryMetricsExportToBigQueryEnabled() - "internal" -%csmethodmodifiers firebase::messaging::SetDeliveryMetricsExportToBigQuery(bool) - "internal" - -%csmethodmodifiers firebase::messaging::GetToken() - "internal" -%csmethodmodifiers firebase::messaging::DeleteToken() - "internal" +// Rename the generated classes to *Internal +%rename(FirebaseMessageInternal) firebase::messaging::Message; +%rename(FirebaseNotificationInternal) firebase::messaging::Notification; +%rename(AndroidNotificationParamsInternal) firebase::messaging::AndroidNotificationParams; +%rename(MessagingOptionsInternal) firebase::messaging::MessagingOptions; // Messaging has a lot of read-only properties, so make all immutable // and call out the mutable ones. %immutable; -%feature("immutable","0") firebase::messaging::Message::data; -%feature("immutable","0") firebase::messaging::Message::message_id; -%feature("immutable","0") firebase::messaging::Message::to; %feature("immutable","0") firebase::messaging::MessagingOptions::suppress_notification_permission_prompt; -// The following docs are all here instead of the header due to b/35780150. - -%csmethodmodifiers firebase::messaging::Message::from " - /// Gets the authenticated ID of the sender. This is a project number in most cases. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::to " - /// Gets or sets recipient of a message. - /// - /// For example it can be a registration token, a topic name, a IID or project - /// ID. - /// - /// This field is used for both upstream messages sent with - /// firebase::messaging:Send() and downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. For upstream messages, - /// PROJECT_ID@gcm.googleapis.com or the more general IID format are accepted. - public" - -%csmethodmodifiers firebase::messaging::Message::collapse_key " - /// Gets the collapse key used for collapsible messages. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::data " - /// Gets or sets the metadata, including all original key/value pairs. - /// Includes some of the HTTP headers used when sending the message. `gcm`, - /// `google` and `goog` prefixes are reserved for internal use. - /// - /// This field is used for both upstream messages sent with - /// firebase::messaging::Send() and downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::message_id " - /// Gets or sets the message ID. This can be specified by sender. Internally a - /// hash of the message ID and other elements will be used for storage. The ID - /// must be unique for each topic subscription - using the same ID may result - /// in overriding the original message or duplicate delivery. - /// - /// This field is used for both upstream messages sent with - /// firebase::messaging::Send() and downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::message_type " - /// Gets the message type, equivalent with a content-type. - /// CCS uses \"ack\", \"nack\" for flow control and error handling. - /// \"control\" is used by CCS for connection control. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::priority " - /// Gets the priority level. Defined values are \"normal\" and \"high\". - /// By default messages are sent with normal priority. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::time_to_live " - /// Gets the time to live, in seconds. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::error " - /// Gets the error code. Used in \"nack\" messages for CCS, and in responses - /// from the server. - /// See the CCS specification for the externally-supported list. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::error_description " - /// Gets the human readable details about the error. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::notification " - /// Gets the optional notification to show. This only set if a notification - /// was received with this message, otherwise it is null. - /// - /// The notification is only guaranteed to be valid during the call to the - /// @ref FirebaseMessaging.MessageReceived event. If you need to keep it - /// around longer you will need to make a copy of either the FirebaseMessage - /// or FirebaseNotification. Copying the FirebaseMessage object implicitly - /// makes a deep copy of the FirebaseNotification which is owned by the - /// FirebaseMessage.Message. - /// - /// This field is only used for downstream messages received through the - /// @ref FirebaseMessaging.MessageReceived event. - public" - -%csmethodmodifiers firebase::messaging::Message::notification_opened " - /// Gets a flag indicating whether this message was opened by tapping a - /// notification in the OS system tray. If the message was received this way - /// this flag is set to true. - public" - -// Make snake_case properties CamelCase. -// Message -%rename(CollapseKey) collapse_key; -%rename(Data) data; -%rename(Error) error; -%rename(ErrorDescription) error_description; -%rename(From) from; -%rename(MessageId) message_id; -%rename(MessageType) message_type; -%rename(Priority) priority; -%rename(RawDataInternal) raw_data; -%rename(NotificationOpened) notification_opened; -%csmethodmodifiers firebase::messaging::Message::time_to_live "internal"; -%rename(TimeToLiveInternal) time_to_live; -%rename(SentTimeInternal) sent_time; -// Hide the string link field as we expose it as a URI in the C# interface. -%rename(LinkInternal) link; -%csmethodmodifiers firebase::messaging::Message::link "internal"; -// Notification is manually copied out of the Message so the proxy doesn't -// reference memory in firebase::messaging::Message. -%ignore firebase::messaging::Message::notification; -// AndroidNotificationParams is manually copied out of the Notification so the -// proxy doesn't reference memory in firebase::messaging::Notification. -%ignore firebase::messaging::Notification::android; -%rename(To) to; -// No reason to export the PollableListener to C# +// Ignore functions and classes that we don't need to expose to C# %ignore firebase::messaging::PollableListener; - -// The following docs are all here instead of the header due to b/35780150. - -%csmethodmodifiers firebase::messaging::Notification::title " - /// Indicates notification title. This field is not visible on tvOS, iOS - /// phones and tablets. - public" - -%csmethodmodifiers firebase::messaging::Notification::body " - /// Indicates notification body text. - public" - -%csmethodmodifiers firebase::messaging::Notification::icon " - /// Indicates notification icon. Sets value to myicon for drawable resource - /// myicon. - public" - -%csmethodmodifiers firebase::messaging::Notification::sound " - /// Indicates a sound to play when the device receives the notification. - /// Supports default, or the filename of a sound resource bundled in the - /// app. - /// - /// Android sound files must reside in /res/raw/, while tvOS and iOS sound - /// files can be in the main bundle of the client app or in the - /// Library/Sounds folder of the app’s data container. - public" - -%csmethodmodifiers firebase::messaging::Notification::badge " - /// Indicates the badge on the client app home icon. iOS and tvOS only. - public" - -%csmethodmodifiers firebase::messaging::Notification::tag " - /// Indicates whether each notification results in a new entry in the - /// notification drawer on Android. If not set, each request creates a new - /// notification. If set, and a notification with the same tag is already - /// being shown, the new notification replaces the existing one in the - /// notification drawer. - public" - -%csmethodmodifiers firebase::messaging::Notification::color " - /// Indicates color of the icon, expressed in \#rrggbb format. Android only. - public" - -%csmethodmodifiers firebase::messaging::Notification::click_action " - /// The action associated with a user click on the notification. - /// - /// On Android, if this is set, an activity with a matching intent filter is - /// launched when user clicks the notification. - /// - /// If set on iOS or tvOS, corresponds to category in APNS payload. - public" - -%csmethodmodifiers firebase::messaging::Notification::body_loc_key " - /// Indicates the key to the body string for localization. - /// - /// On iOS and tvOS, this corresponds to \"loc-key\" in APNS payload. - /// - /// On Android, use the key in the app's string resources when populating this - /// value. - public" - -%csmethodmodifiers firebase::messaging::Notification::body_loc_args " - /// Indicates the string value to replace format specifiers in body string - /// for localization. - /// - /// On iOS and tvOS, this corresponds to \"loc-args\" in APNS payload. - /// - /// On Android, these are the format arguments for the string resource. For - /// more information, see [Formatting strings][1]. - /// - /// [1]: - /// https://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling - public" - -%csmethodmodifiers firebase::messaging::Notification::title_loc_key " - /// Indicates the key to the title string for localization. - /// - /// On iOS and tvOS, this corresponds to \"title-loc-key\" in APNS payload. - /// - /// On Android, use the key in the app's string resources when populating this - /// value. - public" - -%csmethodmodifiers firebase::messaging::Notification::title_loc_args " - /// Indicates the string value to replace format specifiers in title string - /// for localization. - /// - /// On iOS and tvOS, this corresponds to \"title-loc-args\" in APNS payload. - /// - /// On Android, these are the format arguments for the string resource. For - /// more information, see [Formatting strings][1]. - /// - /// [1]: - /// https://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling - public" - - -// Notification -%rename(Badge) firebase::messaging::Notification::badge; -%rename(Body) firebase::messaging::Notification::body; -%rename(BodyLocalizationArgs) firebase::messaging::Notification::body_loc_args; -%rename(BodyLocalizationKey) firebase::messaging::Notification::body_loc_key; -%rename(ClickAction) firebase::messaging::Notification::click_action; -%rename(Color) firebase::messaging::Notification::color; -%rename(Icon) firebase::messaging::Notification::icon; -%rename(Sound) firebase::messaging::Notification::sound; -%rename(Tag) firebase::messaging::Notification::tag; -%rename(Title) firebase::messaging::Notification::title; -%rename(TitleLocalizationArgs) firebase::messaging::Notification::title_loc_args; -%rename(TitleLocalizationKey) firebase::messaging::Notification::title_loc_key; - -// AndroidNotificationParams -%rename(ChannelId) firebase::messaging::AndroidNotificationParams::channel_id; - %ignore firebase::messaging::Listener; %ignore firebase::messaging::Initialize; %ignore firebase::messaging::Terminate; @@ -931,11 +454,12 @@ void* NotificationCopyAndroidNotificationParams(void* notification) { // Map callback function types to delegates. SWIG_MAP_CFUNC_TO_CSDELEGATE( firebase::messaging::ListenerImpl::MessageReceivedCallback, - Firebase.Messaging.FirebaseMessaging.Listener.MessageReceivedDelegate) + Firebase.Messaging.FirebaseMessagingInternal.Listener.MessageReceivedDelegate) SWIG_MAP_CFUNC_TO_CSDELEGATE( firebase::messaging::ListenerImpl::TokenReceivedCallback, - Firebase.Messaging.FirebaseMessaging.Listener.TokenReceivedDelegate) + Firebase.Messaging.FirebaseMessagingInternal.Listener.TokenReceivedDelegate) +// Declare the functions we added to the C++ module that we want to generate C# for namespace firebase { namespace messaging { %csmethodmodifiers SetListenerCallbacks "private"; @@ -947,10 +471,6 @@ void SetListenerCallbacksEnabled(bool message_callback_enabled, bool token_callback_enabled); %csmethodmodifiers SendPendingEvents "private"; void SendPendingEvents(); -%csmethodmodifiers MessageCopyNotification "internal"; -void* MessageCopyNotification(void* message); -%csmethodmodifiers NotificationCopyAndroidNotificationParams "internal"; -void* NotificationCopyAndroidNotificationParams(void* notification); } // messaging } // firebase