Освой Android играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Информация о системе
Информация о процессорах
Информация о файловой системе
Информация о памяти
Информация об операционной системе Linux
Получить информацию о Build
ABI (API 21)
Список запущенных служб на устройстве
Список запущенных процессов на устройстве
Кто владеет информацией, тот владеет миром.
Иногда приходят письма с просьбой рассказать, как получить информацию об устройстве - версия Java, количество процессоров и т.д. Самое смешное, но я написал такой проект в Eclipse ещё в 2011 году на основе какого-то примера из интернета. Но проект так и валялся в папке. Чтобы его окончательно не потерять, я решил выложить его здесь. На самом деле, данная информация мне ни разу не пригодилась. Но вдруг вам надо.
Во многих случаях информация - это большой набор строк. В большинстве случаев подойдёт разметка с использованием ScrollView, в котором содержится TextView. В текстовую метку будем выводить окончательный вариант после сбора информации.
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainAcitivity">
<TextView
android:id="@+id/textViewInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
Класс System с помощью метода getProperty() позволяет узнать различные свойства системы.
Для начала покажу упрощённый код, представив себе, что мы знаем, чего хотим.
package ru.alexanderklimov.info;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView infoTextView = findViewById(R.id.textViewInfo);
infoTextView.setText(getSystemInfo());
}
private String getSystemInfo() {
StringBuffer buffer = new StringBuffer();
getProperty("os.name", "os.name", buffer);
getProperty("os.version", "os.version", buffer);
getProperty("os.arch", "os.arch", buffer);
getProperty("java.vendor.url", "java.vendor.url", buffer);
getProperty("java.version", "java.version", buffer);
getProperty("java.class.path", "java.class.path", buffer);
getProperty("java.class.version", "java.class.version", buffer);
getProperty("java.vendor", "java.vendor", buffer);
getProperty("java.home", "java.home", buffer);
getProperty("user.name", "user.name", buffer);
getProperty("user.home", "user.home", buffer);
getProperty("user.dir", "user.dir", buffer);
return buffer.toString();
}
private void getProperty(String key, String property, StringBuffer buffer) {
buffer.append(key);
buffer.append(" : ");
buffer.append(System.getProperty(property));
buffer.append("\n");
}
}
Существуют предопределённые свойства в виде строк, которые являются ключами. С их помощью можно получить значение.

Выведем все свойства, чего мелочиться. В этот раз мы не указываем конкретные названия свойств, а предоставляем эту работу системе.
package ru.alexanderklimov.info;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import java.util.Enumeration;
import java.util.Properties;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView infoTextView = findViewById(R.id.textViewInfo);
Properties properties = System.getProperties();
infoTextView.append(properties.toString());
infoTextView.append("\n----------\\n\\n");
Enumeration<String> propertyNames =
(Enumeration<String>) properties.propertyNames();
while(propertyNames.hasMoreElements()){
String nextElement = propertyNames.nextElement();
infoTextView.append(nextElement + " : \\n" +
System.getProperty(nextElement) + "\\n\\n");
}
}
}
Обратите внимание, что в устройстве находится кот!

В статье Команды Linux я показывал, как можно получить информацию от системы. Есть отдельные команды, позволяющие узнать информацию о процессорах.
При работе с командами Linux примеры желательно проверять на эмуляторе или рутованных устройствах. Не уверен, что это будет работать на обычных устройствах.
private String getCpuInfo() {
ProcessBuilder processBuilder;
String result = "";
try {
String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
processBuilder = new ProcessBuilder(args);
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
byte[] bytes = new byte[1024];
while (inputStream.read(bytes) != -1) {
result = result + new String(bytes);
}
inputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
// Выводим результат в TextView
infoTextView.setText(getCpuInfo());

Вернуть количество процессорных ядер можно одной строчкой кода. На всякий случай перечитайте документацию.
int availableCores = Runtime.getRuntime().availableProcessors();
infoTextView.setText("Количество ядер процессора: " + availableCores);
Сколько места на дисках, сколько занято, сколько свободно.
private String getFileSystemInfo()
{
ProcessBuilder cmd;
String result="";
try{
String[] args = {"/system/bin/df"};
cmd = new ProcessBuilder(args);
Process process = cmd.start();
InputStream inputStream = process.getInputStream();
byte[] bytes = new byte[1024];
while(inputStream.read(bytes) != -1){
result = result + new String(bytes);
}
inputStream.close();
} catch(IOException ex){
ex.printStackTrace();
}
return result;
}
// вызываем метод
infoTextView.setText(getFileSystemInfo());

Позже обнаружилось, что в Android есть класс StatFs, получающий информацию о месте в файловой системе, который соответствует Unix-команде statvfs(). В API 18 часть методов класса была объявлена устаревшей и заменена на другие.
private String getStatFsInfo() {
StatFs statFs = new StatFs(Environment.getRootDirectory().getAbsolutePath());
StringBuilder builder = new StringBuilder();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
//The size, in bytes, of a block on the file system.
long blockSize = statFs.getBlockSizeLong();
builder.append("BlockSize: \t" + blockSize + "\n");
//The total number of blocks on the file system.
long blockCount = statFs.getBlockCountLong();
builder.append("BlockCount: \t" + blockCount + "\n");
//The total number of bytes supported by the file system.
long totalBytes = statFs.getTotalBytes();
builder.append("TotalBytes: \t" + totalBytes + "\n");
//# of blocks that are free on the file system and available to applications.
long availableBlocks = statFs.getAvailableBlocksLong();
builder.append("AvailableBlocks: \t" + availableBlocks + "\n");
//# of bytes that are free on the file system and available to applications.
long availableBytes = statFs.getAvailableBytes();
builder.append("AvailableBytes: \t" + availableBytes + "\n");
//The total # of blocks that are free on the file system, including reserved blocks
//(that are not available to normal applications).
long freeBlocks = statFs.getFreeBlocksLong();
builder.append("FreeBlocks: \t" + freeBlocks + "\n");
//The total # of bytes that are free on the file system, including reserved blocks
//(that are not available to normal applications).
long freeBytes = statFs.getFreeBytes();
builder.append("FreeBytes: \t" + freeBytes + "\n");
} else {
builder.append("SDK < JELLY_BEAN_MR2 (API Level 18)");
}
return builder.toString();
}
infoTextView.setText(getStatFsInfo());
С помощью ActivityManager можно узнать доступную память, хотя документация не советует полагаться на него. Другую информацию о памяти можно узнать с помощью команды Linux /proc/meminfo:
private String getMemoryInfo() {
ProcessBuilder processBuilder;
StringBuilder builder = new StringBuilder();
ActivityManager activityManager = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
builder.append("Доступная память: ");
builder.append(memoryInfo.availMem);
builder.append("\n\n");
String result = builder.toString();
try {
String[] args = {"/system/bin/cat", "/proc/meminfo"};
processBuilder = new ProcessBuilder(args);
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
byte[] bytes = new byte[1024];
while (inputStream.read(bytes) != -1) {
result = result + new String(bytes);
}
inputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
infoTextView.setText(getMemoryInfo());
Для Kotlin:
var memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)

Информация об операционной системе также доступна через команду Linux:
private String getOsVersionInfo() {
ProcessBuilder processBuilder;
String result = "";
try {
String[] args = { "/system/bin/cat", "/proc/version" };
processBuilder = new ProcessBuilder(args);
Process process = processBuilder.start();
InputStream inputStream = process.getInputStream();
byte[] bytes = new byte[1024];
while (inputStream.read(bytes) != -1) {
result = result + new String(bytes);
}
inputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
return result;
}
infoTextView.setText(getOsVersionInfo());

В Android есть класс Build и Build.VERSION, позволяющие узнать различную информацию о системе:
// Kotlin
textView.text = "Build.VERSION"
textView.append("\nManufacturer: \${Build.MANUFACTURER}")
textView.append("\nModel: ${Build.MODEL}")
// base OS build the product is based on
textView.append("\n\nBase OS: \${Build.VERSION.BASE_OS}")
// current development codename, or the string "REL"
// if this is a release build
textView.append("\nCodeName: ${Build.VERSION.CODENAME}")
// internal value used by the underlying source
// control to represent this build
textView.append("\nIncremental: ${Build.VERSION.INCREMENTAL}")
// developer preview revision of a pre-release sdk
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
textView.append("\nPreview SDK Int: ${Build.VERSION.PREVIEW_SDK_INT}")
}
// user-visible version string.
textView.append("\nRelease: ${Build.VERSION.RELEASE}")
// version string show to the user; may be RELEASE or
// CODENAME if not a final release build
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
textView.append("\nRelease Or CodeName: " +
Build.VERSION.RELEASE_OR_CODENAME
)
}
// user-visible security patch level
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
textView.append("\nSecurity Patch: ${Build.VERSION.SECURITY_PATCH}")
}
// sdk version of the software currently running on this hardware device
textView.append("\nSDK Int (API Level): ${Build.VERSION.SDK_INT}")
// Java
// Пример не во всём совпадает с примером на Kotlin
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView infoTextView = findViewById(R.id.textView);
StringBuffer version = new StringBuffer();
version.append("CODENAME: " + Build.VERSION.CODENAME);
version.append("\nRELEASE: " + Build.VERSION.RELEASE);
version.append("\nINCREMENTAL: " + Build.VERSION.INCREMENTAL);
version.append("\nSDK (уст.): " + Build.VERSION.SDK);
version.append("\nSDK_INT: " + Build.VERSION.SDK_INT);
version.append("\nBOARD: " + Build.BOARD);
version.append("\nBRAND: " + Build.BRAND);
version.append("\nDEVICE: " + Build.DEVICE);
version.append("\nFINGERPRINT: " + Build.FINGERPRINT);
version.append("\nHOST: " + Build.HOST);
version.append("\nID: " + Build.ID);
infoTextView.setText(version.toString());
}

В Android 5.0 (API 21) добавлены несколько новых свойств для определения типа процессора ABI (Application Binary Interface). Существуют три основные категории процессоров.
На текущий момент самый популярный тип процессора - armeabi-v7a
Проверим. Используемые свойства возвращают массив строк.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView supportedABIsTextView = findViewById(R.id.textview);
supportedABIsTextView.setText("Build.SUPPORTED_ABIS:\\n");
String[] SUPPORTED_ABIS = Build.SUPPORTED_ABIS;
for(String abi : SUPPORTED_ABIS){
supportedABIsTextView.append(abi + "\n");
}
supportedABIsTextView.append("\n");
supportedABIsTextView.append("Build.SUPPORTED_32_BIT_ABIS:\n");
String[] SUPPORTED_32_BIT_ABIS = Build.SUPPORTED_32_BIT_ABIS;
for(String abi32 : SUPPORTED_32_BIT_ABIS){
supportedABIsTextView.append(abi32 + "\n");
}
supportedABIsTextView.append("\n");
supportedABIsTextView.append("Build.SUPPORTED_64_BIT_ABIS:\\n");
String[] SUPPORTED_64_BIT_ABIS = Build.SUPPORTED_64_BIT_ABIS;
for(String abi64 : SUPPORTED_64_BIT_ABIS){
supportedABIsTextView.append(abi64 + "\n");
}
supportedABIsTextView.append("\n");
}
На моём устройстве выводится (у вас скорее всего тоже):
Build.SUPPORTED_ABIS:
armeabi-v7a
armeabi
Build.SUPPORTED_32_BIT_ABIS:
armeabi-v7a
armeabi
Build.SUPPORTED_64_BIT_ABIS:
На эмуляторах может выводиться x86. Процессоры MIPS практически не встречаются.
В документации говорится, что эту информацию нужно использовать только при отладке. Добавим TextView:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
// Максимальное число служб. Может быть и меньше
int maxNumber = 100;
List<ActivityManager.RunningServiceInfo> runningServices = activityManager.getRunningServices(maxNumber);
StringBuilder resultStringBuilder = new StringBuilder();
resultStringBuilder.append("Запущено служб: ").append(runningServices.size()).append("\n\n");
for (int i = 0; i < runningServices.size(); i++) {
resultStringBuilder.append(runningServices.get(i).service).append("\n\n");
}
TextView infoTexView = findViewById(R.id.textViewInfo);
infoTexView.setMovementMethod(new ScrollingMovementMethod());
infoTexView.setText(resultStringBuilder);
}
По такому же принципу можно получить список запущенных процессов. В документации говорится, что эту информацию нужно использовать только при отладке. Нам опять понадобится ActivityManager, который предоставит нужную информацию.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
StringBuilder resultStringBuilder = new StringBuilder();
resultStringBuilder.append("Запущено процессов: ").append(runningAppProcesses.size()).append("\\n\\n");
for (int i = 0; i < runningAppProcesses.size(); i++) {
resultStringBuilder.append(runningAppProcesses.get(i).processName).append("\n\n");
}
TextView infoTexView = findViewById(R.id.textViewInfo);
infoTexView.setMovementMethod(new ScrollingMovementMethod());
infoTexView.setText(resultStringBuilder);
}
Open-source Kotlin библиотека для Android Device Info Library позволяет получить информацию о характеристиках устройства.
val sdk = DeviceInfoSDK.getInstance()
// Collect all information at once
val deviceReport = sdk.collectAllInfo()
// Access specific information types
val hardwareInfo = deviceReport.getHardwareInfo()
val systemInfo = deviceReport.getSystemInfo()
val networkInfo = deviceReport.getNetworkInfo()