Since 2015, Conquest! has sent alerts using email. This has worked fine for years but when I first created a UI client for mobile devices, I've wanted to add push notifications. When I looked at this a few years ago, notification services cost money and the integration seemed complex.
But recently I was chatting with ChatGPT and asked about adding notifications to Conquest!. It told me about Firebase and its available free messaging service and after sharing some code samples, we were off to the races. Part 1: Firebase Project Creating a new account and project inside Firebase was easy. I created a service account, ensuring that I downloaded the service account JSON file when prompted as you can't retrieve it again later. The service account information is used to request the access token to send notifications (more on that below). Next I added my iOS and Android applications to my Firebase project and downloaded two additional configuration files, which are required for integration with Unity. Part 2: Server The Conquest! server is the brains of the entire game. In order to send notifications to clients, the server must get an OAUTH2 access token, which expires every hour, from Firebase. The game server is written in C which is great for performance but as ChatGPT said "It’s doable but not fun. C wasn’t made for working with JSON + Base64 + JWT + RS256 + HTTPS, so expect manual plumbing." After reviewing the pseudocode ChatGPT provided, I decided to go with the alternative suggestion, creating a Python script that the C server would call to receive the access token. import google.auth from google.oauth2 import service_account import google.auth.transport.requests import sys # The OAuth 2.0 scope required to send FCM messages SCOPES = ["https://www.googleapis.com/auth/firebase.messaging"] def get_access_token(service_account_file): credentials = service_account.Credentials.from_service_account_file( service_account_file, scopes=SCOPES ) auth_req = google.auth.transport.requests.Request() credentials.refresh(auth_req) return credentials.token if len(sys.argv) < 2: print("Usage: fcm_token.py <path_to_service_account_json>") sys.exit(1) service_account_file = sys.argv[1] token = get_access_token(service_account_file) print(token) This required installing the "google-auth" Python module on both my development and production servers. Now I had the token but I still had to construct the JSON messages. Fortunately, I switched from XML to JSON last year so the server was already using the JSON-C library. I also recently switched from using mailx to send emails to using curl. Both of these changes helped with the development of the new notification system. The server keeps the access token in memory and checks its age to see if its greater than 55 minutes old. If so, it requests a new one by opening a pipe and invoking the Python script above. Next it constructs the notification request using JSON-C and then sends it to Firebase using curl. When a client connects to the server and provides its token, this is stored in a device structure. Part 3: Unity3d The first item to do was install the Firebase SDK into Unity. Since the notifications are coming from the server and the client isn't receiving them directly, I only needed to import FirebaseMessaging.unitypackage. I placed the the application configuration files downloaded from Firebase in Assets/StreamingAssets (Android) and the root Assets folder (iOS). Next I had to add some code in my application to initialize Firebase and receive the client token. I needed to send this token to the server so it knew where to send the notifications. When I first ran the code in the Unity editor I received this error: Database URL not set in the Firebase config. After some back and forth with ChatGPT, it was determined that the URL had to be included in the Android and iOS configuration files i.e., "databaseURL": "https://your-project-id.firebaseio.com" After correcting that error, I was able to run the code in the Editor but not actually test the notifications. Part 4: iOS Naturally, building for iOS was the most complex. From the Apple developer portal, I had to create a new p8 Key used for push notifications and add that to my Firebase project. My development box runs Windows, so after Unity was done I transferred to a Mac. Unity doesn't include all the framework files required to build in XCode (why?!?). In order to add those, I needed to install "CocoaPods". Installing this the first time didn't work (of course) because most Macs ship with an old version of Ruby. In order to update it, I had to use Homebrew, which also wasn't installed. So first I had to install Homebrew and then update Ruby (and adjust my PATH environment variable to use the new versions and tools). Finally, I could install CocoaPods. All of this was done so I could execute "pod install" from the Mac inside the Unity project folder to add all the framework files Firebase required. I opened the xcworkspace file that pod created in XCode. Certain key capabilities cannot be set inside Unity, so I had to add "Background Tasks" (Remote notifications) and "Push Notifications" to the project. Once all of that was done, I was finally able to build the iOS client. Whew! Part 5: Android By contrast, building for Android was much easier. In the Build Settings I had to ensure Custom Main Gradle Template and Custom Launcher Gradle Template were selected. I had to edit the mainTemplate.gradle and replace "**PACKAGING**" with "**PACKAGING_OPTIONS**" and add "**BUILT_IN_EXTRAS**" and "**EXTERNAL_SOURCES**" at the bottom. The Android build completed on Windows but when I first tested no notification showed up. This is because by default Android suppresses notifications if the app is open. Once my tester closed the Conquest! application, the notification worked! There is a workaround to show notifications when the application is open but I decided to leave it as is for now. Conclusion Working with ChatGPT during this process was invaluable. I could have done this with Google searches but it would have taken far more time as I tried to piecemeal solutions from across the Internet. ChatGPT isn't perfect, however, and there were a few times where it led me down an incorrect path. But overall, it is a great tool and I finally have push notifications working for Conquest!. Huzzah!
0 Comments
|
AuthorJames has been working on Conquest! since 1993. Archives
May 2025
Categories |