Flutter: Firebase In-App Messaging "Test on device" message not received
- Conclusion: Re-executing flutterfire configure and registering SHA-1 in Firebase/GCP
- Articles that I referred to
- There doesn't seem to be a problem with the implementation, but the test message doesn't show up
- Firebase In-App Messaging API is already enabled
- Realizing that the Firebase Installations Service is not working
- Noticed that I had set API key restrictions
- Some considerations (key restrictions, save for reflection, registration of SHA-1 for release)
- Summary
Conclusion: Re-executing flutterfire configure and registering SHA-1 in Firebase/GCP
Flutter Errors & Bugs Diary, May 7, 2023
While implementing Firebase In-App Messaging (FIAM), which allows you to send messages while the app is running, the test message was not displayed in the debug build of the app on Android.
It was displayed on iOS, but not on either the actual Android device or the emulator.
I had quite a hard time solving the problem with just the information available on the internet and from ChatGPT, so I've documented the process.
Articles that I referred to
The official website explains as follows.
The relatively new Japanese tutorial on the basic implementation method is as follows. I found it very helpful.
I had finished the basic Firebase settings organized in the following article (in Japanese), and tried to implement it based on the above articles.
There doesn't seem to be a problem with the implementation, but the test message doesn't show up
If the Firebase settings are complete, the settings on the Flutter side should be simple. If you don't set detailed conditions, you should only need to register the package below in 'pubspec.yaml', run 'pub get', and import it in the code.
import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart';
However, to send a message to the test device, you need the 'Firebase Installation ID' (FID) of the test device.
There seem to be various ways to obtain the FID. In my case, I decided to introduce the package below and use 'debugPrint' in the main function to check it on the console.
import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart'; import 'package:firebase_app_installations/firebase_app_installations.dart'; Future<void> main() async{ // This is necessary when performing asynchronous processing in the main function WidgetsFlutterBinding.ensureInitialized(); // Firebase initialization process await Firebase.initializeApp(); // FID retrieval and console display (for test messages) String fidO = await FirebaseInstallations.instance.getId(); debugPrint('FID : $fidO'); runApp(MyApp()); }
Once the FID is confirmed, you should press "Test on device" on the FIAM management screen on Firebase, register the FID and test send, and the message should be displayed (you need to deactivate and activate the app once), but no matter how many times I tried, it was not displayed.
Firebase In-App Messaging API is already enabled
When I looked up reasons why the message might not be displayed on the internet, I often found information about cases where the following error appears in the console.
W/FIAM.Headless(####): Service fetch error: PERMISSION_DENIED: Firebase In-App Messaging API has not been used in project XXXXXXXXX before or it is disabled.
In this case, it seems to be solved by enabling the "Firebase In-App Messaging API" on the GCP (Google Cloud Platform) screen, but in my case, it was already enabled and the above error was not displayed.
Realizing that the Firebase Installations Service is not working
After sending the test message from Firebase, I noticed that the following message was displayed in the console when the app in the debug build was deactivated and then activated.
I/FIAM.Headless(#####): went foreground I/FIAM.Display(#####): Binding to activity: MainActivity I/FIAM.Headless(#####): Setting display event component ...(omission)... I/FIAM.Headless(#####): Forcing fetch from service rather than cache. Test Device: false | App Fresh Install: true I/FIAM.Headless(#####): Recoverable exception while reading cache: /data/user/0/########/files/fiam_impressions_store_file: open failed: ENOENT (No such file or directory) ...(omission)... W/FIAM.Headless(#####): Service fetch error: Firebase Installations Service is unavailable. Please try again later.
The last two sentences ("No such file or directory" and "Service fetch error") seemed to be related to this issue.
When I asked ChatGPT for its opinion, it advised me that the last sentence was the problem, and gave me the following advice (there were other comments as well, but they turned out to be irrelevant in subsequent verification, so they are omitted here).
- The 'Firebase Installations Service is unavailable. Please try again later.' indicates a situation where the Firebase Installations Service (FIS) is not available. If FIS is unavailable, there may be cases where Firebase In-App Messaging (FIAM) does not operate correctly.
- You should make sure that the Firebase configuration file (google-services.json) is properly placed within your project.
Looking at the first point (cause), indeed, looking at the explanation from Firebase official, it seems that "Firebase Installations Service" (FIS) is used internally when operating FIAM, so if FIS is "unavailable", it makes sense that there would be a problem.
Also, regarding the second point (countermeasure), it seems that ChatGPT's answer is based on information up to September 2021, and the current Firebase no longer requires the placement of "google-services.json".
So, I understood that the equivalent work would be to log in to Firebase from the terminal, execute "flutterfire configure", and update "firebase_options.dart".
About this point, as stated in the following Firebase official explanation,
When you start using a new Firebase service or product, you need to re-run "flutterfire configure".
So, it seems necessary even after introducing FIAM. So, after executing "flutterfire configure" and updating "firebase_options.dart", I tried to execute "Test on Device" again, but the test message still did not display...
The same error message continues to be displayed on the console...
Noticed that I had set API key restrictions
When I searched the internet for "Firebase Installations Service is unavailable" and "Service fetch error", I found the following Q&A article.
Although it is an article from more than a year ago,
"FIAM messages are not displayed even after updating google-services.json"
the content was exactly the same as my situation.
Looking at the content of the answer with a solution mark (green check), it seems that appropriate handling of API restrictions is necessary.
Looking at the GitHub page linked in the answer, It says
you need to make sure that the API key used in your app is whitelisted for the Firebase Installation API.
Also, in another article I found, it explained that,
"If you are using API key restrictions for the API key that your application uses, you need to extend those restrictions to allow the new Firebase Installation Service at firebaseinstallations.googleapis.com to be used."
So I went to the management screen of the GCP (Google Cloud Platform) for the target app and went to
"APIs and Services" → "Credentials" → "API Keys" → "Android key" → "Edit API key" screen
and confirmed that the use of the API key was restricted to only the specified Android apps (I had forgotten that I had set this restriction for security reasons).
Normally, I should have had to register the package name of the app and the fingerprint (SHA-1) of the debug certificate, but I hadn't done this.
※ I had only registered the fingerprint of the release certificate, which can be confirmed on the Google Play Console.
Therefore, it seems that in the app built for debugging, the use of the "Firebase Installations Service" was rejected by the authentication, and FIAM could not work.
Immediately, I executed the following command from the terminal, displayed the fingerprint (SHA-1) of the debug certificate, and registered it in the designated places in GCP and Firebase.
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
When I sent a test message from FIAM's "Test on Device", the message finally started to be displayed in the app.
Some considerations (key restrictions, save for reflection, registration of SHA-1 for release)
Consideration 1:
In my case, I did not restrict the usable API keys themselves, but if you do, you may need to add the FIAM API (Firebase In-App Messaging API) to the usable list in the "API Restrictions" section of the GCP screen.
Consideration 2:
It is important to note that changes are not reflected on the GCP's "Edit API Key" screen unless you press "Save" at the bottom of the screen.
※Initially, I thought I had registered the SHA-1, but FIAM's messages were not displayed and I was stuck for a while, but in fact, I had not pressed "Save" and it had not been reflected.
Consideration 3:
Since Android apps released on Google Play are assigned a "release certificate fingerprint" separate from the debug one, it is believed that the SHA-1 for release (which can be confirmed on the Google Play Console) must be registered with GCP and Firebase before release.
※As mentioned earlier, in my case, I had only registered the release version first, so FIAM did not work in the debug app.
Summary
To summarize, the reasons and countermeasures for not being able to send test messages from FIAM's "Test on Device" were as follows:
- Did not update 'firebase_options.dart'
→ Update by running 'flutterfire configure' - The application restriction was set on the API key, but the fingerprint (SHA-1) of the debug certificate was not registered
→ Register the SHA-1 for debugging with GCP and Firebase (The release certificate also needs to be registered when releasing on Google Play)
Useful tools for personal app development
Recommended learning materials
\Aiming for the campaign period can provide comprehensive content at a low cost/