SystemProperties这个涉及的东西比较多,我这里只讲点简单的概念和常用的属性.
Android的系统属性,主要分为两种:
1. 用文件保存的持久属性
mydroid\bionic\libc\include\sys\_system_properties.h 这个文件中有定义:
/* ** Rules: ** ** - there is only one writer, but many readers ** - prop_area.count will never decrease in value ** - once allocated, a prop_info's name will not change ** - once allocated, a prop_info's offset will not change ** - reading a value requires the following steps ** 1. serial = pi->serial ** 2. if SERIAL_DIRTY(serial), wait*, then goto 1 ** 3. memcpy(local, pi->value, SERIAL_VALUE_LEN(serial) + 1) ** 4. if pi->serial != serial, goto 2 ** ** - writing a value requires the following steps ** 1. pi->serial = pi->serial | 1 ** 2. memcpy(pi->value, local_value, value_len) ** 3. pi->serial = (value_len <<24) | ((pi->serial + 1) & 0xffffff) */ #define PROP_PATH_RAMDISK_DEFAULT "/default.prop" #define PROP_PATH_SYSTEM_BUILD "/system/build.prop" #define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop" #define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop" #define PROP_PATH_FACTORY "/factory/factory.prop"
2.每次开机都会导入的Cache属性,Framework层通过:
frameworks\base\core\java\android\os\SystemProperties.java 这个类来操作.
Cache的存储方式为:
/* * Properties are stored in a hybrid trie/binary tree structure. * Each property's name is delimited at '.' characters, and the tokens are put * into a trie structure. Siblings at each level of the trie are stored in a * binary tree. For instance, "ro.secure"="1" could be stored as follows: * * +-----+ children +----+ children +--------+ * | |-------------->| ro |-------------->| secure | * +-----+ +----+ +--------+ * / \ / | * left / \ right left / | prop +===========+ * v v v +-------->| ro.secure | * +-----+ +-----+ +-----+ +-----------+ * | net | | sys | | com | | 1 | * +-----+ +-----+ +-----+ +===========+ */
如何获取Android的系统属性
1.通过android.os.Build这个类,我们可以得到一些基本信息:
以下是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. * *Applications targeting this or a later release will get these * new changes in behavior:
*
Applications targeting this or a later release will get these * new changes in behavior:
*Applications targeting this or a later release will get these * new changes in behavior:
*Applications targeting this or a later release will get these * new changes in behavior:
*Update to Honeycomb MR1 to support 7 inch tablets, improve * screen compatibility mode, etc.
* *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.
* *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
Applications targeting this or a later release will get these * new changes in behavior:
*New {@link android.content.pm.PackageManager#FEATURE_SCREEN_PORTRAIT} * and {@link android.content.pm.PackageManager#FEATURE_SCREEN_LANDSCAPE} * features were 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.
*{@link android.os.AsyncTask} will use the serial executor * by default when calling {@link android.os.AsyncTask#execute}.
*{@link android.content.pm.ActivityInfo#configChanges * ActivityInfo.configChanges} will have the * {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE} and * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE} * bits set; these need to be cleared for older applications because * some developers have done absolute comparisons against this value * instead of correctly masking the bits they are interested in. *
Applications targeting this or a later release will get these * new changes in behavior:
*Applications targeting this or a later release will get these * new changes in behavior:
*Applications targeting this or a later release will get these * new changes in behavior:
*那么就写一个例子,把Build中能查到的所有属性都打印出来吧,当然手机用的是我的花屏MX3.
public class MainActivity extends Activity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); StringBuffer sb = new StringBuffer(); sb.append("ro.build.id"+" : "+Build.ID+"\n"); sb.append("ro.build.display.id"+" : "+Build.DISPLAY+"\n"); sb.append("ro.product.name"+" : "+Build.PRODUCT+"\n"); sb.append("ro.product.device"+" : "+Build.DEVICE+"\n"); sb.append("ro.product.board"+" : "+Build.BOARD+"\n"); sb.append("ro.product.cpu.abi"+" : "+Build.CPU_ABI+"\n"); sb.append("ro.product.cpu.abi2"+" : "+Build.CPU_ABI2+"\n"); sb.append("ro.product.manufacturer"+" : "+Build.MANUFACTURER+"\n"); sb.append("ro.product.brand"+" : "+Build.BRAND+"\n"); sb.append("ro.product.model"+" : "+Build.MODEL+"\n"); sb.append("ro.bootloader"+" : "+Build.BOOTLOADER+"\n"); sb.append("ro.hardware"+" : "+Build.HARDWARE+"\n"); sb.append("ro.serialno"+" : "+Build.SERIAL+"\n"); sb.append("ro.build.type"+" : "+Build.TYPE+"\n"); sb.append("ro.build.tags"+" : "+Build.TAGS+"\n"); sb.append("ro.build.fingerprint"+" : "+Build.FINGERPRINT+"\n"); sb.append("ro.build.date.utc"+" : "+Build.TIME+"\n"); sb.append("ro.build.user"+" : "+Build.USER+"\n"); sb.append("ro.build.host"+" : "+Build.HOST+"\n"); sb.append("radioVersion"+" : "+Build.getRadioVersion()+"\n"); sb.append("ro.build.version.incremental"+" : "+Build.VERSION.INCREMENTAL+"\n"); sb.append("ro.build.version.release"+" : "+Build.VERSION.RELEASE+"\n"); sb.append("ro.build.version.sdk"+" : "+Build.VERSION.SDK_INT+"\n"); sb.append("ro.build.version.codename"+" : "+Build.VERSION.CODENAME+"\n"); tv = (TextView) findViewById(R.id.show); tv.setText(sb.toString()); } }
运行截图:
2.通过反射,直接调用SystemProperties这个类的方法:
当手机通过adb连接电脑后,我们可以通过 adb shell getprop > d:\prop.txt 来获得系统的所有属性值.
而Build这个类获得的属性有限,所以通过反射,我们可以获得更多的信息.
我们发现,Build中有个用 hide标记的属性,让我们用反射把他们show出来
/** * Returns true if we are running a debug build such as "user-debug" or "eng". * @hide */ public static final boolean IS_DEBUGGABLE = SystemProperties.getInt("ro.debuggable", 0) == 1;
public class MainActivity extends Activity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { Class> classT = Class.forName("android.os.SystemProperties"); Method m = classT.getMethod("getInt", new Class[]{String.class,int.class}); int isDebugable = (Integer) m.invoke(classT,new Object[]{"ro.debuggable",0}); tv = (TextView) findViewById(R.id.show); tv.setText(" "+(isDebugable == 1)); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }