How to define firebase-remote-config parameters based on app version - firebase

I need to distribute some settings based on the app version e.g. if app version equals "4.0.1" then a else b. I found the possibility to define a condition named "version" but the documentation says it is bound to the package name of the app and not the version or version code.
see here https://firebase.google.com/docs/remote-config/parameters
I tried it though specifying the app version through a "version" condition but it does not work. Any ideas on this would be much appreciated.

The main problem is that Remote config's "Version" is the build number and not the actual version number.
The way I found around this is you can add a "User Property" in Firebase like "app_version". Then when the app launches add the following code:
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
Analytics.setUserProperty(version, forName: "app_version")
You can then use this User Property in Remote Config as a condition and voila you can base some Remote Config value of of the version number. Note this will require the use of Firebase Analytics as well.

Creating a condition, which targets an app version via regular expression appears to be the only solution in this case.
For my app I use the following configuration:
Here, users who have versions 1.8.* and below receive an alternate version of a backend configuration parameter.
If you need to target only a specific version of the app, then a regular expression is not really necessary, so the approach that you took should work.
Alternatively, you can have far more control if you create a user audience based on app version, and then target the audience.

Related

Issue: Audit usage of navigator.userAgent, navigator.appVersion, and navigator.platform

I started a new project in vue.js. I added navbar. At one point, I noticed issue in the console:
Audit usage of navigator.userAgent, navigator.appVersion, and navigator.platform
I don't understand this, because I don't use any navigator in the project.
Why am I seeing this issue? How can I change it?
The reason one sees the message is well explained in the description of the very same message (audit).
The real question is who/what is the source of it. There is a hint to the file extended-css.js.
Here is an example with another file (as I do not have the extended-css.js):
Right click on the file and then choose Open in new tab.
So there you can see that the reason for the audit message is the hook.js file from the Vue.js devtools extension.
In your case it would be another extension or library you are using - direct or indirect (for example a part of vuetify, etc.).
From there you have 3 choices:
ignore it
wait for the authors of the library to fix the issue and update it
disable the extension/remove the library causing it.
https://blog.chromium.org/2021/05/update-on-user-agent-string-reduction.html
Is helpful to read. Some key points:
"Beginning in M92, we plan to start sending deprecation notices for the navigator.userAgent,
navigator.appVersion, and navigator.platform getters in the DevTools Issues tab."
"If your site, service, library or application relies on certain bits of information being present in the User Agent string such as Chrome minor version, OS version number, or Android device model, you will need to begin the migration to use the User Agent Client Hints API instead."
I know I am not using the navigator getters in question so at this point, it seems I can only wait for an update to the library's .js
(in my case, bootstrap 4) to make the warning go away.

How to handle versions and settings to a Xamarin.Forms Android app correct?

I have a Xamarin.Forms Android app that stores and loads parameters with Application.Current.Properties:
E.g.:
Application.Current.Properties["Key"] ="Value";
If a new version is created, the app has to be tested by some test users.
For this case, the app has to be installed in parallel to the actual (productive) version.
The parameters then have to be re-entered and stored for the test.
As soon, as the app is tested, it has to be updated productive whereby the stored parameters have to be adopted.
Note: The app has to be installed manually (no store in place).
To the android project (in .Forms) there are many settings...
E.G.
Application name
Package name
Version number
Version name
The technical version of the app (e.g. 6 / 7 / and so on) is hard coded in the app (and submitted to a web service that checks the version).
The text to the App Icon (e.g. Appx V7) is set in SplashScreen.cs (as the app use a splashscreen at startup)
(Activity(Label = "Appx V7"...)
For the test version, I change the "Package name" in the project settings (the result is, that the app is installed in parallel to the already installed version what is the goal)
Questions:
What exactly is the setting, which defines, that an App is replaced
and the already stored parameters are adopted?
What is the influence of "version number" and "version name" in this context?
Update to my question (clarification based on the answer from Junior Jiang):
Thanks for your answer. Unfortunately, it don’t fully answer my question (maybe the question was misleading, therefore this clarification).
The main question was, which setting(s) triggers, that an already installed app is UPDATED and the already stored data ARE adopted.
As I wrote, I change the “Package name” to create a TEST version (with another package name, the app is installed in parallel and already stored data are NOT adopted (what is CORRECT for the TEST version).
If the app then has been tested, I have to create a new .apk (from the tested version) that the productive users can install and that has to be UPDATE the already installed version, whereby the stored data HAVE to be adopted.
Actually, I change back the “Package name” to the package name of the productive used (installed) version and that seems to work (but is not really nice, especially as I have done the mistake to name the prod .apk with the (now old) version (appx.V6).
Is the only way to update the app and adopt the stored data to use the SAME SAME “Package name” (that the installed version had) or is there another (better) solution?
About Application.Current.Properties : The Properties dictionary uses a string key and stores an object value.
The Application subclass has a static Properties dictionary which can be used to store data, in particular for use in the OnStart, OnSleep, and OnResume methods. This can be accessed from anywhere in your Xamarin.Forms code using Application.Current.Properties.
It has nothing to do with versions and settings for Android app . So this will not affect the version number and version name in Android app .
1.What exactly is the setting, which defines, that an App is replaced and the already >stored parameters are adopted?
2.What is the influence of "version number" and "version name" in this context?
This Version value of version number and version name is stored in the AndroidManifest.xml file .
Version Number – An integer value (used internally by Android and the application) that represents the version of the application. Most applications start out with this value set to 1, and then it is incremented with each build. This value has no relationship or affinity with the version name attribute (see below). Applications and publishing services should not display this value to users. This value is stored in the AndroidManifest.xml file as android:versionCode.
Version Name – A string that is used only for communicating information to the user about the version of the application (as installed on a specific device). The version name is intended to be displayed to users or in Google Play. This string is not used internally by Android. The version name can be any string value that would help a user identify the build that is installed on their device. This value is stored in the AndroidManifest.xml file as android:versionName.
You can modify them in the AndroidManifest.xml file as follow :
In addition , if want to get them in Forms , can use DependencyService to do .
Create a IAppVersionAndBuild interface :
public interface IAppVersionAndBuild {
string GetVersionNumber();
string GetBuildNumber();
}
Create the implement method class(VersionAndBuild_Android) in Android solution :
using Android.Content.PM;
using VersionAndBuildNumber.DependencyServices;
using VersionAndBuildNumber.Droid.DependencyServices;
using Xamarin.Forms;
[assembly: Dependency(typeof(VersionAndBuild_Android))]
namespace AppOne.Droid.DependencyServices {
public class VersionAndBuild_Android: IAppVersionAndBuild {
PackageInfo _appInfo;
public VersionAndBuild_Android() {
var context = Android.App.Application.Context;
_appInfo = context.PackageManager.GetPackageInfo(context.PackageName, 0);
}
public string GetVersionNumber() {
return _appInfo.VersionName;
}
public string GetBuildNumber() {
return _appInfo.VersionCode.ToString();
}
}
}
Last in ContentPage :
string versionName = DependencyService.Get<IAppVersionAndBuild>().GetVersionNumber();
string versionNumber = DependencyService.Get<IAppVersionAndBuild>().GetBuildNumber();
As I have to replace my app in a customer project (in the near time), I have checked the behavior and defined the following approach now for exactly my case (may be wrong for your case):
Manifest:
[
"Application name" ( 1 ) is not changed
"Package name" ( 1 ) to the productive installed app version (unfortunately) is set to AppName.V6
=> If I could start again, I would name it .prod (without version)
I don't use/change the "Version number" and the "Version name" ( 3 )
Process steps:
(A) - (My) Starting position:
To the productive installed app version, the "Package name" was set to AppName.V6
As I wrote above, this was a mistake (I should have named in .prod instead), but... it now is installed with .V6, so I can't go back...)
(B) - Create new test version:
Change the the label text (showed text to Icon) to the new version (in the example V7)
Rename the "Package name" ( 2 ) and ( 2.1 ) to AppName.whatever.
This "triggers", that the App is installed in parallel to the already installed version and the already stored parameters are not adopted
The app is installed on the mobiles of the test users and tested: Changes are done in the app if needed (without to change the manifest data)
(C) - The app is approved by the testers:
All tests are done successful, the app is ready to go productive...
(D) - Create new version for prod update:
Re change the "Package name" ( 2 ) and ( 2.1 ) to AppName.V6
As the installed version (unfortunately) have this "Package name" and the App only will be replaced, if this package name ist used for the update.
This way, the .apk is generated with AppName.V6-signed.apk (what is logical wrong, as the real version in the example is V7)
Therefore, I change the name to the .apk after generation manually (in windows explorer) to the correct name (in the example: AppName.V7-signed.apk)
Note: The name of the .apk seems not to have any technical impact. This way, I easily can save versions and versions also can be stored in the user mobile devices...
(E) - Install new Version:
The new version is installed on the user mobiles,
thereby ( F ):
The already installed app it replaced
Already stored parameters are adopted
The text to the Icon changes to AppName V7
This is a description, how I do it now for my case.
As I wrote above, If I would be able to go back, I would name the "Package name":
AppName.Prod (for the productive app version)
and
AppName.Test (for the test version(s))
I hope, this helps somebody...
Feel free to post a better solution, if you have one...

Will I have problems if I publish an app with a packagename different of bundle id?

Recently I had to change the package name of my android project because I had to disable an old app to change some pieces of information and some of the UI of it. But the business logic are pretty the same. So I wonder, can I use the same solution with a different package name for Android (for create another app in google play with the same name but different package name) and then keep the bundle id the same for iOS to not have to recreate another one in the app store? Will I have problems with it?
Thanks very much.
In my knowledge, there should not be any issues if you make sure about the following pointers:
Everything that was registered on the old bundle id is now registered for the new one and replaced with the new one all over your project. eg: if you have a firebase product used then you replace the old googleservices.json with the new one.
The old app that you have on the store is removed(To avoid confusion for users)
You can use the same key to sign the key but you cannot use the same App that you added on store earlier.
Make sure you do not have any dependency of any sort on the old bundle id.
Note: Your old app will not be replaced by this new one even though they would have the same name as the bundle id is the unique identifier for this.
There should not be any problems if you use the same bundle id for the new iOS app as you had earlier but usually, both apps have the same bundle just to keep it standard. But you can always opt. not to.
Goodluck feel free to get back if you have any more queries

Intent Extension for Siri Shortcuts works in Sample App not in existing project

I am trying to use Intents Extension in my existing Obj-C project for conversational shortcuts in iOS 13. I have followed all the steps and the procedures work fine in a sample app.
But when I try it out in my existing application the intents fail to launch and it is automatically redirected to my parent app.
The console error is as follows
[Intents] -[INCache cacheableObjectForIdentifier:] Unable to find cacheable object with identifier intents-remote-image-proxy:?proxyIdentifier=2A439A9B-6D95-BFB2-FCE4-31408D1E677F.png&storageServiceIdentifier=com.apple.Intents.INImageServiceConnection in cache.
Has anyone faced such an issue with intents? Please share your thoughts on this.
Additional Info:
The intent is registered. Have implemented the 'handle' 'resolve' methods and have also declared them in the interface.
Have the extension's min deployment target same as the parent (which created an issue that I had missed previously).
The issue was created due to setting up 'Copy only when installing' boolean as 'true' in 'Embed App Extensions' under 'Build Phases'. It was resolved once the check was made 'false'.

How to setup different firebase environments in Flutter

I am trying to figure out how to set up different firebase environments in a flutter project.
I understand how to do this in firebase, I created two projects, one for production, one for the test. Then, in an iOS or Android project, I could use various methods to switch between these two environments using separate google-services.json or GoogleServices-Info.plist files.
In Flutter I found this description of how to separate environments, but it only explains how to differentiate between environments in the flutter code.
How can I get this environment to change what iOS and Android build at compile time? It would even be sufficient simply to allow a file copy hook at build time.
You can switch accounts using FirebaseApp.configure. You can offer your own solution or secret dev panel to switch between them.
The solutions will build flavours and plist implementations will lock you into builds when you deploy for TestFlight + they are messy.
Here's an example: (You could use Assets as well.)
// Load a named file.
let filePath = Bundle.main.path(forResource: "MyGoogleService", ofType: "plist")
guard let fileopts = FirebaseOptions(contentsOfFile: filePath!)
else { assert(false, "Couldn't load config file") }
FirebaseApp.configure(options: fileopts)
I wrote an article about how to do this for Firebase configuration as well as runtime configuration in dart code using flavors and platform channels.
https://medium.com/#matt.goodson.business/separating-build-environment-configurations-in-flutter-with-firebase-doing-it-the-right-way-c72c3ad3621f
Flutter flavors work pretty seamlessly with Android flavors. For iOS you need to create Xcode schemes for each flavor and link them to build configurations.
For dart configuration, you can use platform channels to get the flavor used during the build at runtime. This lets you configure the app without having multiple main.dart files or passing a target argument.
Salvatore Giordano has written a blog post with a detailed description of how to achieve this:
https://medium.com/#salvatoregiordanoo/flavoring-flutter-392aaa875f36
Flutter accepts a parameter --flavor=<flavor> which allows you to select different build flavors. In Android this works as expected, selecting different build flavors. IOS is a little tricker because a scheme is needed for every flavor, and the build configurations in the form of Release-<flavor> are also needed.
Once these parts are in place, they can be used, to select the firebase configuration as you would in any iOS or Android project.
The challenge is getting Dart code to also be aware of the flavor, and the blog post provides no good solution for this. It suggests the standard method of using different entry points can be used, but the correct entry point must be matched to the correct flavor manually by the person invoking the app.
Specifically to Firebase env config you can use this article and this article from CodeMagic which explains how you can set up plist files with build env variables.
If you need to have a different set of values inside your Dart code, like an option you can use this package. It allows to generate Dart class config file from console command params.
Update 12/05/2020
Since Flutter 1.17 you can actually use compile-time variables with --dart-define argument in flutter run and flutter build commands
Here is an article that describes how to specify and use them.
With the release of Flutter for Web to the stable channel, I put together instructions for targeting multiple firebase projects (e.g. dev, staging, prod) from multiple build platforms (i.e. iOS, Android, and Web).

Resources