如何以编程方式查找 Android 版本名称?
Posted
技术标签:
【中文标题】如何以编程方式查找 Android 版本名称?【英文标题】:How to find the Android version name programmatically? 【发布时间】:2012-05-19 20:11:20 【问题描述】:我写这样的代码来查找android版本
String version=Build.VERSION.RELEASE;
通过使用此代码,我得到了版本号,但我想要版本名称。 如何获取版本名称?
【问题讨论】:
【参考方案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。以上是关于如何以编程方式查找 Android 版本名称?的主要内容,如果未能解决你的问题,请参考以下文章
如何在android中以编程方式查找TextView的文本区域(高度/宽度)
如何以编程方式从 Android 中删除 SQLite 数据库