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. .NET 中的中间件(Middleware)

    ASP.NET Core 中间件 什么是中间件(Middleware)? 中间件是组装到应用程序管道中以处理请求和响应的软件. 每个组件: 选择是否将请求传递给管道中的下一个组件. 可以在调用管道中的 ...

  2. [AGC029D] Grid game题解

    这题很显然可以用贪心来解. 由于先手不动一定会让局数更少,所以先手要能动就动. 而后手一定是希望他的石子可以撞到一个障碍物上,这样先手就无法移动了,后手就可以让局数更少. 因为先手一定会能动就动,所以 ...

  3. Advanced .NET Remoting: 第 9 章 3.在 Remoting 中传递额外的运行时信息

    Advanced .NET Remoting:第 9 章 3.传递运行时信息 前面使用的接收器 ( Sink ) 是 IClientChannelSinks 与 IServerChannelSinks ...

  4. Getting Started with JavaFX

    https://openjfx.io/openjfx-docs/#maven Run HelloWorld using Maven If you want to develop JavaFX appl ...

  5. Qt编写的modbus模拟器/支持网络和串口以及websocket/支持网络rtu

    一.使用说明 1.1 设备模拟-Com 第一步,填写要模拟的设备地址,0表示自动处理,也就是收到什么地址就应答什么地址. 第二步,填写对应的串口号和波特率. 第三步,单击打开串口,成功后会变成关闭串口 ...

  6. Qt编写地图综合应用59-经纬度坐标纠偏

    一.前言 地图应用中都涉及到一个问题就是坐标纠偏的问题,这个问题的是因为根据地方规则保密性要求不允许地图厂商使用标准的GPS坐标,而是要用国家定义的偏移标准,或者在此基础上再做算法运算,所以这就出现了 ...

  7. Qt音视频开发2-vlc回调处理

    一.前言 用句柄来显示视频,方便是很方便,但是有个缺点就是不能拿到实时视频的每张图片的数据,这个就比较讨厌,大部分的监控行业的应用,除了截图以外,很可能需要拿到图片自己做一些处理的,而且拿到图片自己绘 ...

  8. Swagger UI、RESTful简介

    Swagger UI 简介 Swagger UI允许任何人(无论您是开发团队还是最终用户)都可以可视化API资源并与之交互,而无需任何实现逻辑.它是根据您的OpenAPI(以前称为Swagger)规范 ...

  9. KES(KingBaseES)集群部署实战

    今天我们将探讨关于KES(KingBaseES)的集群部署方案.作为示例,我们将以读写分离(RWC)集群为例,快速在本地进行部署和安装,并深入了解KES的部署流程.在本章中,我们将采用Windows平 ...

  10. 《入梦》Revisited

      寝室里有本<美丽新世界>(Brave New World),书页翻过灯塔里上升的螺旋阶梯,还有大概三分之一的篇幅是<重返美丽新世界>(Brave New World Rev ...