远程配置 firebase_用于应用程序更新检查的Firebase远程配置

远程配置 firebase

介绍 (Introduction)

Firebase is a mobile and web application development platform developed by Firebase, Inc. in 2011, then acquired by Google in 2014. As of March 2020, the Firebase platform has 19 products, which are used by more than 1.5 million apps.

Firebase是由Firebase,Inc.于2011年开发,然后于2014年被Google收购的移动和Web应用程序开发平台。截至2020年3月,Firebase平台有19种产品,超过150万种应用程序在使用。

Firebase has become very necessary for Android developers these days. I have previously written a post on How to Use Remote Config to Change App Appearance please check it out for a basic understanding of Firebase Remote Config. In this post, we will learn how to use Remote Config for showing app updates pop-up with using Rest API.

如今,Firebase对于Android开发人员而言已经变得非常必要。 我之前曾写过一篇有关如何使用远程配置更改应用外观的文章,请查看这篇文章,以基本了解Firebase远程配置。 在本文中,我们将学习如何使用Rest Config使用Remote Config来显示应用程序更新弹出窗口。

什么是应用程序更新? (What are app Updates?)

An app update is nothing but a new version available at the store however, the user is using an older version of the app. It’s a quite common thing to show App update pop-up’s inside the app when a new optional version or a mandatory version of apps are launched.

应用程序更新仅是商店中可用的新版本,但是,用户正在使用旧版本的应用程序。 当启动新的可选版本或强制性版本的应用程序时,在应用程序内部显示应用程序更新弹出窗口是很常见的事情。

So to understand this better let’s take an example, where I have an app at Play Store but there was a programmatic error or a business requirement change and I don’t want any of my old users or new users to install or use the older version of my app. So What do I do? If I fix that particular thing and release a new version of the app at the store.

因此,为了更好地理解这一点,让我们举一个例子,我在Play商店中有一个应用,但是程序错误或业务需求发生了变化,我不希望任何老用户或新用户安装或使用旧版本我的应用程序 那我该怎么办? 如果我修复该特定问题并在商店中发布该应用程序的新版本。

Is this enough? No, fixing only that particular issue is not acceptable. Here we have a requirement that no user can use the older version of the app. So what do we do? Here we have to show a Mandatory Update. There are two types of app updates those are

这够了吗? 不,仅解决该特定问题是不可接受的。 在此,我们要求所有用户都不能使用旧版本的应用程序。 那么我们该怎么办? 在这里,我们必须显示一个强制更新。 有两种类型的应用程序更新,分别是

  • Mandatory Update: Here we generally show a mandatory pop-up to update the app unless we don’t allow users to use the app. This is mandatory which means the user can’t navigate or use any feature of the app without updating to the latest version.

    强制更新:此处通常会显示强制弹出窗口以更新应用程序,除非我们不允许用户使用该应用程序。 这是强制性的 ,这意味着用户无法在不更新到最新版本的情况下导航或使用应用程序的任何功能。

Image for post
  • Latest Update: Here we generally show the pop-up that there was a new version available at the store and request him to update the app for better usage. This is an optional update and we show this randomly not every time frustrating the user. Here the user can navigate or use any feature of the app without updating to the latest version

    最新更新 :我们通常会在弹出窗口中显示商店中有可用的新版本,并请他更新该应用程序以更好地使用。 这是一个可选更新,我们不会每次都使用户感到沮丧时随机显示。 用户可以在这里导航或使用应用程序的任何功能,而无需更新到最新版本

Image for post

I think you got a basic idea about what we are going to implement so let’s check out the coding part.

我认为您对我们将要实现的内容有一个基本的了解,所以让我们检查一下编码部分。

我们会做什么 (What are we going to do)

Let’s do the coding part step-by-step for easy understanding. Our requirement is to

让我们逐步进行编码部分,以便于理解。 我们的要求是

  • Setup Firebase Remote Config

    设置 Firebase远程配置

  • Add required parameters at Remote Config section in Firebase Console

    在Firebase控制台的“远程配置”部分中添加所需的参数

  • Set default parameter values inside the app for update check requirement

    在应用程序内设置默认参数值以进行更新检查

  • Add logic to fetch, activate, and get parameter values

    添加逻辑以获取,激活和获取参数值

  • After fetching the latest values compare the versions of the current app and remote version and show update pop-ups if required.

    提取最新值后, 比较当前应用程序的版本和远程版本,并在需要时显示更新弹出窗口

实作 (Implementation)

Step 1: If you haven’t already added Firebase then, add Firebase to your Android project. Then let’s add remote config dependency in app-level build.gradle(app/build.gradle)

步骤1:如果尚未添加Firebase, 则将Firebase添加到您的Android项目 。 然后让我们在应用程序级别的build.gradle( app / build.gradle )中添加远程配置依赖

implementation 'com.google.firebase:firebase-config-ktx:19.1.4'
implementation 'com.google.firebase:firebase-analytics-ktx:17.4.3'

For Remote Config, Google Analytics is required for the conditional targeting of app instances to user properties, audiences, and Firebase Predictions. Make sure that you enable Google Analytics in your project.

对于“远程配置”,需要有Google Analytics(分析)才能有条件地将应用实例定位到用户属性,受众群体和Firebase预测。 确保在项目中启用Google Analytics(分析)

Step 2: Add required parameters at Remote Config. Now it’s time to add required values at the console. From the Firebase console, open your project, then select Remote Config under Grow section from the left-hand side menu

步骤2:在“远程配置”中添加所需的参数 。 现在是时候在控制台上添加所需的值了。 在Firebase控制台中 ,打开您的项目,然后从左侧菜单中的“ 增长”部分下选择“ 远程配置”。

Image for post

The parameters that are required are

所需的参数是

min_version_of_app: specifies the minimum required version to use the app. Without this or above version user can’t access the app content. We show the mandatory update pop-up in this case.

min_version_of_app:指定使用该应用程序所需的最低版本。 没有此版本或更高版本,用户将无法访问应用内容。 在这种情况下,我们显示强制更新弹出窗口。

latest_version_of_app: specifies the latest version of the app at the store. We show the optional update pop-up in this case.

Latest_version_of_app:指定商店中应用程序的最新版本。 在这种情况下,我们显示了可选的更新弹出窗口。

The name of the params can be anything that you like but theme of the params is important, Why are we using them, and does they satisfy our requirement.

参数的名称可以是任何您喜欢的名称,但是参数的主题很重要,为什么我们要使用它们,它们是否满足我们的要求。

“Parameter key” and “Default value” we have to fill in and finally not forget to hit “PUBLISH CHANGES“ to make our changes go live. Add the parameter’s min_version_of_app & latest_version_of_app and hit Publish changes button.

我们必须填写“参数键”“默认值” ,最后不要忘记点击“ 发布更改以使更改生效 。 添加参数的min_version_of_app和latest_version_of_app,然后点击发布更改按钮。

Image for post

Now we are done from the server-side let’s move to client-side implementation.

现在我们已经从服务器端完成了,让我们转到客户端实现。

Step 3: Set in-app default parameter values required. We can set in-app default parameter values in the Remote Config object so that our app behaves as intended before it connects to the Remote Config backend, and so that default values are available if none are set in the backend.

步骤3:设置所需的应用内默认参数值。 我们可以在Remote Config对象中设置应用内默认参数值 ,以便我们的应用在连接到Remote Config后端之前按预期方式运行,并且如果后端中未设置默认值,则默认值可用。

  1. Define a set of parameter names and default parameter values using a Map object or an XML resource file stored in your app’s res/xml folder. The Remote Config quickstart sample app uses an XML file to define default parameter names and values.

    使用Map对象或定义一个参数名称和默认参数值的集合 XML资源文件存储在应用程序的res/xml文件夹中。 Remote config quickstart示例应用程序使用XML文件定义默认参数名称和值。

  2. Add these values to the Remote Config object using setDefaultsAsync(int), as shown:

    使用setDefaultsAsync(int)将这些值添加到Remote Config对象,如下所示:

val remoteConfig = Firebase.remoteConfig
remoteConfig.setDefaultsAsync(R.xml.remote_config_defaults)

In our case right-click on res folder and add xml folder if not exists then add an XML file with attribute name welcome_image

在我们的情况下,右键单击res文件夹并添加xml文件夹(如果不存在),然后添加属性名称welcome_imageXML文件

Image for post

Step 4: It’s the best practice to init all Firebase related things in the application class onCreate() as following

步骤4:最佳做法是在应用程序类onCreate()中初始化所有与Firebase相关的内容,如下所示

package com.example.viewmodel


import android.app.Application
import android.util.Log
import com.google.firebase.FirebaseApp
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings


class SampleApplication : Application() {


    override fun onCreate() {
        super.onCreate()
        initFirebaseRemoteConfig()
    }


    private fun initFirebaseRemoteConfig() {
        FirebaseApp.initializeApp(this)
        FirebaseRemoteConfig.getInstance().apply {
            //set this during development
            val configSettings = FirebaseRemoteConfigSettings.Builder()
                .setMinimumFetchIntervalInSeconds(0)
                .build()
            setConfigSettingsAsync(configSettings)
            //set this during development


            setDefaultsAsync(R.xml.remote_config_defaults)
            fetchAndActivate().addOnCompleteListener { task ->
                val updated = task.result
                if (task.isSuccessful) {
                    val updated = task.result
                    Log.d("TAG", "Config params updated: $updated")
                } else {
                    Log.d("TAG", "Config params updated: $updated")
                }
            }
        }


    }
}

This initializes the firebase and sets the default values using setDefaultsAsync() and then makes a fetch call. Once the values are received from Firebase as we used fetchAndActivate() which means fetch and activate the values once received that means if anyone from that point requests the params from remoteConfigObject it will have the latest values received from the server.

这将初始化firebase并使用setDefaultsAsync()设置默认值,然后进行提取调用。 一旦我们使用fetchAndActivate()从Firebase接收了值,这意味着一旦接收就获取并激活了值,这意味着如果那时有人从remoteConfigObject请求参数,它将从服务器接收到最新的值。

  1. To fetch parameter values from the Remote Config backend, call the fetch() method. Any values that you set in the backend are fetched and stored in the Remote Config object.

    要从Remote Config后端获取参数值,请调用fetch ()方法。 您在后端设置的任何值都将被提取并存储在Remote Config对象中。

  2. To make fetched parameter values available to your app, call the activate() method.

    要将获取的参数值提供给您的应用程序,请调用activate ()方法。

  3. For cases where you want to fetch and activate values in one call, you can use a fetchAndActivate() request to fetch values from the Remote Config backend and make them available to the app

    对于要在一次调用中获取和激活值的情况,可以使用fetchAndActivate ()请求从Remote Config后端获取值并将其提供给应用程序

This is how we receive the latest values from the FirebaseConsole.

这就是我们从FirebaseConsole接收最新值的方式。

Step 5: As we have received the latest values from the console the next step is to check the mandatory update first as it has a high priority. For this, we need to get the app version on the device using the getAppVersion() method and get the min_version_of_app fetched from the console and compare them using checkMandateVersionApplicable().

步骤5:当我们从控制台收到最新值时,下一步是首先检查强制更新,因为它具有较高的优先级。 为此,我们需要使用getAppVersion()方法获取设备上的应用版本,并获取从控制台获取的min_version_of_app ,并使用checkMandateVersionApplicable()比较它们

As this app has only dots separator for version name we just used the delimiter “.” dot using the method getAppVersionWithoutAlphaNumeric(). Else we check both the app version and latest_version_of_app are the same if not we show optional update pop-up however if this condition is also passed user can move to the normal flow. This is best to do in SplashActivity as it would be the initial screen of launch.

由于该应用程序的版本名称只有点分隔符,因此我们只使用定界符“ 。”。 使用方法getAppVersionWithoutAlphaNumeric()进行 运算。 否则,如果没有显示可选的更新弹出窗口,我们将检查应用程序版本latest_version_of_app是否相同,但是如果还通过了此条件,则用户可以转到常规流程。 最好在SplashActivity中执行此操作,因为这将是启动的初始屏幕。

package com.example.viewmodel


import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.google.firebase.remoteconfig.FirebaseRemoteConfig




class MainActivity : AppCompatActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample)
        
        checkForUpdate()
    }


    private fun checkForUpdate() {


        val appVersion: String = getAppVersion(this)
        val remoteConfig = FirebaseRemoteConfig.getInstance()


        val currentVersion =
            remoteConfig.getString("min_version_of_app")
        val minVersion =
            remoteConfig.getString("latest_version_of_app")
        if (!TextUtils.isEmpty(minVersion) && !TextUtils.isEmpty(appVersion) && checkMandateVersionApplicable(
                getAppVersionWithoutAlphaNumeric(minVersion),
                getAppVersionWithoutAlphaNumeric(appVersion)
            )
        ) {
            onUpdateNeeded(true)
        } else if (!TextUtils.isEmpty(currentVersion) && !TextUtils.isEmpty(appVersion) && !TextUtils.equals(
                currentVersion,
                appVersion
            )
        ) {
            onUpdateNeeded(false)
        } else {
            moveForward()
        }
    }




    private fun checkMandateVersionApplicable(
        minVersion: String,
        appVersion: String
    ): Boolean {
        return try {
            val minVersionInt = minVersion.toInt()
            val appVersionInt = appVersion.toInt()
            minVersionInt > appVersionInt
        } catch (exp: NumberFormatException) {
            false
        }
    }


    private fun getAppVersion(context: Context): String {
        var result: String? = ""
        try {
            result = context.packageManager
                .getPackageInfo(context.packageName, 0).versionName
        } catch (e: PackageManager.NameNotFoundException) {
            Log.e("TAG", e.message)
        }
        return result?:""
    }


    private fun getAppVersionWithoutAlphaNumeric(result: String): String {
        var version_str = ""
        version_str = result.replace(".", "")
        return version_str
    }


    private fun onUpdateNeeded(isMandatoryUpdate: Boolean) {
        val dialogBuilder = AlertDialog.Builder(this)
            .setTitle(getString(R.string.update_app))
            .setCancelable(false)
            .setMessage(if (isMandatoryUpdate) getString(R.string.dialog_update_available_message) else "A new version is found on Play store, please update for better usage.")
            .setPositiveButton(getString(R.string.update_now))
            { dialog, which ->
                openAppOnPlayStore(this, null)
            }


        if (!isMandatoryUpdate) {
            dialogBuilder.setNegativeButton(getString(R.string.later)) { dialog, which ->
                moveForward()
                dialog?.dismiss()
            }.create()
        }
        val dialog: AlertDialog = dialogBuilder.create()
        dialog.show()
    }


    private fun moveForward() {
        Toast.makeText(this, "Next Page Intent", Toast.LENGTH_SHORT).show()
    }


    fun openAppOnPlayStore(ctx: Context, package_name: String?) {
        var package_name = package_name
        if (package_name == null) {
            package_name = ctx.packageName
        }
        val uri = Uri.parse("market://details?id=$package_name")
        openURI(ctx, uri, "Play Store not found in your device")
    }


    fun openURI(
        ctx: Context,
        uri: Uri?,
        error_msg: String?
    ) {
        val i = Intent(Intent.ACTION_VIEW, uri)
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
        if (ctx.packageManager.queryIntentActivities(i, 0).size > 0) {
            ctx.startActivity(i)
        } else if (error_msg != null) {
            Toast.makeText(this, error_msg, Toast.LENGTH_SHORT).show()
        }
    }


}

Output:

输出:

Image for post
Image for post
Mandatory n Optional updates triggered based on the condition evaluated
强制n根据评估的条件触发可选更新

Please let me know your suggestions and comments.

请让我知道您的建议和意见。

You can find me on Medium and LinkedIn

您可以在MediumLinkedIn上找到我…

Thanks for reading…

谢谢阅读…

翻译自: https://medium.com/android-dev-hacks/firebase-remote-config-for-app-updates-check-81379ff96cd1

远程配置 firebase

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值