Android如何獲取手機各項資訊

DroidMind發表於2015-11-13

1、使用Build獲取架構屬性
下面我們來根據原始碼看看通過Build這個類可以得到哪些配置資訊,具體就不解釋了,從命名基本可以理解其代表的屬性。

public class Build {
    //當一個版本屬性不知道時所設定的值。
    public static final String UNKNOWN = "unknown";
    //修訂版本列表碼
    public static final String ID = getString("ro.build.id");
    //螢幕引數
    public static final String DISPLAY = getString("ro.build.display.id");
    //整個產品的名稱
    public static final String PRODUCT = getString("ro.product.name");
    //裝置引數
    public static final String DEVICE = getString("ro.product.device");
    //主機板
    public static final String BOARD = getString("ro.product.board");
    //cpu指令集
    public static final String CPU_ABI = getString("ro.product.cpu.abi");
    //cpu指令集2
    public static final String CPU_ABI2 = getString("ro.product.cpu.abi2");
    //硬體製造商
    public static final String MANUFACTURER = getString("ro.product.manufacturer");
    //系統定製商
    public static final String BRAND = getString("ro.product.brand");
    //版本即終端使用者可見的名稱
    public static final String MODEL = getString("ro.product.model");
    //系統啟動程式版本號
    public static final String BOOTLOADER = getString("ro.bootloader");
    //硬體名稱
    public static final String HARDWARE = getString("ro.hardware");
    //硬體序列號
    public static final String SERIAL = getString("ro.serialno");
    //build的型別
    public static final String TYPE = getString("ro.build.type");
    //描述build的標籤,如未簽名,debug等等。
    public static final String TAGS = getString("ro.build.tags");
    //唯一識別碼
    public static final String FINGERPRINT = getString("ro.build.fingerprint");

    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");
    //獲取無線電韌體版本
    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;
        }
    }

  //各種版本字串
    public static class VERSION {
        public static final String INCREMENTAL = getString("ro.build.version.incremental");
        public static final String RELEASE = getString("ro.build.version.release");
        public static final int SDK_INT = SystemProperties.getInt(
                "ro.build.version.sdk", 0);
        public static final String CODENAME = getString("ro.build.version.codename");
    }

    //目前已知的版本程式碼的列舉類
    public static class VERSION_CODES {
        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.
         */
        public static final int DONUT = 4;

        /**
         * November 2009: Android 2.0
         */
        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.
         */
        public static final int HONEYCOMB = 11;

        /**
         * May 2011: Android 3.1.
         */
        public static final int HONEYCOMB_MR1 = 12;

        /**
         * June 2011: Android 3.2.
         */
        public static final int HONEYCOMB_MR2 = 13;

        /**
         * October 2011: Android 4.0.
         */
        public static final int ICE_CREAM_SANDWICH = 14;

        /**
         * December 2011: Android 4.0.3.
         */
        public static final int ICE_CREAM_SANDWICH_MR1 = 15;

        /**
         * June 2012: Android 4.1.
         */
        public static final int JELLY_BEAN = 16;

        /**
         * Android 4.2: Moar jelly beans!
         */
        public static final int JELLY_BEAN_MR1 = 17;

        /**
         * Android 4.3: Jelly Bean MR2, the revenge of the beans.
         */
        public static final int JELLY_BEAN_MR2 = 18;

        /**
         * Android 4.4: KitKat, another tasty treat.
         */
        public static final int KITKAT = 19;
    }

}

下面舉個例子:

/**
 * 獲取裝置資訊
 * 
 * @return
 */
private String getDeviceInfo() {
  StringBuffer sb = new StringBuffer();
  sb.append(主機板: + Build.BOARD);
  sb.append(系統啟動程式版本號: + Build.BOOTLOADER);
  sb.append(系統定製商: + Build.BRAND);
  sb.append(cpu指令集: + Build.CPU_ABI);
  sb.append(cpu指令集2 + Build.CPU_ABI2);
  sb.append(設定引數: + Build.DEVICE);
  sb.append(螢幕引數: + Build.DISPLAY);
  sb.append(www.2cto.com無線電韌體版本: + Build.getRadioVersion());
  sb.append(硬體識別碼: + Build.FINGERPRINT);
  sb.append(硬體名稱: + Build.HARDWARE);
  sb.append(HOST: + Build.HOST);
  sb.append(修訂版本列表: + Build.ID);
  sb.append(硬體製造商: + Build.MANUFACTURER);
  sb.append(版本: + Build.MODEL);
  sb.append(硬體序列號: + Build.SERIAL);
  sb.append(手機制造商: + Build.PRODUCT);
  sb.append(描述Build的標籤: + Build.TAGS);
  sb.append(TIME: + Build.TIME);
  sb.append(builder型別: + Build.TYPE);
  sb.append(USER: + Build.USER);
  return sb.toString();
}

2、ActivityManager獲取記憶體資訊

在ActivityManager裡面有個getMemoryInfo函式,可以獲取到記憶體資訊。

public void getMemoryInfo(MemoryInfo outInfo) {
    try {
        ActivityManagerNative.getDefault().getMemoryInfo(outInfo);
    } catch (RemoteException e) {
    }
}

下面我們來看看MemoryInfo這個類:

public static class MemoryInfo implements Parcelable {
    public long availMem;
    public long totalMem;
    public long threshold;
    public boolean lowMemory;

    public MemoryInfo() {
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(availMem);
        dest.writeLong(totalMem);
        dest.writeLong(threshold);
        dest.writeInt(lowMemory ? 1 : 0);
        dest.writeLong(hiddenAppThreshold);
        dest.writeLong(secondaryServerThreshold);
        dest.writeLong(visibleAppThreshold);
        dest.writeLong(foregroundAppThreshold);
    }

    public void readFromParcel(Parcel source) {
        availMem = source.readLong();
        totalMem = source.readLong();
        threshold = source.readLong();
        lowMemory = source.readInt() != 0;
        hiddenAppThreshold = source.readLong();
        secondaryServerThreshold = source.readLong();
        visibleAppThreshold = source.readLong();
        foregroundAppThreshold = source.readLong();
    }

    public static final Creator<MemoryInfo> CREATOR
            = new Creator<MemoryInfo>() {
        public MemoryInfo createFromParcel(Parcel source) {
            return new MemoryInfo(source);
        }
        public MemoryInfo[] newArray(int size) {
            return new MemoryInfo[size];
        }
    };

    private MemoryInfo(Parcel source) {
        readFromParcel(source);
    }
}

另外,需要說明的是,我們可以直接讀取系統的一個檔案來獲取記憶體資訊。這個檔案目錄為:/proc/meminfo
如下圖:

這裡寫圖片描述

3、獲取SDCard儲存

/** 
 * 獲得SD卡總大小 
 *  
 * @return 
 */  
private String getSDTotalSize() {  
    File path = Environment.getExternalStorageDirectory();  
    StatFs stat = new StatFs(path.getPath());  
    long blockSize = stat.getBlockSize();  
    long totalBlocks = stat.getBlockCount();  
    return Formatter.formatFileSize(MainActivity.this, blockSize * totalBlocks);  
}  

/** 
 * 獲得sd卡剩餘容量,即可用大小 
 *  
 * @return 
 */  
private String getSDAvailableSize() {  
    File path = Environment.getExternalStorageDirectory();  
    StatFs stat = new StatFs(path.getPath());  
    long blockSize = stat.getBlockSize();  
    long availableBlocks = stat.getAvailableBlocks();  
    return Formatter.formatFileSize(MainActivity.this, blockSize * availableBlocks);  
}  

/** 
 * 獲得機身記憶體總大小 
 *  
 * @return 
 */  
private String getRomTotalSize() {  
    File path = Environment.getDataDirectory();  
    StatFs stat = new StatFs(path.getPath());  
    long blockSize = stat.getBlockSize();  
    long totalBlocks = stat.getBlockCount();  
    return Formatter.formatFileSize(MainActivity.this, blockSize * totalBlocks);  
}  

/** 
 * 獲得機身可用記憶體 
 *  
 * @return 
 */  
private String getRomAvailableSize() {  
    File path = Environment.getDataDirectory();  
    StatFs stat = new StatFs(path.getPath());  
    long blockSize = stat.getBlockSize();  
    long availableBlocks = stat.getAvailableBlocks();  
    return Formatter.formatFileSize(MainActivity.this, blockSize * availableBlocks);  
} 

另外,我們可以通過StorageManager來獲取其他的資訊,但需要注意的是有些方法需要使用反射來呼叫,因為它們是不可見的。

4、讀取CPU資訊

我們可以讀取系統目錄下/proc/cpuinfo的檔案來獲取CPU資訊。如下圖所示,事實上,我們可以檢視/proc目錄的所有檔案,來檢視各種資訊。

這裡寫圖片描述

/proc/cmdline:顯示核心啟動的命令列。
/proc/cpuinfo:顯示系統cpu的資訊。
/proc/filesystems,顯示當前註冊了的檔案系統列表,nodev表示為虛擬檔案系統。
/proc/interrupts:顯示當前系統的中斷資訊.
/proc/ioports:被佔用的輸入/輸出地址範圍列表。
/proc/kmsg:輸出核心訊息日誌。
/proc/loadavg:監控cpu平均負載,其數值為所有核上cpu佔用的累加值,前三個分別表示最近1515分鐘的平均負載,第四個表示當前執行程式數和程式總數,最後一個表示最近執行的程式id。
/proc/locks:開啟檔案上的加鎖資訊。
/proc/meminfo:顯示物理及虛擬記憶體使用情況。
/proc/misc:核心函式misc_register登記的裝置驅動程式。
/proc/modules:載入的核心模組列表。
/proc/mounts:當前系統所安裝的檔案系統資訊(包括手動安裝的)。
/proc/stat:系統簡要資訊。
/proc/uptime:分別表示系統啟動時間和系統空閒時間。
/proc/version:系統核心版本。
/proc/net:其實際掛載點是/proc/self/net,能夠顯示當前各種網路情況,例如通過tcp檔案可以檢視tcp連線數及連線情況。
/proc/sys 報告各種不同的核心引數,某些引數能在root的情況下進行修改。
/proc/devices 當前掛載的所有軟硬體裝置(字元裝置和塊裝置),包括主裝置號和裝置名稱。
/proc/asound:音效卡相關的資訊。
/proc/buddyinfo:每個記憶體區中每個order有多少塊可用,和記憶體碎片問題有關。
/proc/bus:輸入裝置資訊。
/proc/cgroups:檢視cgroups子系統資訊。
/proc/diskstats:用於顯示磁碟、分割槽和統計資訊。
/proc/execdomains:安全相關的資訊。
/proc/fb:幀緩衝裝置資訊。
/proc/iomem:記錄實體地址的分配情況。
/proc/kallsyms:核心符號表資訊。
/proc/pagetypeinfo:記憶體分頁資訊。
/proc/partitions:分割槽資訊
/proc/sched_debug:cpu排程資訊。
/proc/softirqs:軟中斷情況。
/proc/vmallocinfo:vmalloc記憶體分配資訊。
/proc/vmstat:統計虛擬記憶體資訊。
/proc/pid:顯示進城相關的所有資訊。

5、獲取電池電量資訊

獲取到電池資訊一般可以通過兩個類獲取:android.content.BroadcastReceiver類和android.os.BatteryManager類

在BroadcastReceiver的onReceive()事件,接收到的Intent.ACTION_BATTERY_CHANGED,包括下面的資訊:

“status”(int型別)…狀態,定義值是BatteryManager.BATTERY_STATUS_XXX。
“health”(int型別)…健康,定義值是BatteryManager.BATTERY_HEALTH_XXX。
“present”(boolean型別)
“level”(int型別)…電池剩餘容量
“scale”(int型別)…電池最大值。通常為100。
“icon-small”(int型別)…圖示ID。
“plugged”(int型別)…連線的電源插座,定義值是BatteryManager.BATTERY_PLUGGED_XXX。
“voltage”(int型別)…mV。
“temperature”(int型別)…溫度,0.1度單位。例如 表示197的時候,意思為19.7度。
“technology”(String型別)…電池型別,例如,Li-ion等等。
public class BatteryTestActivity extends Activity {
     /** Called when the activity is first created. */
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);        
     }

     @Override
     protected void onResume() {
         super.onResume();

         IntentFilter filter = new IntentFilter();

         filter.addAction(Intent.ACTION_BATTERY_CHANGED);
         registerReceiver(mBroadcastReceiver, filter);
     }

     @Override
     protected void onPause() {
         super.onPause();

         unregisterReceiver(mBroadcastReceiver);
     }

     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                 int status = intent.getIntExtra("status", 0);
                 int health = intent.getIntExtra("health", 0);
                 boolean present = intent.getBooleanExtra("present", false);
                 int level = intent.getIntExtra("level", 0);
                 int scale = intent.getIntExtra("scale", 0);
                 int icon_small = intent.getIntExtra("icon-small", 0);
                 int plugged = intent.getIntExtra("plugged", 0);
                 int voltage = intent.getIntExtra("voltage", 0);
                 int temperature = intent.getIntExtra("temperature", 0);
                 String technology = intent.getStringExtra("technology");

                 String statusString = "";

                 switch (status) {
                 case BatteryManager.BATTERY_STATUS_UNKNOWN:
                     statusString = "unknown";
                     break;
                 case BatteryManager.BATTERY_STATUS_CHARGING:
                     statusString = "charging";
                     break;
                 case BatteryManager.BATTERY_STATUS_DISCHARGING:
                     statusString = "discharging";
                     break;
                 case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
                     statusString = "not charging";
                     break;
                 case BatteryManager.BATTERY_STATUS_FULL:
                     statusString = "full";
                     break;
                 }

                 String healthString = "";

                 switch (health) {
                 case BatteryManager.BATTERY_HEALTH_UNKNOWN:
                     healthString = "unknown";
                     break;
                 case BatteryManager.BATTERY_HEALTH_GOOD:
                     healthString = "good";
                     break;
                 case BatteryManager.BATTERY_HEALTH_OVERHEAT:
                     healthString = "overheat";
                     break;
                 case BatteryManager.BATTERY_HEALTH_DEAD:
                     healthString = "dead";
                     break;
                 case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
                     healthString = "voltage";
                     break;
                 case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
                     healthString = "unspecified failure";
                     break;
                 }

                 String acString = "";

                 switch (plugged) {
                 case BatteryManager.BATTERY_PLUGGED_AC:
                     acString = "plugged ac";
                     break;
                 case BatteryManager.BATTERY_PLUGGED_USB:
                     acString = "plugged usb";
                     break;
                 }

                 Log.v("status", statusString);
                 Log.v("health", healthString);
                 Log.v("present", String.valueOf(present));
                 Log.v("level", String.valueOf(level));
                 Log.v("scale", String.valueOf(scale));
                 Log.v("icon_small", String.valueOf(icon_small));
                 Log.v("plugged", acString);
                 Log.v("voltage", String.valueOf(voltage));
                 Log.v("temperature", String.valueOf(temperature));
                 Log.v("technology", technology);
             }
         }
     };
 }

應用程式為了取得電池的狀態,通常的做法是監聽ACTION_BATTERY_CHANGED這個intent,只能在收到這個intent的時候才能取得電池的狀態資訊,有沒有同步取得電池資訊的辦法呢?

實際上,系統driver維護著儲存電池資訊的一組檔案。

/sys/class/power_supply/ac/online  AC電源連線狀態
/sys/class/power_supply/usb/online USB電源連線狀態
/sys/class/power_supply/battery/status  充電狀態
/sys/class/power_supply/battery/health  電池狀態
/sys/class/power_supply/battery/present 使用狀態
/sys/class/power_supply/battery/capacity 電池level
/sys/class/power_supply/battery/batt_vol 電池電壓
/sys/class/power_supply/battery/batt_temp 電池溫度
/sys/class/power_supply/battery/technology 電池技術

當電池狀態發生變化時,driver會更新這些檔案,因此在應用程式中通過讀取這些檔案的辦法,可以做到同步取得電池資訊。

6、獲取手機各種狀態資訊

TelephonyManager tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);       

/*    
* 電話狀態:    
* 1.tm.CALL_STATE_IDLE=0          無活動    
* 2.tm.CALL_STATE_RINGING=1  響鈴    
* 3.tm.CALL_STATE_OFFHOOK=2  摘機    
*/      
tm.getCallState();//int       

/*    
* 電話方位:    
*     
*/      
tm.getCellLocation();//CellLocation       

/*    
* 唯一的裝置ID:    
* GSM手機的 IMEI 和 CDMA手機的 MEID.     
* Return null if device ID is not available.    
*/      
tm.getDeviceId();//String       

/*    
* 裝置的軟體版本號:    
* 例如:the IMEI/SV(software version) for GSM phones.    
* Return null if the software version is not available.     
*/      
tm.getDeviceSoftwareVersion();//String       

/*    
* 手機號:    
* GSM手機的 MSISDN.    
* Return null if it is unavailable.     
*/      
tm.getLine1Number();//String       

/*    
* 附近的電話的資訊:    
* 型別:List<NeighboringCellInfo>     
* 需要許可權:android.Manifest.permission#ACCESS_COARSE_UPDATES    
*/      
tm.getNeighboringCellInfo();//List<NeighboringCellInfo>       

/*    
* 獲取ISO標準的國家碼,即國際長途區號。    
* 注意:僅當使用者已在網路註冊後有效。    
*       在CDMA網路中結果也許不可靠。    
*/      
tm.getNetworkCountryIso();//String       

/*    
* MCC+MNC(mobile country code + mobile network code)    
* 注意:僅當使用者已在網路註冊時有效。    
*    在CDMA網路中結果也許不可靠。    
*/      
tm.getNetworkOperator();//String       

/*    
* 按照字母次序的current registered operator(當前已註冊的使用者)的名字    
* 注意:僅當使用者已在網路註冊時有效。    
*    在CDMA網路中結果也許不可靠。    
*/      
tm.getNetworkOperatorName();//String       

/*    
* 當前使用的網路型別:    
* 例如: NETWORK_TYPE_UNKNOWN  網路型別未知  0    
NETWORK_TYPE_GPRS     GPRS網路  1    
NETWORK_TYPE_EDGE     EDGE網路  2    
NETWORK_TYPE_UMTS     UMTS網路  3    
NETWORK_TYPE_HSDPA    HSDPA網路  8     
NETWORK_TYPE_HSUPA    HSUPA網路  9    
NETWORK_TYPE_HSPA     HSPA網路  10    
NETWORK_TYPE_CDMA     CDMA網路,IS95A 或 IS95B.  4    
NETWORK_TYPE_EVDO_0   EVDO網路, revision 0.  5    
NETWORK_TYPE_EVDO_A   EVDO網路, revision A.  6    
NETWORK_TYPE_1xRTT    1xRTT網路  7    
*/      
tm.getNetworkType();//int       

/*    
* 手機型別:    
* 例如: PHONE_TYPE_NONE  無訊號    
PHONE_TYPE_GSM   GSM訊號    
PHONE_TYPE_CDMA  CDMA訊號    
*/      
tm.getPhoneType();//int       

/*    
* Returns the ISO country code equivalent for the SIM provider's country code.    
* 獲取ISO國家碼,相當於提供SIM卡的國家碼。    
*     
*/      
tm.getSimCountryIso();//String       

/*    
* Returns the MCC+MNC (mobile country code + mobile network code) of the provider of the SIM. 5 or 6 decimal digits.    
* 獲取SIM卡提供的移動國家碼和行動網路碼.5或6位的十進位制數字.    
* SIM卡的狀態必須是 SIM_STATE_READY(使用getSimState()判斷).    
*/      
tm.getSimOperator();//String       

/*    
* 服務商名稱:    
* 例如:中國移動、聯通    
* SIM卡的狀態必須是 SIM_STATE_READY(使用getSimState()判斷).    
*/      
tm.getSimOperatorName();//String       

/*    
* SIM卡的序列號:    
* 需要許可權:READ_PHONE_STATE    
*/      
tm.getSimSerialNumber();//String       

/*    
* SIM的狀態資訊:    
*  SIM_STATE_UNKNOWN          未知狀態 0    
SIM_STATE_ABSENT           沒插卡 1    
SIM_STATE_PIN_REQUIRED     鎖定狀態,需要使用者的PIN碼解鎖 2    
SIM_STATE_PUK_REQUIRED     鎖定狀態,需要使用者的PUK碼解鎖 3    
SIM_STATE_NETWORK_LOCKED   鎖定狀態,需要網路的PIN碼解鎖 4    
SIM_STATE_READY            就緒狀態 5    
*/      
tm.getSimState();//int       

/*    
* 唯一的使用者ID:    
* 例如:IMSI(國際移動使用者識別碼) for a GSM phone.    
* 需要許可權:READ_PHONE_STATE    
*/      
tm.getSubscriberId();//String       

/*    
* 取得和語音郵件相關的標籤,即為識別符    
* 需要許可權:READ_PHONE_STATE    
*/      
tm.getVoiceMailAlphaTag();//String       

/*    
* 獲取語音郵件號碼:    
* 需要許可權:READ_PHONE_STATE    
*/      
tm.getVoiceMailNumber();//String       

/*    
* ICC卡是否存在    
*/      
tm.hasIccCard();//boolean       

/*    
* 是否漫遊:    
* (在GSM用途下)    
*/      
tm.isNetworkRoaming();// 

值得注意的是,這個需要android.permission.READ_PHONE_STATE許可權。

6、獲取流量資訊

有兩種方法,一種是使用TrafficStats類,另一種就是讀取系統流量檔案:/proc/net/xt_qtaguid/stats

關於第一種方法:參考文章:Android中TrafficStats流量監控類

參考文章:
獲取Android手機各種狀態資訊

Android 獲取系統 cpu 資訊,記憶體,版本,電量等資訊

Android系統/proc目錄詳解

Android獲取SD卡總容量,可用大小,機身記憶體總容量及可用大小的系統方法

Android Low Memory Killer

相關文章