在android系统中,/system/build.prop中含有大量系统相关的信息:
# begin build properties
# autogenerated by buildinfo.sh
ro.build.id=FRF91
ro.build.display.id=sdk-eng 2.2 FRF91 43546 test-keys
ro.build.version.incremental=43546
ro.build.version.sdk=8
ro.build.version.codename=REL
ro.build.version.release=2.2
ro.build.date=Wed Jun 30 13:58:00 PDT 2010
ro.build.date.utc=1277931480
ro.build.type=eng
ro.build.user=android-build
ro.build.host=android-test-25.mtv.corp.google.com
ro.build.tags=test-keys
ro.product.model=sdk
ro.product.brand=generic
ro.product.name=sdk
ro.product.device=generic
ro.product.board=
ro.product.cpu.abi=armeabi
ro.product.manufacturer=unknown
ro.product.locale.language=ldpi
ro.product.locale.region=
ro.wifi.channels=
ro.board.platform=
# ro.build.product is obsolete; use ro.product.device
ro.build.product=generic
# Do not try to parse ro.build.description or .fingerprint
ro.build.description=sdk-eng 2.2 FRF91 43546 test-keys
ro.build.fingerprint=generic/sdk/generic/:2.2/FRF91/43546:eng/test-keys
# end build properties
#
# system.prop for generic sdk
#
rild.libpath=/system/lib/libreference-ril.so
rild.libargs=-d /dev/ttyS0
#
# ADDITIONAL_BUILD_PROPERTIES
#
ro.config.notification_sound=OnTheHunt.ogg
ro.config.alarm_alert=Alarm_Classic.ogg
media.stagefright.enable-player=true
media.stagefright.enable-meta=true
media.stagefright.enable-scan=true
media.stagefright.enable-http=true
ro.kernel.android.checkjni=1
ro.setupwizard.mode=OPTIONAL
xmpp.auto-presence=true
ro.config.nocheckin=yes
net.bt.name=Android
dalvik.vm.stack-trace-file=/data/anr/traces.txt
想要针对不同sdk版本,进行不同的处理,就要获取sdk的版本,即ro.build.version.sdk对应的值,本来想用下面的方法获取属性值,但是获取不成功:
System.getenv("ro.build.version.sdk")
在系统源码中发现SystemProperties可以获取这些属性值,但是SystemProperties没有公布出来,于是想到用反射的办法来调用SystemProperties的方法:
package org.ckl.reflect;
import java.lang.reflect.Method;
import android.util.Log;
public class MySystemProperties {
private static final String TAG = "MySystemProperties";
// String SystemProperties.get(String key){}
public static String get(String key) {
init();
String value = null;
try {
value = (String) mGetMethod.invoke(mClassType, key);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
//int SystemProperties.get(String key, int def){}
public static int getInt(String key, int def) {
init();
int value = def;
try {
Integer v = (Integer) mGetIntMethod.invoke(mClassType, key, def);
value = v.intValue();
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
public static int getSdkVersion() {
return getInt("ro.build.version.sdk", -1);
}
//-------------------------------------------------------------------
private static Class<?> mClassType = null;
private static Method mGetMethod = null;
private static Method mGetIntMethod = null;
private static void init() {
try {
if (mClassType == null) {
mClassType = Class.forName("android.os.SystemProperties");
mGetMethod = mClassType.getDeclaredMethod("get", String.class);
mGetIntMethod = mClassType.getDeclaredMethod("getInt", String.class, int.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面的方法确实可以获取到sdk的版本:
Log.i(TAG, MySystemProperties.get("ro.build.version.sdk"));
Log.i(TAG, "" + MySystemProperties.getInt("ro.build.version.sdk", -1));
后来发现sdk中的android.os.Build完全可以提供这些信息:
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os;
import com.android.internal.telephony.TelephonyProperties;
/**
* Information about the current build, extracted from system properties.
*/
public class Build {
/** Value used for when a build property is unknown. */
public static final String UNKNOWN = "unknown";
/** Either a changelist number, or a label like "M4-rc20". */
public static final String ID = getString("ro.build.id");
/** A build ID string meant for displaying to the user */
public static final String DISPLAY = getString("ro.build.display.id");
/** The name of the overall product. */
public static final String PRODUCT = getString("ro.product.name");
/** The name of the industrial design. */
public static final String DEVICE = getString("ro.product.device");
/** The name of the underlying board, like "goldfish". */
public static final String BOARD = getString("ro.product.board");
/** The name of the instruction set (CPU type + ABI convention) of native code. */
public static final String CPU_ABI = getString("ro.product.cpu.abi");
/** The name of the second instruction set (CPU type + ABI convention) of native code. */
public static final String CPU_ABI2 = getString("ro.product.cpu.abi2");
/** The manufacturer of the product/hardware. */
public static final String MANUFACTURER = getString("ro.product.manufacturer");
/** The brand (e.g., carrier) the software is customized for, if any. */
public static final String BRAND = getString("ro.product.brand");
/** The end-user-visible name for the end product. */
public static final String MODEL = getString("ro.product.model");
/** The system bootloader version number. */
public static final String BOOTLOADER = getString("ro.bootloader");
/**
* The radio firmware version number.
*
* @deprecated The radio firmware version is frequently not
* available when this class is initialized, leading to a blank or
* "unknown" value for this string. Use
* {@link #getRadioVersion} instead.
*/
@Deprecated
public static final String RADIO = getString(TelephonyProperties.PROPERTY_BASEBAND_VERSION);
/** The name of the hardware (from the kernel command line or /proc). */
public static final String HARDWARE = getString("ro.hardware");
/** A hardware serial number, if available. Alphanumeric only, case-insensitive. */
public static final String SERIAL = getString("ro.serialno");
/** Various version strings. */
public static class VERSION {
/**
* The internal value used by the underlying source control to
* represent this build. E.g., a perforce changelist number
* or a git hash.
*/
public static final String INCREMENTAL = getString("ro.build.version.incremental");
/**
* The user-visible version string. E.g., "1.0" or "3.4b5".
*/
public static final String RELEASE = getString("ro.build.version.release");
/**
* The user-visible SDK version of the framework in its raw String
* representation; use {@link #SDK_INT} instead.
*
* @deprecated Use {@link #SDK_INT} to easily get this as an integer.
*/
@Deprecated
public static final String SDK = getString("ro.build.version.sdk");
/**
* The user-visible SDK version of the framework; its possible
* values are defined in {@link Build.VERSION_CODES}.
*/
public static final int SDK_INT = SystemProperties.getInt(
"ro.build.version.sdk", 0);
/**
* The current development codename, or the string "REL" if this is
* a release build.
*/
public static final String CODENAME = getString("ro.build.version.codename");
/**
* The SDK version to use when accessing resources.
* Use the current SDK version code. If we are a development build,
* also allow the previous SDK version + 1.
* @hide
*/
public static final int RESOURCES_SDK_INT = SDK_INT
+ ("REL".equals(CODENAME) ? 0 : 1);
}
/**
* Enumeration of the currently known SDK version codes. These are the
* values that can be found in {@link VERSION#SDK}. Version numbers
* increment monotonically with each official platform release.
*/
public static class VERSION_CODES {
/**
* Magic version number for a current development build, which has
* not yet turned into an official release.
*/
public static final int CUR_DEVELOPMENT = 10000;
/**
* October 2008: The original, first, version of Android. Yay!
*/
public static final int BASE = 1;
/**
* February 2009: First Android update, officially called 1.1.
*/
public static final int BASE_1_1 = 2;
/**
* May 2009: Android 1.5.
*/
public static final int CUPCAKE = 3;
/**
* September 2009: Android 1.6.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
* <li> They must explicitly request the
* {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission to be
* able to modify the contents of the SD card. (Apps targeting
* earlier versions will always request the permission.)
* <li> They must explicitly request the
* {@link android.Manifest.permission#READ_PHONE_STATE} permission to be
* able to be able to retrieve phone state info. (Apps targeting
* earlier versions will always request the permission.)
* <li> They are assumed to support different screen densities and
* sizes. (Apps targeting earlier versions are assumed to only support
* medium density normal size screens unless otherwise indicated).
* They can still explicitly specify screen support either way with the
* supports-screens manifest tag.
* </ul>
*/
public static final int DONUT = 4;
/**
* November 2009: Android 2.0
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
* <li> The {@link android.app.Service#onStartCommand
* Service.onStartCommand} function will return the new
* {@link android.app.Service#START_STICKY} behavior instead of the
* old compatibility {@link android.app.Service#START_STICKY_COMPATIBILITY}.
* <li> The {@link android.app.Activity} class will now execute back
* key presses on the key up instead of key down, to be able to detect
* canceled presses from virtual keys.
* <li> The {@link android.widget.TabWidget} class will use a new color scheme
* for tabs. In the new scheme, the foreground tab has a medium gray background
* the background tabs have a dark gray background.
* </ul>
*/
public static final int ECLAIR = 5;
/**
* December 2009: Android 2.0.1
*/
public static final int ECLAIR_0_1 = 6;
/**
* January 2010: Android 2.1
*/
public static final int ECLAIR_MR1 = 7;
/**
* June 2010: Android 2.2
*/
public static final int FROYO = 8;
/**
* November 2010: Android 2.3
*/
public static final int GINGERBREAD = 9;
/**
* February 2011: Android 2.3.3.
*/
public static final int GINGERBREAD_MR1 = 10;
/**
* February 2011: Android 3.0.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
* <li> The default theme for applications is now dark holographic:
* {@link android.R.style#Theme_Holo}.
* <li> The activity lifecycle has changed slightly as per
* {@link android.app.Activity}.
* <li> When an application requires a permission to access one of
* its components (activity, receiver, service, provider), this
* permission is no longer enforced when the application wants to
* access its own component. This means it can require a permission
* on a component that it does not itself hold and still access that
* component.
* </ul>
*/
public static final int HONEYCOMB = 11;
/**
* May 2011: Android 3.1.
*/
public static final int HONEYCOMB_MR1 = 12;
/**
* June 2011: Android 3.2.
*
* <p>Update to Honeycomb MR1 to support 7 inch tablets, improve
* screen compatibility mode, etc.</p>
*
* <p>As of this version, applications that don't say whether they
* support XLARGE screens will be assumed to do so only if they target
* {@link #HONEYCOMB} or later; it had been {@link #GINGERBREAD} or
* later. Applications that don't support a screen size at least as
* large as the current screen will provide the user with a UI to
* switch them in to screen size compatibility mode.</p>
*
* <p>This version introduces new screen size resource qualifiers
* based on the screen size in dp: see
* {@link android.content.res.Configuration#screenWidthDp},
* {@link android.content.res.Configuration#screenHeightDp}, and
* {@link android.content.res.Configuration#smallestScreenWidthDp}.
* Supplying these in <supports-screens> as per
* {@link android.content.pm.ApplicationInfo#requiresSmallestWidthDp},
* {@link android.content.pm.ApplicationInfo#compatibleWidthLimitDp}, and
* {@link android.content.pm.ApplicationInfo#largestWidthLimitDp} is
* preferred over the older screen size buckets and for older devices
* the appropriate buckets will be inferred from them.</p>
*
* <p>New {@link android.content.pm.PackageManager#FEATURE_SCREEN_PORTRAIT}
* and {@link android.content.pm.PackageManager#FEATURE_SCREEN_LANDSCAPE}
* features are introduced in this release. Applications that target
* previous platform versions are assumed to require both portrait and
* landscape support in the device; when targeting Honeycomb MR1 or
* greater the application is responsible for specifying any specific
* orientation it requires.</p>
*/
public static final int HONEYCOMB_MR2 = 13;
/**
* Android 4.0.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
* <ul>
* <li> For devices without a dedicated menu key, the software compatibility
* menu key will not be shown even on phones. By targeting Ice Cream Sandwich
* or later, your UI must always have its own menu UI affordance if needed,
* on both tablets and phones. The ActionBar will take care of this for you.
* <li> 2d drawing hardware acceleration is now turned on by default.
* You can use
* {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated}
* to turn it off if needed, although this is strongly discouraged since
* it will result in poor performance on larger screen devices.
* <li> The default theme for applications is now the "device default" theme:
* {@link android.R.style#Theme_DeviceDefault}. This may be the
* holo dark theme or a different dark theme defined by the specific device.
* The {@link android.R.style#Theme_Holo} family must not be modified
* for a device to be considered compatible. Applications that explicitly
* request a theme from the Holo family will be guaranteed that these themes
* will not change character within the same platform version. Applications
* that wish to blend in with the device should use a theme from the
* {@link android.R.style#Theme_DeviceDefault} family.
* <li> Managed cursors can now throw an exception if you directly close
* the cursor yourself without stopping the management of it; previously failures
* would be silently ignored.
* <li> The fadingEdge attribute on views will be ignored (fading edges is no
* longer a standard part of the UI). A new requiresFadingEdge attribute allows
* applications to still force fading edges on for special cases.
* </ul>
*/
public static final int ICE_CREAM_SANDWICH = 14;
}
/** The type of build, like "user" or "eng". */
public static final String TYPE = getString("ro.build.type");
/** Comma-separated tags describing the build, like "unsigned,debug". */
public static final String TAGS = getString("ro.build.tags");
/** A string that uniquely identifies this build. Do not attempt to parse this value. */
public static final String FINGERPRINT = getString("ro.build.fingerprint");
// The following properties only make sense for internal engineering builds.
public static final long TIME = getLong("ro.build.date.utc") * 1000;
public static final String USER = getString("ro.build.user");
public static final String HOST = getString("ro.build.host");
/**
* Returns the version string for the radio firmware. May return
* null (if, for instance, the radio is not currently on).
*/
public static String getRadioVersion() {
return SystemProperties.get(TelephonyProperties.PROPERTY_BASEBAND_VERSION, null);
}
private static String getString(String property) {
return SystemProperties.get(property, UNKNOWN);
}
private static long getLong(String property) {
try {
return Long.parseLong(SystemProperties.get(property));
} catch (NumberFormatException e) {
return -1;
}
}
}
也是调用SystemProperties实现的:
private static String getString(String property) {
return SystemProperties.get(property, UNKNOWN);
}
package org.ckl.reflect;
import android.os.Build;
import android.util.Log;
public class AndroidInfo {
private static final String TAG = "AndroidInfo";
private AndroidInfo() {}
public static void info() {
String info =
"Product: " + Build.PRODUCT
+ ", CPU_ABI: " + Build.CPU_ABI
+ ", TAGS: " + Build.TAGS
+ ", VERSION_CODES.BASE: " + Build.VERSION_CODES.BASE
+ ", MODEL: " + Build.MODEL
+ ", SDK: " + Build.VERSION.SDK
+ ", VERSION.RELEASE: " + Build.VERSION.RELEASE
+ ", DEVICE: " + Build.DEVICE
+ ", DISPLAY: " + Build.DISPLAY
+ ", BRAND: " + Build.BRAND
+ ", BOARD: " + Build.BOARD
+ ", FINGERPRINT: " + Build.FINGERPRINT
+ ", ID: " + Build.ID
+ ", MANUFACTURER: " + Build.MANUFACTURER
+ ", USER: " + Build.USER;
Log.i(TAG, info);
}
}