Android отримує безкоштовний розмір внутрішньої / зовнішньої пам'яті


98

Я хочу отримати розмір вільної пам'яті на внутрішньому / зовнішньому зберіганні свого пристрою програмно. Я використовую цей фрагмент коду:

StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
long bytesAvailable = (long)stat.getBlockSize() *(long)stat.getBlockCount();
long megAvailable = bytesAvailable / 1048576;
Log.e("","Available MB : "+megAvailable);

File path = Environment.getDataDirectory();
StatFs stat2 = new StatFs(path.getPath());
long blockSize = stat2.getBlockSize();
long availableBlocks = stat2.getAvailableBlocks();
String format =  Formatter.formatFileSize(this, availableBlocks * blockSize);
Log.e("","Format : "+format);

і результат, який я отримую:

11-15 10:27:18.844: E/(25822): Available MB : 7572
11-15 10:27:18.844: E/(25822): Format : 869MB

Проблема полягає в тому, що я хочу отримати вільну пам’ять про SdCard, який зараз є 1,96GB. Як я можу виправити цей код, щоб отримати безкоштовний розмір?


Станом на рівень 18 API вони перейменували метод на закінчення Long. Ймовірно, вам потрібно буде додати перевірку рівня API до нього
Jayshil Dave

Всі рішення я намагався нікого не працювати, коли я формату як внутрішній сховище ... чи можете ви мені порадувати, як це досягти?
Yogesh Rathi

Відповіді:


182

Нижче наведено код для вашої мети:

public static boolean externalMemoryAvailable() {
        return android.os.Environment.getExternalStorageState().equals(
                android.os.Environment.MEDIA_MOUNTED);
    }

    public static String getAvailableInternalMemorySize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long availableBlocks = stat.getAvailableBlocksLong();
        return formatSize(availableBlocks * blockSize);
    }

    public static String getTotalInternalMemorySize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long totalBlocks = stat.getBlockCountLong();
        return formatSize(totalBlocks * blockSize);
    }

    public static String getAvailableExternalMemorySize() {
        if (externalMemoryAvailable()) {
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSizeLong();
            long availableBlocks = stat.getAvailableBlocksLong();
            return formatSize(availableBlocks * blockSize);
        } else {
            return ERROR;
        }
    }

    public static String getTotalExternalMemorySize() {
        if (externalMemoryAvailable()) {
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSizeLong();
            long totalBlocks = stat.getBlockCountLong();
            return formatSize(totalBlocks * blockSize);
        } else {
            return ERROR;
        }
    }

    public static String formatSize(long size) {
        String suffix = null;

        if (size >= 1024) {
            suffix = "KB";
            size /= 1024;
            if (size >= 1024) {
                suffix = "MB";
                size /= 1024;
            }
        }

        StringBuilder resultBuffer = new StringBuilder(Long.toString(size));

        int commaOffset = resultBuffer.length() - 3;
        while (commaOffset > 0) {
            resultBuffer.insert(commaOffset, ',');
            commaOffset -= 3;
        }

        if (suffix != null) resultBuffer.append(suffix);
        return resultBuffer.toString();
    }

Отримати розмір оперативної пам’яті

ActivityManager actManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo memInfo = new ActivityManager.MemoryInfo();
actManager.getMemoryInfo(memInfo);
long totalMemory = memInfo.totalMem;

2
getBlockSize()і getBlockCountзастаріли.
Nima G

2
@DineshPrajapati Спасибі за відповідь, у мене є запит, якщо я використовую Environment.getRootDirectory () замість Environment.getDataDirectory для обчислення внутрішнього сховища, я отримую деякий вихід. Це стосується внутрішньої пам'яті іншої пам’яті ..
А. К. Джоші

3
@DineshPrajapati .. Тестовано на MOTO G2 Отримання помилкових даних для зовнішнього зберігання
AK Joshi

1
Використовуйте Довгий зрештою для нових рівнів API (> 18)
Gun2sh

1
Дуже дякую вам за обмін знаннями
Кішань Соні

40

Ось як я це зробив:

StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
long bytesAvailable;
if (android.os.Build.VERSION.SDK_INT >= 
    android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
    bytesAvailable = stat.getBlockSizeLong() * stat.getAvailableBlocksLong();
}
else {
    bytesAvailable = (long)stat.getBlockSize() * (long)stat.getAvailableBlocks();
}
long megAvailable = bytesAvailable / (1024 * 1024);
Log.e("","Available MB : "+megAvailable);

2
але це знецінено :(
abbasalim

@ ArMo372, Ви хлопці дізналися код заміни для цього?
SimpleCoder

3
Просто замініть getBlockSizeі getAvailableBlocksна getBlockSizeLongі getAvailableBlocksLong.
smg

1
це не отримати потрібний простір. Це отримує 1141 замість 1678 @smg

1
Рішення не працює , коли я роблю формат як внутрішня пам'ять ... Ви можете порадувати мене, як це зробити досягти цього
Йогеш Rathi

27

З API 9 ви можете:

long freeBytesInternal = new File(ctx.getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
long freeBytesExternal = new File(getExternalFilesDir(null).toString()).getFreeSpace();

2
File.getUsableSpace (), мабуть, краще, тому що ви, ймовірно, не працюєте як root.
Марк

У File.getUsableSpace()виглядає як простий метод використовувати , а не використовувати StatFs. Чому я використовую StatFs@MarkCarter?
StuStirling

1
@ DiscoS2 Ви б використовувати StatFs якщо ваш minSdkVersion менше 9.
Mark

1
Як би ви також контролювали зміни пам’яті?
андроїд розробник

24

Щоб отримати всі доступні папки пам’яті (включаючи карти SD), спочатку отримуєте файли пам’яті:

File internalStorageFile=getFilesDir();
File[] externalStorageFiles=ContextCompat.getExternalFilesDirs(this,null);

Тоді ви можете отримати доступний розмір кожного з них.

Існує 3 способи зробити це:

API 8 і нижче:

StatFs stat=new StatFs(file.getPath());
long availableSizeInBytes=stat.getBlockSize()*stat.getAvailableBlocks();

API 9 і вище:

long availableSizeInBytes=file.getFreeSpace();

API 18 і вище (не потрібен, якщо попередній варіант у порядку):

long availableSizeInBytes=new StatFs(file.getPath()).getAvailableBytes(); 

Щоб отримати хороший відформатований рядок того, що ви отримали зараз, ви можете використовувати:

String formattedResult=android.text.format.Formatter.formatShortFileSize(this,availableSizeInBytes);

або ви можете використовувати це у випадку, якщо ви хочете побачити точне число байтів, але добре:

NumberFormat.getInstance().format(availableSizeInBytes);

Зверніть увагу, що я думаю, що внутрішня пам’ять може бути такою ж, як і перша зовнішня пам’ять, оскільки перша є емульованою.


EDIT: Використовуючи StorageVolume на Android Q і вище, я думаю, що можливо отримати вільний простір кожного, використовуючи щось на кшталт:

    val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageVolumes = storageManager.storageVolumes
    AsyncTask.execute {
        for (storageVolume in storageVolumes) {
            val uuid: UUID = storageVolume.uuid?.let { UUID.fromString(it) } ?: StorageManager.UUID_DEFAULT
            val allocatableBytes = storageManager.getAllocatableBytes(uuid)
            Log.d("AppLog", "allocatableBytes:${android.text.format.Formatter.formatShortFileSize(this,allocatableBytes)}")
        }
    }

Я не впевнений, чи правильно це, і я не можу знайти загальний розмір кожного, тому я написав про це тут і запитав про це тут .


1
Як отримати вільний простір на знімній SD-карті (або флеш-пам'яті USB OTG) на пристроях з API 23? нові StatFs (file.getPath ()). getAvailableBytes () або file.getUsableSpace () дає 972546048 байт незалежно від реального розміру пам’яті на Nexus 5 (Marshmallow 6.0.1).
isbsent

@isabsent Nexus 5 не має слота для SD-карти. Як ви це перевірили?
андроїд розробник

Я перевірив це за допомогою флешки USB OTG.
isbsent

@isabsent Я його ніколи не використовував. Вибачте. Чи добре це працює на API 22 і нижче?
андроїд розробник

1
@Smeet Чи можна спробувати його на Android 6 або вище? Якщо так, можливо, це така проблема: code.google.com/p/android/isissue/detail?id=200326
розробник для android


7

Спробуйте цей простий фрагмент

    public static String readableFileSize() {
    long availableSpace = -1L;
    StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2)
        availableSpace = (long) stat.getBlockSizeLong() * (long) stat.getAvailableBlocksLong();
    else
        availableSpace = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize();

    if(availableSpace <= 0) return "0";
    final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
    int digitGroups = (int) (Math.log10(availableSpace)/Math.log10(1024));
    return new DecimalFormat("#,##0.#").format(availableSpace/Math.pow(1024, digitGroups)) + " " + units[digitGroups];
}

Дякую, але у мене є java.lang.ArrayIndexOutOfBoundsException: length=5; index=-2147483648помилка, здається, що digitGroupsрезультат -2147483648.
Акуна

Рішення не працює , коли я роблю формат як внутрішня пам'ять ... Ви можете порадувати мене, як це зробити досягти цього
Йогеш Rathi

6

Зробити доступне сховище дуже просто, якщо ви отримуєте внутрішній та зовнішній шлях зберігання. Також зовнішній шлях зберігання телефону дійсно дуже легко знайти, використовуючи

Environment.getExternalStorageDirectory (). GetPath ();

Тому я просто зосереджуюсь на тому, як знайти шляхи зовнішнього знімного сховища, наприклад, знімної SDCard, USB OTG (не перевірена USB OTG, оскільки у мене немає USB OTG).

Нижче наведено список усіх можливих зовнішніх шляхів зберігання даних.

 /**
     * This method returns the list of removable storage and sdcard paths.
     * I have no USB OTG so can not test it. Is anybody can test it, please let me know
     * if working or not. Assume 0th index will be removable sdcard path if size is
     * greater than 0.
     * @return the list of removable storage paths.
     */
    public static HashSet<String> getExternalPaths()
    {
    final HashSet<String> out = new HashSet<String>();
    String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
    String s = "";
    try
    {
        final Process process = new ProcessBuilder().command("mount").redirectErrorStream(true).start();
        process.waitFor();
        final InputStream is = process.getInputStream();
        final byte[] buffer = new byte[1024];
        while (is.read(buffer) != -1)
        {
            s = s + new String(buffer);
        }
        is.close();
    }
    catch (final Exception e)
    {
        e.printStackTrace();
    }

    // parse output
    final String[] lines = s.split("\n");
    for (String line : lines)
    {
        if (!line.toLowerCase(Locale.US).contains("asec"))
        {
            if (line.matches(reg))
            {
                String[] parts = line.split(" ");
                for (String part : parts)
                {
                    if (part.startsWith("/"))
                    {
                        if (!part.toLowerCase(Locale.US).contains("vold"))
                        {
                            out.add(part.replace("/media_rw","").replace("mnt", "storage"));
                        }
                    }
                }
            }
        }
    }
    //Phone's external storage path (Not removal SDCard path)
    String phoneExternalPath = Environment.getExternalStorageDirectory().getPath();

    //Remove it if already exist to filter all the paths of external removable storage devices
    //like removable sdcard, USB OTG etc..
    //When I tested it in ICE Tab(4.4.2), Swipe Tab(4.0.1) with removable sdcard, this method includes
    //phone's external storage path, but when i test it in Moto X Play (6.0) with removable sdcard,
    //this method does not include phone's external storage path. So I am going to remvoe the phone's
    //external storage path to make behavior consistent in all the phone. Ans we already know and it easy
    // to find out the phone's external storage path.
    out.remove(phoneExternalPath);

    return out;
}

Як я пам’ятаю, використання константних імен для обробки контурів може не працювати на деяких пристроях, оскільки деякі можуть мати власні шляхи. Я сподіваюся, що це не так. +1 за зусилля.
андроїд розробник

1
@androiddeveloper Дякую, дорогі за голосування. Мені потрібна підтримка всіх, щоб перевірити цей код на вашому пристрої, оскільки я не маю всіх пристроїв, але перевірений на 4-х різних пристроях і працює добре. Прокоментуйте, будь ласка, тут не працює на мобільному телефоні будь-якого органу.
Сміт

Рішення не працює , коли я роблю формат як внутрішня пам'ять ... Ви можете порадувати мене, як це зробити досягти цього
Йогеш Rathi

4

Швидке доповнення до теми зовнішньої пам'яті

Не плутайте назву методу externalMemoryAvailable()у відповіді Дінеша Праджапаті.

Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())дає поточний стан пам'яті, якщо носій присутній і встановлений у точці монтажу з доступом до читання / запису. Ви отримаєте trueнавіть на пристроях без SD-карт, як, наприклад, Nexus 5. Але все-таки це "обов'язковий" метод перед будь-якими операціями зі зберіганням.

Щоб перевірити, чи є на вашому пристрої SD-карта, ви можете скористатися методом ContextCompat.getExternalFilesDirs()

На ньому не відображаються перехідні пристрої, такі як флешки USB.

Також пам’ятайте, що ContextCompat.getExternalFilesDirs()на Android 4.3 і новіших версій завжди повертатиметься лише 1 запис (SD-карта, якщо вона доступна, інакше Внутрішня). Більше про це можна прочитати тут .

  public static boolean isSdCardOnDevice(Context context) {
    File[] storages = ContextCompat.getExternalFilesDirs(context, null);
    if (storages.length > 1 && storages[0] != null && storages[1] != null)
        return true;
    else
        return false;
}

в моєму випадку цього було досить, але не забувайте, що на деяких пристроях Android можуть бути 2 SD-карти, тож якщо вам потрібні всі - відрегулюйте код вище.


2
@RequiresApi(api = Build.VERSION_CODES.O)
private void showStorageVolumes() {
    StorageStatsManager storageStatsManager = (StorageStatsManager) getSystemService(Context.STORAGE_STATS_SERVICE);
    StorageManager storageManager = (StorageManager) getSystemService(Context.STORAGE_SERVICE);
    if (storageManager == null || storageStatsManager == null) {
        return;
    }
    List<StorageVolume> storageVolumes = storageManager.getStorageVolumes();
    for (StorageVolume storageVolume : storageVolumes) {
        final String uuidStr = storageVolume.getUuid();
        final UUID uuid = uuidStr == null ? StorageManager.UUID_DEFAULT : UUID.fromString(uuidStr);
        try {
            Log.d("AppLog", "storage:" + uuid + " : " + storageVolume.getDescription(this) + " : " + storageVolume.getState());
            Log.d("AppLog", "getFreeBytes:" + Formatter.formatShortFileSize(this, storageStatsManager.getFreeBytes(uuid)));
            Log.d("AppLog", "getTotalBytes:" + Formatter.formatShortFileSize(this, storageStatsManager.getTotalBytes(uuid)));
        } catch (Exception e) {
            // IGNORED
        }
    }
}

Клас StorageStatsManager представив Android O і вище, який може дати вам безкоштовний і загальний байт у зовнішньому / внутрішньому сховищі. Детальніше з вихідним кодом ви можете прочитати мою наступну статтю. ви можете використовувати відображення для нижчих, ніж Android O

https://medium.com/cashify-engineering/how-to-get-storage-stats-in-android-o-api-26-4b92eca6805b


2

Це те, як я це зробив ..

внутрішня загальна пам'ять

double totalSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getTotalSpace();
double totMb = totalSize / (1024 * 1024);

Внутрішній вільний розмір

 double availableSize = new File(getApplicationContext().getFilesDir().getAbsoluteFile().toString()).getFreeSpace();
    double freeMb = availableSize/ (1024 * 1024);

Зовнішня вільна і загальна пам'ять

 long freeBytesExternal =  new File(getExternalFilesDir(null).toString()).getFreeSpace();
       int free = (int) (freeBytesExternal/ (1024 * 1024));
        long totalSize =  new File(getExternalFilesDir(null).toString()).getTotalSpace();
        int total= (int) (totalSize/ (1024 * 1024));
       String availableMb = free+"Mb out of "+total+"MB";

0

Щодо зовнішнього меню, є ще один спосіб:
File external = Environment.getExternalStorageDirectory(); free:external.getFreeSpace(); total:external.getTotalSpace();


0

Після перевірки іншого рішення пишіть код сам це повний код для пошуку

  • Загальна зовнішня пам'ять
  • Безкоштовна зовнішня пам'ять
  • Використовувана зовнішня пам'ять
  • Внутрішня пам'ять TotaL
  • Використовувана внутрішня пам'ять
  • Безкоштовна внутрішня пам'ять

'' ''

object DeviceMemoryUtil {
private const val error: String = "Something went wrog"
private const val noExternalMemoryDetected = "No external Storage detected"
private var totalExternalMemory: Long = 0
private var freeExternalMemory: Long = 0
private var totalInternalStorage: Long = 0
private var freeInternalStorage: Long = 0

/**
 * Checks weather external memory is available or not
 */
private fun externalMemoryAvailable(): Boolean {
    return Environment.getExternalStorageState() ==
            Environment.MEDIA_MOUNTED
}

/**
 *Gives total external memory
 * @return String Size of external memory
 * @return Boolean True if memory size is returned
 */
fun getTotalExternalMemorySize(): Pair<String?, Boolean> {
    val dirs: Array<File> = ContextCompat.getExternalFilesDirs(CanonApplication.getCanonAppInstance(), null)
    return if (externalMemoryAvailable()) {
        if (dirs.size > 1) {
            val stat = StatFs(dirs[1].path)
            val blockSize = stat.blockSizeLong
            val totalBlocks = stat.blockCountLong
            var totalExternalSize = totalBlocks * blockSize
            totalExternalMemory = totalExternalSize
            Pair(formatSize(totalExternalSize), true)
        } else {
            Pair(error, false)
        }
    } else {
        Pair(noExternalMemoryDetected, false)
    }
}

/**
 * Gives free external memory size
 * @return String Size of free external memory
 * @return Boolean True if memory size is returned
 */
fun getAvailableExternalMemorySize(): Pair<String?, Boolean> {
    val dirs: Array<File> = ContextCompat.getExternalFilesDirs(CanonApplication.getCanonAppInstance(), null)
    if (externalMemoryAvailable()) {
        return if (dirs.size > 1) {
            val stat = StatFs(dirs[1].path)
            val blockSize = stat.blockSizeLong
            val availableBlocks = stat.availableBlocksLong
            var freeExternalSize = blockSize * availableBlocks
            freeExternalMemory = freeExternalSize
            Pair(formatSize(freeExternalSize), true)
        } else {
            Pair(error, false)
        }
    } else {
        return Pair(noExternalMemoryDetected, false)
    }
}

/**
 * Gives used external memory size
 *  @return String Size of used external memory
 * @return Boolean True if memory size is returned
 */
fun getUsedExternalMemorySize(): Pair<String?, Boolean> {
    return if (externalMemoryAvailable()) {
        val totalExternalSize = getTotalExternalMemorySize()
        val freeExternalSize = getAvailableExternalMemorySize()
        if (totalExternalSize.second && freeExternalSize.second) {
            var usedExternalVolume = totalExternalMemory - freeExternalMemory
            Pair(formatSize(usedExternalVolume), true)
        } else {
            Pair(error, false)
        }
    } else {
        Pair(noExternalMemoryDetected, false)
    }
}

/**
 *Formats the long to size of memory in gb,mb etc.
 * @param size Size of memory
 */
fun formatSize(size: Long): String? {
    return android.text.format.Formatter.formatFileSize(CanonApplication.getCanonAppInstance(), size)
}

/**
 * Gives total internal memory size
 *  @return String Size of total internal memory
 * @return Boolean True if memory size is returned
 */
fun getTotalInternalStorage(): Pair<String?, Boolean> {
    if (showStorageVolumes()) {
        return Pair(formatSize(totalInternalStorage), true)
    } else {
        return Pair(error, false)
    }

}

/**
 * Gives free or available internal memory size
 *  @return String Size of free internal memory
 * @return Boolean True if memory size is returned
 */
fun getFreeInternalStorageVolume(): Pair<String?, Boolean> {
    return if (showStorageVolumes()) {
        Pair(formatSize(freeInternalStorage), true)
    } else {
        Pair(error, false)
    }
}

/**
 *For calculation of internal storage
 */
private fun showStorageVolumes(): Boolean {
    val storageManager = CanonApplication.canonApplicationInstance.applicationContext.getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageStatsManager = CanonApplication.canonApplicationInstance.applicationContext.getSystemService(Context.STORAGE_STATS_SERVICE) as StorageStatsManager
    if (storageManager == null || storageStatsManager == null) {
        return false
    }
    val storageVolumes: List<StorageVolume> = storageManager.storageVolumes
    for (storageVolume in storageVolumes) {
        var uuidStr: String? = null
        storageVolume.uuid?.let {
            uuidStr = it
        }
        val uuid: UUID = if (uuidStr == null) StorageManager.UUID_DEFAULT else UUID.fromString(uuidStr)
        return try {
            freeInternalStorage = storageStatsManager.getFreeBytes(uuid)
            totalInternalStorage = storageStatsManager.getTotalBytes(uuid)
            true
        } catch (e: Exception) {
            // IGNORED
            false
        }
    }
    return false
}

fun getTotalInternalExternalMemory(): Pair<Long?, Boolean> {
    if (externalMemoryAvailable()) {
        if (getTotalExternalMemorySize().second) {
            if (getTotalInternalStorage().second) {
                return Pair(totalExternalMemory + totalInternalStorage, true)
            } else {
                return Pair(0, false)
            }
        }
        return Pair(0, false)
    } else {
        if (getTotalInternalStorage().second) {
            return Pair(totalInternalStorage, true)
        } else {
            return Pair(0, false)
        }
    }

}

fun getTotalFreeStorage(): Pair<Long,Boolean> {
    if (externalMemoryAvailable()){
        if(getFreeInternalStorageVolume().second){
            getFreeInternalStorageVolume()
            getAvailableExternalMemorySize()
                return Pair(freeExternalMemory + freeInternalStorage,true)
        }
        else{
            return Pair(0,false)
        }
    }
    else {
        if (getFreeInternalStorageVolume().second){
            getFreeInternalStorageVolume()
            return Pair(freeInternalStorage,true)
        }
      else{
            return Pair(0,false)
        }
    }

}}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.