I try to init Firebase depending on a user language preferences.
For example:
User open an app.
Select language A: Flutter should init project A (config, etc.).
Similarly when the user selects a different language.
The problem is that iOS needs to have default GoogleService-Info.plist file.
During the dynamic init of a Firebase there is created an app but the default one is from the default file and takes the priority over project A. Ultimately, two applications are created (DEFAULT and A). This causes that FirebaseMessaging is assigned to the default Firebase app instead of the second one based on a user preference.
According to the messaging.dart docs:
/// If [app] is not provided, the default Firebase app will be used.
// TODO: messaging does not yet support multiple Firebase Apps. Default app only.
In that case there is no possibility to support dynamic init of a Firebase config file due to the fact that there will be always a default app initiated from the default config file.
In native apps I can create many .plist files and invoke FirebaseApp.configure(options: options)
Do you have any idea how to solve this problem in Flutter?
The problem you are experiencing with FirebaseMessaging is a result of the firebase_messaging package not yet supporting .instanceFor(). The presence of the default app would not be an issue otherwise, but the default app is hard coded to be the only supported app in FirebaseMessaging.
Support for .instanceFor() has already been added to the FirebaseAuth, FirebaseFirestore and FirebaseStorage packages. If FirebaseMessaging
supported instanceFor(), you could simply pass your secondary app name in and reference it using that method. Instead, the lack of support in that package adds needless complication. More info on instances here: https://firebase.flutter.dev/docs/core/usage/#secondary-firebase-apps.
Further information pertaining to the lack of multi-app support in fcm can be found here: https://github.com/FirebaseExtended/flutterfire/issues/5844. There is mention of a possible workaround (which I have not personally attempted) and also an open PR at https://github.com/FirebaseExtended/flutterfire/pull/6549 which is still in the draft stage.
You may be able to accomplish the desired functionality using flavors but I am not familiar enough with them to assist on that topic: https://flutter.dev/docs/deployment/flavors.
I was in the same situation and opted to subscribe all app users to the default app instance and in turn perform all fcm dispatching via firebase cloud function on behalf of my default project, until the firebase_messaging package team fixes this obvious hole in their implementation.
If you have the ability to contain all your data in a single project, organized by language collections and isolated by rules you may want to consider that an option as well.
Related
How can I set the sender id when requesting a registration token for Firebase messaging in Android?
I need this, because I have to have different FB projects for the apps and the server that is sending the notifications. It's described here, but I think the doc is missing something. Searching StackOverflow results in answers that are not up-to-date, also. Can't find the way to do it with the latest version of the API.
I suggest having a read on controlling your Firebase registration/instance it also explains not only how to manually initialise your own firebase with custom options/name but also how firebase initialises itself automatically using the Google plugin and json file which will help you better understand what solution may be best for you.
Essentially you need to manually initialise your Firebase service in your Android apps Application class and provide a FirebaseOptions.Builder class to the Firebase.initializeApp, which allows you to call setGcmSenderId among other things like api key etc.
This official link shows how to configure mutliple projects in your application which may be an option too.
I wanted to keep using the google-services.json, so I didn't want to do the manual init. Then when I read how the Google Services Gradle Plugin works, I was going to make the manual init by using the values from the file - more info here: https://developers.google.com/android/guides/google-services-plugin#processing_the_json_file
In the end, I ended up not changing anything in the code and just changing project_info/project_number in the google-services.json. It's used for gcm_defaultSenderId. Everything looks good, now. Hope it's not used for anything, else. We are using FCM, only, so I think it will be ok. I don't like this, but it will do.
the sender id and project details are set using configuration file "google-services.json",it reads this file from app folder of your android project.
to get google-services.json for your firebase project in firebase console, open project settings and select your app and download the file and place it inside app folder of your android project.
I have an Android App where I want to the UserName and serverURL to be pre-filled when device opens , Based on the device enrolment it will fetch the these values on userName and serverURL field .
Can I use Android Restriction API to get those configuration value.
like below
List<RestrictionEntry> restrictions =
manager.getManifestRestrictions(Constants.PACKAGE_NAME_APP_RESTRICTION_SCHEMA);
It seems documents kind of vogue for Android
Android documentation isn't perfect but at least this one about managed configurations is a bit good ;) .
To provide externally managed configurations:
Declare the managed configurations in your app manifest. Doing so allows the IT admin to read the app's configurations through Google Play APIs.
Whenever the app resumes, use the RestrictionsManager object to check the current managed configurations, and change your app's UI and behavior to conform with those configurations.
Listen for the ACTION_APPLICATION_RESTRICTIONS_CHANGED intent. When you receive this broadcast, check the RestrictionsManager to see what the current managed configurations are, and make any necessary changes to your app's behavior.
You can also check the sample projet AppRestrictions for more details.
Good luck
I've been working on an app which displays a list of websites when click on it will be redirected to webview in the app itself, I'm unable to find a way how to update the links dynamically without updating the app. So, If I want users to interact with new links the new links should automatically be updated in the app without update and in the webview too. Is it possible to do that?
You should use firebase remote config feature, which best fits in your case.
Firebase Remote Config is a cloud service that lets you change the
behavior and appearance of your app without requiring users to
download an app update.
Well to do that you first need to create a project in firebase console
In remote config feature you can add data in key-value pair. Like in this image:
I have added two key-value pair, as can add as much as you want. Now in the app side you have to add dependency:
implementation ‘com.google.firebase:firebase-config:11.8.0’
And to fetch the values which you have added in firebase, you can easily get those url but first you need to follow some steps to do that. You can check this simple tutorial.
Note: To get the values from firebase remote config you must need to click on publish changes button(Which you can see in above image top right corner).
You can store that link to a server and return that link when the app hits a certain API of that server. But for doing that, you need to setup a server, build a server application if you haven't already. Which is a lot of work for just storing a website link.
Another option could be, you can use services like http://bit . ly and create a custom link from that service, like http://bit . ly/my_specific_domain and use this link in your app. When you need to point to a different website, you can just update where http://bit . ly/my_specific_domain redirects to.
But you best bet would be to use Firebase Remote Config, which is both reliable and easy to implement, but that is already described in previous answer.
I have developed my Android app using Firebase and I have developed an iOS app using Firebase. I created two different projects in Firebase, thinking I had to. Now, in order to get the two to talk to each other, I was told to put both in the same project.
I was referred to go to configuring multiple apps but after reading it, I am a bit confused. Any clarification would be greatly appreciated.
I want to connect my iOS project to the Android project I have.
I understand that I need to go the Overview and add another app and select IOS.
I am assuming once I do this, I get a new GoogleService-Info.plist file? And I am also assuming I replace the new plist file with the old, correct?
What I don't understand is the part below:
Use multiple projects in your application
Sometimes you need to access different projects using the same APIs - for example, accessing multiple database instances. In most cases there is a central Firebase application object that manages the configuration for all the Firebase APIs. This object is initialized as part of your normal setup. However, when you want to access multiple projects from a single application, you’ll need a distinct Firebase application object to reference each one individually. It’s up to you to initialize these other instances.
In both cases, you need to first create a Firebase options object to hold the configuration data for the Firebase application. Full documentation for the options can be found in the API reference documentation for the following classes:
The use of these classes to support multiple projects in an application is shown in the following examples:
iOS:
// Configure with manual options.
let secondaryOptions = FirebaseOptions(googleAppID: "1:27992087142:ios:2a4732a34787067a", gcmSenderID: "27992087142")
secondaryOptions.bundleID = "com.google.firebase.devrel.FiroptionConfiguration"
secondaryOptions.apiKey = "AIzaSyBicqfAZPvMgC7NZkjayUEsrepxuXzZDsk"
secondaryOptions.clientID = "27992087142-ola6qe637ulk8780vl8mo5vogegkm23n.apps.googleusercontent.com"
secondaryOptions.databaseURL = "https://myproject.firebaseio.com"
secondaryOptions.storageBucket = "myproject.appspot.com"
Android:
// Manually configure Firebase Options
FirebaseOptions options = new FirebaseOptions.Builder()
.setApplicationId("1:27992087142:android:ce3b6448250083d1") // Required for Analytics.
.setApiKey("AIzaSyADUe90ULnQDuGShD9W23RDP0xmeDc6Mvw") // Required for Auth.
.setDatabaseUrl("https://myproject.firebaseio.com") // Required for RTDB.
.build();
After you have initialized this options object, you can use it to configure an additional Firebase application instance. Note that in all the examples shown below we use the string secondary. This name is used to retrieve the application instance, and to distinguish it from other instances, including the default instance (named [DEFAULT]). You should pick a string appropriate to the intended use of the other Firebase project.
The following snippets demonstrate connecting to an alternative Realtime Database (the APIs for other Firebase features follow the same pattern).
iOS:
// Configure an alternative FIRApp.
FirebaseApp.configure(name: "secondary", options: secondaryOptions)
// Retrieve a previous created named app.
guard let secondary = FirebaseApp.app(name: "secondary")
else { assert(false, "Could not retrieve secondary app") }
// Retrieve a Real Time Database client configured against a specific app.
let secondaryDb = Database.database(app: secondary)
Android:
// Initialize with secondary app.
FirebaseApp.initializeApp(this /* Context */, options, "secondary");
// Retrieve secondary app.
FirebaseApp secondary = FirebaseApp.getInstance("secondary");
// Get the database for the other app.
FirebaseDatabase secondaryDatabase = FirebaseDatabase.getInstance(secondary);
I just don't know if I have to put the code in for both the Android and IOS project or just the IOS (where this is the one I will be adding to the Android project in Firebase).
The documentation page you're referring to describes how to connect a single app to multiple Firebase projects. Your scenario is the exact opposite: you have multiple apps that you want to connect to a single Firebase project.
To do this, you simply:
Create an Android app in your Firebase project, download the google-services.json, and add it to your Android project.
Create an iOS app in your Firebase project, download the google-services.plist, and add it to your iOS project.
So... ignore the documentation page you quoted, and instead just add an Android app, and an iOS app to the same project. They can then access the same back-end services.
What is the best way to discover an Android application's API or hooks into/from the application?
Specifically, I am looking to pass a parameter or data to an application, utilize the application's specific functions, and return data or a parameter to the calling application.
A few ideas come to mind, but I am unfamiliar with what is available, specifically to Android.
Contact an application's developer directly
Somehow decompile the APK to browse the source
Read any available documentation
Some ways to check out what is available for :
Tool to re-engineer closed APK files
http://code.google.com/p/android-apktool/
Review intent filters for actions
Lookup the app in some sort of application manager on your phone. Android System Info. If you go to the details of the app it will tell you where the apk is and the name of it. For instance, under the Email app you can see "Source: /system/app/Email.apk".
To pull that off just do "adb pull /system/app/Email.apk Email.apk", to pull it to your current directory.
Look at the Manifest.xml. Rename the apk to zip and unpack.
Follow the instructions here: http://android.amberfog.com/?p=582
Then you can read the decompiled Manifest.xml and look at the intent filters they are registering.
Android applications are all in their own sandbox, so you can not just arbitrarily call some other Android applications' functions, they would need to be made public to you somehow.
If you are looking to execute some function that is provided by another Android application, you would most likely need to hear about it from the developer, most likely from their public documentation if they have any.
The correct way to do this is to use "intents". With an intent, you can launch another application (such as a barcode scanner) and the user interacts with it. Then, the application exits returning some data (such as the barcode). Try googling or see:
http://www.vogella.com/articles/AndroidIntent/article.html