【问题标题】:How to find the Android version name programmatically?如何以编程方式查找 Android 版本名称?
【发布时间】:2012-05-19 20:11:20
【问题描述】:

我写这样的代码来查找Android版本

String version=Build.VERSION.RELEASE;

通过使用此代码,我得到了版本号,但我想要版本名称。 如何获取版本名称?

【问题讨论】:

    标签: android android-ndk


    【解决方案1】:

    如前所述,反思似乎是这个问题的关键。不需要 StringBuilder 和额外的格式,添加它只是为了说明用法。

    import java.lang.reflect.Field;
    ...
    
    StringBuilder builder = new StringBuilder();
    builder.append("android : ").append(Build.VERSION.RELEASE);
    
    Field[] fields = Build.VERSION_CODES.class.getFields();
    for (Field field : fields) {
        String fieldName = field.getName();
        int fieldValue = -1;
    
        try {
            fieldValue = field.getInt(new Object());
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    
        if (fieldValue == Build.VERSION.SDK_INT) {
            builder.append(" : ").append(fieldName).append(" : ");
            builder.append("sdk=").append(fieldValue);
        }
    }
    
    Log.d(LOG_TAG, "OS: " + builder.toString());
    

    在我的 4.1 模拟器上,我得到以下输出:

    D/MainActivity( 1551): OS: android : 4.1.1 : JELLY_BEAN : sdk=16
    

    享受吧!

    【讨论】:

    • 使用自己的静态名称数组并按索引查找会更简单、更安全。
    • 对于可以为每个版本定期更新的应用来说,静态数组可能是理想的选择,但对于许多 Android 版本可能不会更新的项目,这可能仍然是首选解决方案。跨度>
    • 它只返回 P,而不是 Pie。
    【解决方案2】:

    优化的代码,这将工作:

    import java.lang.reflect.Field;
    
    Field[] fields = Build.VERSION_CODES.class.getFields();
    String osName = fields[Build.VERSION.SDK_INT + 1].getName();
    Log.d("Android OsName:",osName);
    

    【讨论】:

    • 仅供参考:对于 Android 8.1,这会产生:O_MR1
    • 是的,Android 返回名称取决于定义的变量developer.android.com/reference/android/os/…
    • 这让我最近遇到了麻烦,因为 '+ 1' 使它跑出了字段数组的末尾。我不明白这里的推理。我最后添加了一个检查,看看 SDK_INT + 1 是否太大。如果是,我使用“字段”中的最后一个条目,但我真的不知道这是否是最好的做法。在下面的 cmets 中有更多关于此的内容。
    • 现在不安全。可能导致崩溃。我们可以使用构建一个字符串数组/映射并手动映射版本号/字符串名称。
    【解决方案3】:

    API 28 (Android Pie) 之后,Build.VERSION_CODES更改 一些字段。

    所以,如果你使用:

    Field[] fields = Build.VERSION_CODES.class.getFields();
    String osName = fields[Build.VERSION.SDK_INT + 1].getName();
    

    会因为超出范围异常导致您的应用立即崩溃。

    所有 API 级别的解决方案是:

    Field[] fields = Build.VERSION_CODES.class.getFields();
    String codeName = "UNKNOWN";
    for (Field field : fields) {
        try {
            if (field.getInt(Build.VERSION_CODES.class) == Build.VERSION.SDK_INT) {
                codeName = field.getName();
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    

    或者在 Kotlin 中使用 Java 8 的风格:

    val fields = Build.VERSION_CODES::class.java.fields
    var codeName = "UNKNOWN"
    fields.filter { it.getInt(Build.VERSION_CODES::class) == Build.VERSION.SDK_INT }
          .forEach { codeName = it.name }
    

    【讨论】:

    • 您的解决方案简直是最好的,因为自 API 28 以来字段排列发生了变化。
    • 您可以选择 firstOrNull,而不是在过滤列表上循环。 val fields = Build.VERSION_CODES::class.java.fields val codeName fields.firstOrNull { it.getInt(Build.VERSION_CODES::class) == Build.VERSION.SDK_INT }?.name ?: "UNKNOWN"
    • 好答案!此代码由 api 29 运行。:)
    【解决方案4】:

    http://developer.android.com/reference/android/os/Build.VERSION_CODES.html 包含具有您要查找的名称的字段。 因此,您可以使用反射来查找与“版本”值对应的字段。

    你为什么要这个名字?

    【讨论】:

    • 客户端要求获取自己手机的版本号和版本名称
    • 那么最好的可能是将 Build.VERSION.SDK_INT 发送到您的服务器,然后将该 int 映射到您要提供给客户的名称。
    • 我刚刚给了你一个,另一个答案也是如此:使用 android.os.Build.VERSION.SDK_INT 获取一个数字,然后找到 android.os.Build.VERSION_CODES 中的哪个字段具有该值反射。该字段的名称就是您要查找的内容
    【解决方案5】:

    你会从这些获得信息

    android.os.Build.VERSION_CODES 
    
    android.os.Build.VERSION.SDK_INT
    

    更多信息可以通过这个链接获得:

    Retrieving Android API version programmatically

    希望这会对你有所帮助。

    【讨论】:

      【解决方案6】:

      看看这个:

      // Names taken from android.os.build.VERSION_CODES
      String[] mapper = new String[] {
          "ANDROID BASE", "ANDROID BASE 1.1", "CUPCAKE", "DONUT",
          "ECLAIR", "ECLAIR_0_1", "ECLAIR_MR1", "FROYO", "GINGERBREAD",
          "GINGERBREAD_MR1", "HONEYCOMB", "HONEYCOMB_MR1", "HONEYCOMB_MR2",
          "ICE_CREAM_SANDWICH", "ICE_CREAM_SANDWICH_MR1", "JELLY_BEAN"
      };
      int index = Build.VERSION.SDK_INT - 1;
      String versionName = index < mapper.length? mapper[index] : "UNKNOWN_VERSION"; // > JELLY_BEAN)
      

      请注意,此解决方案仅适用于版本代码不断递增 1,并且您必须使用每个新的 android 版本更新列表(如果准确很重要)。

      【讨论】:

      • 那么,每一个新的 Android 版本你都必须更新这个数组,弱。
      【解决方案7】:

      如 android 文档中所述,手机运行的 SDK 级别(整数)可用于:

      android.os.Build.VERSION.SDK_INT;

      这个int对应的枚举在android.os.Build.VERSION_CODES类中。

      代码示例:

      int currentapiVersion = android.os.Build.VERSION.SDK_INT;
      if (currentapiVersion >= android.os.Build.VERSION_CODES.FROYO){
          // Do something for froyo and above versions
      } else{
          // do something for phones running an SDK before froyo
      }
      

      编辑:此 SDK_INT 自 Donut (android 1.6 / API4) 起可用,因此请确保您的应用程序在使用时与 Cupcake (android 1.5 / API3) 不兼容,否则您的应用程序将崩溃(感谢程序员 Bruce精度)。

      【讨论】:

        【解决方案8】:

        我已经应用了上面的解决方案,但对“O”和“N”作为版本名称不太满意,所以我做了一些更改。希望对其他人也有用

            /**
         * Gets the version name from version code. Note! Needs to be updated
         * when new versions arrive, or will return a single letter. Like Android 8.0 - Oreo
         * yields "O" as a version name.
         * @return version name of device's OS
         */
        private static String getOsVersionName() {
            Field[] fields = Build.VERSION_CODES.class.getFields();
            String name =  fields[Build.VERSION.SDK_INT + 1].getName();
        
            if(name.equals("O")) name = "Oreo";
            if(name.equals("N")) name = "Nougat";
            if(name.equals("M")) name = "Marshmallow";
        
            if(name.startsWith("O_")) name = "Oreo++";
            if(name.startsWith("N_")) name = "Nougat++";
        
            return name;
        }
        

        【讨论】:

          【解决方案9】:

          适合初学者的解决方案。 我使用版本代码,因为它们比代号更好,更不容易混淆。例如。果冻豆、奥利奥、棒棒糖等在单一代号下具有不同的版本代码。 无论如何,您可以将版本代码替换为代号。

           var androidVersion = ""
              androidVersion = when (android.os.Build.VERSION.SDK_INT){
                  16 -> "Android 4.1"
                  17 -> "Android 4.2"
                  18 -> "Android 4.3"
                  19 -> "Android 4.4"
                  21 -> "Android 5.0"
                  22 -> "Android 5.1"
                  23 -> "Android 6.0"
                  24 -> "Android 7.0"
                  25 -> "Android 7.1"
                  26 -> "Android 8.0"
                  27 -> "Android 8.1"
                  28 -> "Android 9"
                  29 -> "Android 10"
                  else -> "API " + android.os.Build.VERSION.SDK_INT
              }
          

          【讨论】:

            【解决方案10】:

            当我尝试在 API 19 上运行的模拟器时,反射不起作用。

            所以我想出了“Nacho Coloma”和“Kevin Grant”的混合答案

            String osName="";
            Field[] fields = Build.VERSION_CODES.class.getFields();
            for (Field field : fields) {
                String fieldName = field.getName();
                int fieldValue = -1;
            
                try {
                    fieldValue = field.getInt(new Object());
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (NullPointerException e) {
                    e.printStackTrace();
                }
            
                if (fieldValue == Build.VERSION.SDK_INT) {
                    osName=fieldName; break;
                }
            }
            if(osName.isEmpty()) {
                String[] mapper = new String[]{
                        "ANDROID BASE", "ANDROID BASE 1.1", "CUPCAKE", "DONUT",
                        "ECLAIR", "ECLAIR_0_1", "ECLAIR_MR1", "FROYO",
                        "GINGERBREAD", "GINGERBREAD_MR1", "HONEYCOMB", "HONEYCOMB_MR1",
                        "HONEYCOMB_MR2", "ICE_CREAM_SANDWICH", "ICE_CREAM_SANDWICH_MR1", "JELLY_BEAN",
                        "JELLY_BEAN", "JELLY_BEAN", "KITKAT", "KITKAT",
                        "LOLLIPOOP", "LOLLIPOOP_MR1", "MARSHMALLOW", "NOUGAT",
                        "NOUGAT", "OREO", "OREO", "ANDROID P"};
                int index = Build.VERSION.SDK_INT - 1;
                osName = index < mapper.length ? mapper[index] : "UNKNOWN_VERSION";
            }
            

            【讨论】:

              【解决方案11】:

              此答案为 Marshmallow on 提供了更好的(完整)名称,同时如果您在新版本发布时不更新您的应用程序(两全其美),也可以保持面向未来。版本名称列表来自here.

              String versionName =
                      Build.VERSION_CODES.class.getFields()[Build.VERSION.SDK_INT + 1].getName();
              String[] versionNames = new String[]{
                      "ANDROID BASE", "ANDROID BASE 1.1", "CUPCAKE", "DONUT",
                      "ECLAIR", "ECLAIR_0_1", "ECLAIR_MR1", "FROYO", "GINGERBREAD",
                      "GINGERBREAD_MR1", "HONEYCOMB", "HONEYCOMB_MR1", "HONEYCOMB_MR2",
                      "ICE_CREAM_SANDWICH", "ICE_CREAM_SANDWICH_MR1",
                      "JELLY_BEAN", "JELLY_BEAN_MR1", "JELLY_BEAN_MR2", "KITKAT", "KITKAT_WATCH",
                      "LOLLIPOP", "LOLLIPOP_MR1", "MARSHMALLOW", "NOUGAT", "OREO", "OREO_MR1"
              };
              int nameIndex = Build.VERSION.SDK_INT - 1;
              if (nameIndex < versionNames.length) {
                  versionName = versionNames[nameIndex];
              }
              

              显然这是从其他人的答案衍生而来的。根据我的经验,当您尝试编辑现有答案以改进它时,人们不喜欢它,因此我创建了一个新答案。

              【讨论】:

                【解决方案12】:

                Build.VERSION.SDK;返回正确的结果,但从 API 16 开始不推荐使用 SDK:Android 4.1 (Jelly Bean)。所以它会显示为 w

                【讨论】:

                  【解决方案13】:

                  如果您正在寻找Xamarin.Android,解决方案很简单:

                  Build.VERSION.SdkInt.ToString();
                  

                  很简单。

                  原因是SdkInt映射到Android的SDK_INT

                  [Register("SDK_INT", ApiSince = 4)]
                  public static BuildVersionCodes SdkInt
                  {
                    get
                    {
                      return (BuildVersionCodes) Build.VERSION._members.StaticFields.GetInt32Value("SDK_INT.I");
                    }
                  }
                  

                  映射到枚举,在 C# 中,当调用枚举 ToString 时,会返回枚举的名称(而不是值):

                   public enum BuildVersionCodes
                    {
                      [IntDefinition("Android.OS.Build.VERSION_CODES.Base", JniField = "android/os/Build$VERSION_CODES.BASE")] Base = 1,
                      [IntDefinition("Android.OS.Build.VERSION_CODES.Base11", JniField = "android/os/Build$VERSION_CODES.BASE_1_1")] Base11 = 2,
                      [IntDefinition("Android.OS.Build.VERSION_CODES.Cupcake", JniField = "android/os/Build$VERSION_CODES.CUPCAKE")] Cupcake = 3,
                   ...
                  

                  【讨论】:

                    【解决方案14】:

                    你可以试试下面的功能。

                     public String AndroidOSName() {
                        String os = Build.VERSION.SDK;
                        System.out.println("here is my os" + " " + os);
                        if (os.equals("23")) {
                            return "Marshmallow";
                        } else if (os.equals("21")) {
                            return "Lollipop";
                        } else if (os.equals("22")) {
                            return "LOLLIPOP_MR1";
                        } else if (os.equals("20")) {
                            return "KitKat";
                        } else if (os.equals("19")) {
                            return "KitKat";
                        } else if (os.equals("18")) {
                            return "Jelly Bean";
                        } else if (os.equals("17")) {
                    
                            return "Jelly Bean";
                        } else if (os.equals("16")) {
                            return "Jelly Bean";
                        } else if (os.equals("15")) {
                            return "Ice Cream Sandwich";
                        } else if (os.equals("14")) {
                            return "Ice Cream Sandwich";
                        } else if (os.equals("13")) {
                            return "Honeycomb";
                        } else if (os.equals("12")) {
                            return "Honeycomb";
                        } else if (os.equals("11")) {
                            return "Honeycomb";
                        } else if (os.equals("10")) {
                            return "Gingerbread";
                        } else if (os.equals("9")) {
                            return "Froyo";
                        } else if (os.equals("8")) {
                            return "Froyo";
                        } else {
                            return "Not Found";
                        }
                    
                    }
                    

                    【讨论】:

                    • 请注意,如果您想宣传自己的网站或博客,您必须在回答中披露您的隶属关系。否则,您的回答可能会被标记为垃圾邮件。请阅读How to not be a spammer
                    猜你喜欢
                    • 2013-02-25
                    • 1970-01-01
                    • 2014-11-20
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-08-28
                    • 1970-01-01
                    • 2015-05-22
                    相关资源
                    最近更新 更多