Освой 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");
    }
}

Существуют предопределённые свойства в виде строк, которые являются ключами. С их помощью можно получить значение.

Information

Выведем все свойства, чего мелочиться. В этот раз мы не указываем конкретные названия свойств, а предоставляем эту работу системе.


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");
        }
    }
}

Обратите внимание, что в устройстве находится кот!

Information

Информация о процессорах

В статье Команды 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());

Information

Вернуть количество процессорных ядер можно одной строчкой кода. На всякий случай перечитайте документацию.


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());

Information

Позже обнаружилось, что в 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)

Memory

Информация об операционной системе Linux

Информация об операционной системе также доступна через команду 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());

Memory

Получить информацию о Build

В 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()); }

Build

ABI

В Android 5.0 (API 21) добавлены несколько новых свойств для определения типа процессора ABI (Application Binary Interface). Существуют три основные категории процессоров.

  • ARM: armeabi, armeabi-v7a (обычно поддерживает и armeabi), arm64-v8a (обычно поддерживает armeabi и armeabi-v7a)
  • X86: x86, x86_64 (обычно поддерживает и x86)
  • MIPS: mips, mips64 (обычно поддерживает и mips)

На текущий момент самый популярный тип процессора - 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);
}

Библиотека Device Info Library

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()
Реклама