APK 获取设备信息

头文件

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

获取设备型号

public static String getDeviceModel() {
return Build.MODEL;
}

获取设备制造商

public static String getManufacturer() {
return Build.MANUFACTURER;
}

获取Android版本号

public static String getAndroidVersion() {
return Build.VERSION.RELEASE;
}

获取SDK版本信息

public static int getDeviceSDK(){
return android.os.Build.VERSION.SDK_INT;
}

获取当前设备安全补丁级别日期

public static String getSecurityPatchLevel() {
return Build.VERSION.SECURITY_PATCH;
}

获取设备制造商

public static String getDeviceMANUFACTURER() {
return Build.SOC_MANUFACTURER;
}

获取构建的内部版本

内部版本Build IDrb-a3568/build/make/core/build_id.mk 目录下

public static String getBuildID() {
return Build.ID;
}

获取显示信息

public static String getDisplay() {
return Build.DISPLAY;
}

获取设备硬件名

public static String getHardware() {
return Build.HARDWARE;
}

获取设备CPU架构

public static String getCpuArchitecture() {
return Build.CPU_ABI;
}

获取CPU名称

通过读取Linux文件的形式获取

public static String getCpuName() {
String str1 = "/proc/cpuinfo";
String str2 = "";
String cpuName = "";
try {
FileReader fileReader = new FileReader(str1);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((str2 = bufferedReader.readLine()) != null) {
// 为空跳过
if (TextUtils.isEmpty(str2)) {
continue;
}
// 进行 分割 对比
// 使用split(":\\s+", 2)方法将字符串str2按冒号和后续空格分割成最多两部分。例如,"Hardware: Intel Core i7"会被分成["Hardware", "Intel Core i7"]。
String[] arrayOfString = str2.split(":\\s+", 2);
if (TextUtils.equals(arrayOfString[0].trim(), "Hardware")) {
cpuName = arrayOfString[1];
break;
}
}
bufferedReader.close();
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
return cpuName;
}

获取CPU核数

public static String getCpuCores() {
return Build.CPU_ABI;
}

获取CPU频率

public static final int DEVICEINFO_UNKNOWN = -1;
/**
* Method for reading the clock speed of a CPU core on the device. Will read from either
* {@code /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq} or {@code /proc/cpuinfo}.
*
* @return Clock speed of a core on the device, or -1 in the event of an error.
* 获取 CPU 频率
*/
public static ArrayList<Integer> getCPUFreqMHzs() {
int maxFreq = DEVICEINFO_UNKNOWN;
int curFreq = 0;
ArrayList<Integer> arrayList = new ArrayList<Integer>();
try {
int coreNum = getNumberOfCPUCores();
for (int i = 0; i < coreNum; i++) {
String filename =
"/sys/devices/system/cpu/cpu" + i + "/cpufreq/cpuinfo_max_freq";
File cpuInfoMaxFreqFile = new File(filename);
if (cpuInfoMaxFreqFile.exists() && cpuInfoMaxFreqFile.canRead()) {
byte[] buffer = new byte[128];
FileInputStream stream = new FileInputStream(cpuInfoMaxFreqFile);
try {
stream.read(buffer);
int endIndex = 0;
// Trim the first number out of the byte buffer.
while (Character.isDigit(buffer[endIndex]) && endIndex < buffer.length) {
endIndex++;
}
String str = new String(buffer, 0, endIndex);
// 频率是按照1000计算
curFreq = Integer.parseInt(str) / 1000;
arrayList.add(curFreq);
} catch (NumberFormatException e) {
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
stream.close();
}
}
}
if (maxFreq == DEVICEINFO_UNKNOWN && arrayList.size() == 0) {
FileInputStream stream = new FileInputStream("/proc/cpuinfo");
try {
int freqBound = parseFileForValue("cpu MHz", stream);
curFreq = freqBound;
arrayList.add(curFreq);
} finally {
stream.close();
}
}
} catch (IOException e) {
}
return arrayList;
}
/**
* Reads the number of CPU cores from the first available information from
* {@code /sys/devices/system/cpu/possible}, {@code /sys/devices/system/cpu/present},
* then {@code /sys/devices/system/cpu/}.
*
* @return Number of CPU cores in the phone, or DEVICEINFO_UKNOWN = -1 in the event of an error.
*/
public static int getNumberOfCPUCores() {
int coreNumber = -1;
if (coreNumber != DEVICEINFO_UNKNOWN) {
return coreNumber;
}
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
// Gingerbread doesn't support giving a single application access to both cores, but a
// handful of devices (Atrix 4G and Droid X2 for example) were released with a dual-core
// chipset and Gingerbread; that can let an app in the background run without impacting
// the foreground application. But for our purposes, it makes them single core.
coreNumber = 1;
return coreNumber;
}
int cores;
try {
cores = getCoresFromFileInfo("/sys/devices/system/cpu/present");
if (cores == DEVICEINFO_UNKNOWN) {
cores = new File("/sys/devices/system/cpu/").listFiles(CPU_FILTER).length;;
}
} catch (SecurityException e) {
cores = DEVICEINFO_UNKNOWN;
} catch (NullPointerException e) {
cores = DEVICEINFO_UNKNOWN;
}
coreNumber = cores;
return coreNumber;
} /**
* Tries to read file contents from the file location to determine the number of cores on device.
* @param fileLocation The location of the file with CPU information
* @return Number of CPU cores in the phone, or DEVICEINFO_UKNOWN = -1 in the event of an error.
*/
private static int getCoresFromFileInfo(String fileLocation) {
InputStream is = null;
try {
is = new FileInputStream(fileLocation);
BufferedReader buf = new BufferedReader(new InputStreamReader(is));
String fileContents = buf.readLine();
buf.close();
return getCoresFromFileString(fileContents);
} catch (IOException e) {
return DEVICEINFO_UNKNOWN;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
// Do nothing.
}
}
}
} /**
* Converts from a CPU core information format to number of cores.
* @param str The CPU core information string, in the format of "0-N"
* @return The number of cores represented by this string
*/
private static int getCoresFromFileString(String str) {
if (str == null || !str.matches("0-[\\d]+$")) {
return DEVICEINFO_UNKNOWN;
}
return Integer.valueOf(str.substring(2)) + 1;
} private static final FileFilter CPU_FILTER = new FileFilter() {
@Override
public boolean accept(File pathname) {
String path = pathname.getName();
//regex is slow, so checking char by char.
if (path.startsWith("cpu")) {
for (int i = 3; i < path.length(); i++) {
if (!Character.isDigit(path.charAt(i))) {
return false;
}
}
return true;
}
return false;
}
}; /**
* Helper method for reading values from system files, using a minimised buffer.
*
* @param textToMatch - Text in the system files to read for.
* @param stream - FileInputStream of the system file being read from.
* @return A numerical value following textToMatch in specified the system file.
* -1 in the event of a failure.
*/
private static int parseFileForValue(String textToMatch, FileInputStream stream) {
byte[] buffer = new byte[1024];
try {
int length = stream.read(buffer);
for (int i = 0; i < length; i++) {
if (buffer[i] == '\n' || i == 0) {
if (buffer[i] == '\n') i++;
for (int j = i; j < length; j++) {
int textIndex = j - i;
//Text doesn't match query at some point.
if (buffer[j] != textToMatch.charAt(textIndex)) {
break;
}
//Text matches query here.
if (textIndex == textToMatch.length() - 1) {
return extractValue(buffer, j);
}
}
}
}
} catch (IOException e) {
//Ignore any exceptions and fall through to return unknown value.
} catch (NumberFormatException e) {
}
return DEVICEINFO_UNKNOWN;
} /**
* Helper method used by {@link #parseFileForValue(String, FileInputStream) parseFileForValue}. Parses
* the next available number after the match in the file being read and returns it as an integer.
* @param index - The index in the buffer array to begin looking.
* @return The next number on that line in the buffer, returned as an int. Returns
* DEVICEINFO_UNKNOWN = -1 in the event that no more numbers exist on the same line.
*/
private static int extractValue(byte[] buffer, int index) {
while (index < buffer.length && buffer[index] != '\n') {
if (Character.isDigit(buffer[index])) {
int start = index;
index++;
while (index < buffer.length && Character.isDigit(buffer[index])) {
index++;
}
String str = new String(buffer, 0, start, index - start);
return Integer.parseInt(str);
}
index++;
}
return DEVICEINFO_UNKNOWN;
}

获取设备内存信息

// 获取设备总内存
public static String getTotalMemory(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
am.getMemoryInfo(mi);
return Formatter.formatFileSize(context, mi.totalMem);// 将获取的内存大小规格化
} // 获取设备剩余内存
public static String getAvailableMemory(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
am.getMemoryInfo(mi);
return Formatter.formatFileSize(context, mi.availMem);// 将获取的内存大小规格化
} // 格式化文件大小,单位为MB
private static String formatFileSize(long sizeInBytes) {
return Formatter.formatFileSize(null, sizeInBytes);
}

获取主板品牌

public static String getBRAND() {
return Build.BRAND;
}

统一输出日志

// 统一日志输出方法
public static void logDeviceInfo(Context context) {
if (true) { // 仅在 Debug 模式打印日志,避免正式版泄露设备信息
Log.i(TAG, "===== 设备信息 =====");
Log.i(TAG, String.format("设备型号: %s", getDeviceModel()));
Log.i(TAG, String.format("Android 版本: %s (SDK %d)", getAndroidVersion(), getDeviceSDK()));
Log.i(TAG, String.format("安全补丁级别: %s", getSecurityPatchLevel()));
Log.i(TAG, String.format("Build 号: %s", getBuildID()));
Log.i(TAG, String.format("屏幕显示信息: %s", getDisplay()));
Log.i(TAG, "===== 产品信息 =====");
Log.i(TAG, String.format("硬件信息: %s", getHardware()));
Log.i(TAG, String.format("制造商: %s", getDeviceMANUFACTURER()));
Log.i(TAG, String.format("品牌: %s", getBRAND())); Log.i(TAG, "===== 内存信息 =====");
Log.i(TAG, String.format("总内存: %s", getTotalMemory(context)));
Log.i(TAG, String.format("可用内存: %s", getAvailableMemory(context)));
Log.i(TAG, "======CPU信息=======");
Log.i(TAG, String.format("CPU 名称: %s", getCpuName()));
Log.i(TAG, String.format("CPU 架构: %s", getCpuArchitecture()));
Log.i(TAG, String.format("CPU 核数: %s", getNumberOfCPUCores()));
Log.i(TAG, String.format("CPU 频率: %s", getCPUFreqMHzs()));
}
}

获取存储信息

// 获取设备存储 信息
// 获取StorageManager实例
private String GetStorageInfo(Map<String,String> m_Device_Map) throws IOException {
String Storege_info = "";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
StorageStatsManager storageStatsManager = (StorageStatsManager)getSystemService(STORAGE_STATS_SERVICE);
List<StorageVolume> volumeList = storageManager.getStorageVolumes(); Log.i(Tag,"获取的存储数量" + volumeList.size());
for (StorageVolume volume : volumeList) {
if (null != volume ) {
String label = volume.getDescription(this); //这个其实就是U盘的名称
String status = volume.getState(); //设备挂载的状态,如:mounted、unmounted
boolean isEmulated = volume.isEmulated(); //是否是内部存储设备
boolean isRemovable = volume.isRemovable(); //是否是可移除的外部存储设备
String mPath=""; //设备的路径
Log.i(Tag,"name:"+label);
Log.i(Tag,"status:"+status);
Log.i(Tag,"isEmulated:"+isEmulated);
Log.i(Tag,"isRemovable:"+isRemovable); File file;
try {
long totalSpace = 0;
long availSpace = 0;
file = volume.getDirectory();
mPath = file.getPath();
Log.i(Tag,"mPath:"+mPath);
// 判断存储路径是否指向系统盘
String path = volume.getDirectory().getAbsolutePath();
if (mPath.contains("/storage/emulated/0") ) {
// 读取系统所在占用空间
try {
totalSpace = storageStatsManager.getTotalBytes(StorageManager.UUID_DEFAULT);//总空间大小
availSpace = storageStatsManager.getFreeBytes(StorageManager.UUID_DEFAULT);//可用空间大小
long systemBytes = totalSpace - availSpace;//系统所占不可用空间大小
Log.i(Tag,"totalBytes:"+ formatFileSize(totalSpace));
Log.i(Tag,"isEmulated:"+ formatFileSize(availSpace));
Log.i(Tag,"systemBytes:"+ formatFileSize(systemBytes));
} catch (IOException e) {
e.printStackTrace();
}
}
else {
// 通过读取挂载文件夹的形式读取文件空间
totalSpace = file.getTotalSpace();
availSpace = file.getFreeSpace();
Log.i(Tag, "可用的block数目::" + SDCardUtils.formatFileSize(totalSpace) + ",剩余空间:" + SDCardUtils.formatFileSize(availSpace)); }
// 设备名称 对应的空间容量
m_Device_Map.put(label,"Storage:" + formatFileSize(totalSpace) );
}catch (Exception e) {
e.toString();
}
}
else
{
Log.i(Tag,"Not volume");
}
}
}
//想看外部存储时,替换uuid即可
return Storege_info;
} /**
* 格式化文件大小并转换为可视化单位(B, KB, MB, GB, TB)
*/
private String formatFileSize(long sizeInBytes) {
if (sizeInBytes <= 0) {
return "0 B";
}
// 定义单位 列表
final String[] units = new String[] {"B", "KB", "MB", "GB", "TB"}; // 计算单位的指数
int unitIndex = 0;
double size = sizeInBytes; // 根据大小调整单位
while (size >= 1000 && unitIndex < units.length - 1) {
size /= 1000;
unitIndex++;
}
// 保留两位小数
return String.format("%.2f %s", size, units[unitIndex]);
}

设备信息源码位置修改

build\make\core\sysprop.mk

  • 搜索到数据很多,根据当前使用的Rockchip 3568的芯片,找到 3568对应的文件夹下的 device/rockchip/rk356x/rk3568_t/rk3568_t.mk

  • 根据需求修改相应的参数

参考资料

android利用StorageStatsManager获取应用程序的存储信息

Android设备基础信息获取 源码修改方式 APK开发的更多相关文章

  1. Android反编译获取源码-android学习之旅(70)

    上一讲我们介绍了如何获取资源文件,这一节讲解如何获取源码,其实获取源码真的很简单 首先还是要有工具,Dex2jar,这个工具用于将apk解压之后的dex文件转化为jar文件还有jd-gui的这个工具能 ...

  2. Android -- 带你从源码角度领悟Dagger2入门到放弃(二)

    1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...

  3. Ubuntu 14.04 LTS 下 android 2.3.5 源码编译过程

    Ubuntu 14.04 LTS 下 android 2.3.5 源码编译过程   在新的Ubuntu 64位系统下去编译早期的安卓源码是会出现很多问题的,因为64位系统在安装完成后,很多32位的兼容 ...

  4. 实例源码--Android手机狗(防盗)源码

      下载源码   技术要点: 1. SharedPreferences数据保存 2. SIM卡状态监 听 3. 发短信.发邮 箱.获取通讯信息 4. 源码带详细的 中文注释 ...... 详细介绍: ...

  5. Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮

    前言 之前写过屏蔽系统导航栏功能的文章,具体可看Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP)/动态显示和隐藏NavigationBar 在某些特殊定制的版本中要求 ...

  6. Android6.0 源码修改之屏蔽系统短信功能和来电功能

    一.屏蔽系统短信功能 1.屏蔽所有短信 android 4.2 短信发送流程分析可参考这篇 戳这 源码位置 vendor\mediatek\proprietary\packages\apps\Mms\ ...

  7. Eclipse Class Decompiler影响class默认打开方式,重新设置Eclipse默认源码打开方式

    安装Eclipse Class Decompiler插件后,Eclipse中的默认源码打开方式被修改为Eclipse Class Decompiler 这不是我喜欢的,因为我希望,源码从网络中获取,当 ...

  8. Android6.0 源码修改之 Contacts应用

    一.Contacts应用的主界面和联系人详情界面增加顶部菜单添加退出按钮 通过Hierarchy View 工具可以发现 主界面对应的类为 PeopleActivity 联系人详情界面对应的类为 Qu ...

  9. el-upload源码修改跳坑

    之前给element-ui提了一个问题,结果没有鸟我,没办法,只能修改源码来满足需求了 (备注:element-ui2依然没有修改,为了迎合产品还是要改源码) 本文讨论的组件属性仅限于list-typ ...

  10. 【转】Ubuntu 14.04.3上配置并成功编译Android 6.0 r1源码

    http://www.linuxidc.com/Linux/2016-01/127292.htm 终于成功把Android 6.0 r1源码的源码编译.先上图,这是在Ubuntu中运行的Android ...

随机推荐

  1. e00格式分析

    Arc/Info Export (E00) Format Analysis Original Author: Unknown Last Update: 2000-02-24,  Daniel Mori ...

  2. nvm安装node.js无法使用

    前情 最近在使用某此第三方模块需要依赖不同的node版本,于是想通nvm来管理node版本 坑 网上下载nvm-window的安装包,一步步傻瓜式安装下去,发现nrm无法使用,设置环境变量也没有用,再 ...

  3. 【快慢指针】LeetCode 143. 重排链表

    题解 用快慢指针先找到中间结点,然后断开前后两条链,用头插法的思路逆转后面那条链,最后两条链依次从前往后遍历插入即可. 参考代码 /** * Definition for singly-linked ...

  4. openEuler欧拉配置Nacos集群

    ​一.安装Nacos systemctl stop firewalld ​systemctl disable firewalld mkdir -p /home/nacos tar xvf nacos- ...

  5. Tomcat 已集成 CROS Fitler ExpiresFilter 等一堆常用 Filter

    http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html 再也不需要三方包提供的 filter 了

  6. 性能测试 -- docker部署grafana

    一.前提 1.安装好了docker 2.docker内 和 jmeter脚本 全都已经部署好了influxdb,并且数据采集等都正常 二.docker 部署 grafana 的操作步骤 1.下载 do ...

  7. Linux 查看 && 修改端口范围限制

    1.显示当前临时端口的范围: sysctl net.ipv4.ip_local_port_range或 cat /proc/sys/net/ipv4/ip_local_port_range一般情形下: ...

  8. 关于Java的UUID

    UUID或者UNID或者UID,是一个统一唯一标识,可以用来标记文档.数据或其它需要唯一标识的东西.Java 5.0内置UUID的实现,见java.util.UUID. 下面代码是找到的2种实现方式, ...

  9. Python爬虫requests判断请求超时并重新post/get发送请求

    Python爬虫requests判断请求超时并重新post/get发送请求在使用Python爬虫中,你可以使用requests库来发送网络请求.为了判断请求超时并重新发送请求,你可以设置一个超时时间, ...

  10. 《HelloGitHub》第 105 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. github.com/521xueweihan/HelloG ...