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. 怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev

    本文引用怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev 在 vscode 设置项中配置 gopls 的 ui.navigation.importShortcut ...

  2. vtkCellLocator IntersectWithLine 返回不是最近的交点

    vtkCellLocator IntersectWithLine 有一个重载函数(下面),返回不是最近的交点,因为到交点的距离没有比较,就直接覆盖了.不知道原本是否就是这样.可以用其他重载代替. in ...

  3. 【Android】谷歌应用关机闹钟 PowerOffAlarm 源码分析,并实现定时开、关机

    前言 RTC RTC 即实时时钟(Real-Time Clock),主要是功能有: 时间保持:RTC可以在断电的时候,仍然保持计时功能,保证时间的连续性 时间显示与设置:RTC可以向系统提供年.月.日 ...

  4. angr-ctf

    angr 的项目地址 https://github.com/jakespringer/angr_ctf angr实战 00 拖到IDA 就是输入正确的指令才能通关 这次试一下用angr来解题 goah ...

  5. mysql忘记密码的终极解决方案(docker-compose)

    MYSQL8的安全性能有所提高,装好后,各种不适应,需要各种调试. 1. 首先,root密码忘记或是更改,操作步骤: vi mysql/config/my.cnf 在[mysqld]的段中加上一句:s ...

  6. DSB的数字正交解调

    1.DSB调制过程 ​ DSB信号是一种双边带调幅调制信号,又叫双边带调幅,通过改变载波的振幅来实现基带数据的传输. 其函数表达式如下: \[s(t) = m(t)*cos(2\pi ft + \va ...

  7. 【Javaweb】【答卷】萌狼蓝天大二上学期期末Javaweb考试复习卷(一)

  8. [转]By not providing "FindEigen3.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find...

    在编译安装的时候出现如下问题,是Eigen3的Cmake依赖问题, 已经安装eigen3,但在项目的find_package(Eigen3 QUERIED)中,无法找到FindEigen3.Cmake ...

  9. Spring基础 02 | JdbcTemplate

    JdbcTemplate Spring对Jdbc的Api简单封装 开发步骤 1.导入Spring-jdbc.spring-tx坐标 2.创建数据库表和实例 3.创建jdbcTemplate对象 4.执 ...

  10. winform 引用AForge调用摄像头拍照

    Nuget安装这个2个: AForge.Controls; AForge.Video.DirectShow; code: namespace WindowsFormsApp1 { partial cl ...