Firebase 远程配置:无法读取任何值,但获取成功

Firebase Remote Config: Can't read any values, but fetch is successful

我正在尝试使用 Firebase 的新远程配置功能获取远程配置参数,但我遇到了问题。

这是我的远程配置控制台:

我正在我的应用程序中进行提取和更新 onCreate():

final FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
remoteConfig.fetch().addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull Task<Void> task) {
        if (task.isSuccessful()) {
            remoteConfig.activateFetched();
        }
    }
});

我是这样读的:

FirebaseRemoteConfig remoteConfig = FirebaseRemoteConfig.getInstance();
String value = remoteConfig.getString("active_subscriptions");

值正在返回 null。

如果我调用 remoteConfig.getInfo().getLastFetchStatus(),它会 returns LAST_FETCH_STATUS_SUCCESS,所以看起来提取成功了。

知道为什么我的值为空吗?

您可能会在远程配置中点击 caching。它的工作方式是 Config 将在本地缓存传入的项目,并且 return 它们。所以你最后一次(缓存的)获取状态可能是在定义值之前,我们得到一个缓存的空白值。

您可以控制缓存过期时间,但如果您过于频繁地获取数据,您就有被限制的风险。

因为这是一个常见的开发问题,所以有一个开发者模式可以让您更快地请求(对于小用户组):

FirebaseRemoteConfigSettings configSettings = 
    new FirebaseRemoteConfigSettings.Builder()
        .setDeveloperModeEnabled(BuildConfig.DEBUG)
        .build();
FirebaseRemoteConfig.getInstance().setConfigSettings(configSettings);

当您调用 fetch 时,您可以传递一个较短的缓存过期时间

long cacheExpiration = 3600;
FirebaseRemoteConfig mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();
if (mFirebaseRemoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled()) {
     cacheExpiration = 0;
}
mFirebaseRemoteConfig.fetch(cacheExpiration)
     .addOnCompleteListener(new OnCompleteListener<Void>() {
     // ...
});

如果您需要完整参考,quickstart sample 就是这样做的。

找到问题了。

添加一些日志记录后,我发现获取作业的 onComplete() 从未被调用。我将提取从我的应用程序 onCreate 移到了片段的,现在它可以正常工作了!

Ian Barber,这可能需要调查或澄清,因为日志表明 Firebase 在应用程序中初始化时没有问题,并且提取是静默失败。)

找到解决方法!见下文

我正在 运行 关注 "silent completion" 事情 - 我调用 "fetch" 但 onComplete、onSuccess 或 onFailure 侦听器永远不会触发。我尝试将它移动到 activity onCreate,但仍然没有任何反应,因此,配置项永远不会从服务器加载。我已启用开发人员模式,并使用缓存值 0 调用 fetch。

我能够(一次)在行 "public void onComplete(@NonNull Task task) {" 上放置一个断点,它被击中,然后我能够单步执行并触发 onComplete。然后我无法以任何其他方式重现相同的结果,包括(我认为)第二次做同样的事情。

似乎是时间或并发问题,但考虑到这是一个异步调用,这没有什么意义。

解决方法

如果您从 Activity#onResume(或者,我想,Activity#onStart)获取,它会完美运行。从 Activity#onCreate 或 Application#onCreate 调用 fetch 会导致调用似乎永远不会得到处理,事实上,应用程序的性能在 fetch 开始后会显着下降,所以我认为有一个循环 运行宁什么的。*

解决方法#2

如果您真的希望从 Application#onCreate(我这样做)运行,这似乎也有效:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        // Run mFirebaseRemoteConfig.fetch(timeout) here, and it works
    }
}, 0);

在这种情况下的第一件事是检查您是否有正确的 firebase 配置以及您是否已连接到 firebase。如果您有 android studio 2.2,请转到工具->Firebase->RemoteConfig - 连接到 Firebase 和查看您是否收到一条通知说 connected.Once 已连接 在您的代码中执行以下操作: mFirebaseRemoteConfig = FirebaseRemoteConfig.getInstance();

    /** NOTE: At this point, your app can use in-app default parameter values.To use in-app
     *        default values,skip the next section. You can deploy your app without setting
     *        parameter values on the server,and then later set values on the server to
     *        override the default behavior and appearance of your app.
     */

    mFirebaseRemoteConfig.setDefaults(R.xml.remote_config_defaults);
    FirebaseRemoteConfigSettings configSettings = new FirebaseRemoteConfigSettings.Builder()
            .setDeveloperModeEnabled(true)
            .build();
    mFirebaseRemoteConfig.setConfigSettings(configSettings);

然后执行以下操作获取配置 long cacheExpiration = 2000; // 可以增加这个通常 12 小时是推荐的

    /** If in developer mode cacheExpiration is set to 0 so each fetch will retrieve values from
     * the server.*/

    if (mFirebaseRemoteConfig.getInfo().getConfigSettings().isDeveloperModeEnabled()) {
        cacheExpiration = 0;
    }

   /**  cacheExpirationSeconds is set to cacheExpiration here, indicating that any previously
    * fetched and cached config would be considered expired because it would have been fetched
    * more than cacheExpiration seconds ago. Thus the next fetch would go to the server unless
    * throttling is in progress. The default expiration duration is 43200 (12 hours).
    */

    mFirebaseRemoteConfig.fetch(cacheExpiration)//TODO Bring this from a config file
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Firebase Remote config Fetch Succeeded");
                        // Once the config is successfully fetched it must be activated before newly fetched
                        // values are returned.
                        mFirebaseRemoteConfig.activateFetched();
                    } else {
                        Log.d(TAG, "Firebase Remote config Fetch failed");
                    }
                    showRemoteConfig();
                }
            });

运行 您的应用程序并检查日志“Firebase Remote config Fetch Succeeded”。如果您看到相同的内容,您的远程配置已加载并激活。

我使用了类似@Ian Barber 的代码(复制):

FirebaseRemoteConfigSettings configSettings = 
    new FirebaseRemoteConfigSettings.Builder()
        .setDeveloperModeEnabled(BuildConfig.DEBUG)
        .build();
FirebaseRemoteConfig.getInstance().setConfigSettings(configSettings);

我的问题是 "BuildConfig.DEBUG",它 returns 错误。所以它在缓存中取值 1h 直到它被再次获取!

我遇到了同样的问题,并且没有解决方法对我有帮助。问题出在测试设备上。我在没有安装 Google 移动服务的情况下使用了模拟器,因此没有触发 Complete 事件。我用 GMS 尝试了我的 phone,一切都很好。祝你好运。

我有一个问题,Firebase 远程配置没有使用 fetch(0) 触发 OnCompleteListener,但是使用 fetch() 可以。

查看 FirebaseRemoteConfig.fetch() does not trigger OnCompleteListener every time,我发现第一个答案有时甚至与 fetch(0) 一起工作。然后我再次将间隔设置为3600秒,因为错误继续出现:

override fun onPostResume() {
    super.onPostResume()

    // Initialize FirebaseRemoteConfig here.
    ...

    firebaseRemoteConfig.fetch(3600).addOnCompleteListener { task ->
        if (task.isSuccessful) {
            firebaseRemoteConfig.activateFetched()
            //calling function to check if new version is available or not
            checkForUpdate(currentVersionCode, firebaseRemoteConfig.getString(VERSION_CODE_KEY))
        } else
            Toast.makeText(this@MainActivity, "Someting went wrong please try again",
                Toast.LENGTH_SHORT).show()
    }

}

我也遇到了这个问题。原来我没有在 Firebase 控制台中看到 'Publish' 按钮。 :facepalm:

嗯,在我的例子中,我能够在 addOnCompleteListener 中接收 fetch 方法的控制权,但是我在调​​用 firebaseRemoteConfig.activate() 之后就获取了值 firebaseRemoteConfig,所以当我尝试从 firebaseRemoteConfig 中获取值 returns 我之前保存的值是因为 firebaseRemoteConfig.activate() 异步运行并且在我从 firebaseRemoteConfig 获取它们之前没有保存新值,所以我添加了完整的监听器activate() 方法也一样,这里:

firebaseRemoteConfig.fetch()
            .addOnCompleteListener(activity, OnCompleteListener {
                if (it.isSuccessful)
                {
                    Log.d("task","success")
                    firebaseRemoteConfig.activate().addOnCompleteListener {  // here I have added a listener
                        val base_url=firebaseRemoteConfig.getString("base_url")
                        Log.d("base url",base_url)
                        Toast.makeText(activity, "Base url: $base_url",Toast.LENGTH_SHORT).show()
                    }
                }
                else
                {
                    Log.d("task","failure")
                }

            })

我在做一个大项目,问题隐藏在一个意想不到的地方。 长话短说:firebase 应用程序 ID(通常通过 google-services.json 设置)已通过代码更改:

FirebaseOptions.Builder builder = new FirebaseOptions.Builder();
builder.setApplicationId(applicationId);
builder.setApiKey(apiKey);
FirebaseOptions options = builder.build();
FirebaseApp.initializeApp(context, options);

解决方案是删除该代码并让 firebase 使用来自 "google-services.json" 的信息。