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ตอนนี้ ฉันจะแก้ไขรหัสนี้เพื่อให้ได้ขนาดฟรีได้อย่างไร


ในระดับ API 18 พวกเขาได้เปลี่ยนชื่อวิธีการลงท้ายด้วย Long คุณอาจต้องเพิ่มการตรวจสอบระดับ API ก่อน
Jayshil Dave

วิธีแก้ปัญหาทั้งหมดฉันพยายามไม่ให้ใครทำงานเมื่อฉันฟอร์แมตเป็นที่จัดเก็บข้อมูลภายใน ... คุณช่วยฉันหน่อยได้ไหมจะทำอย่างไรให้สำเร็จ
Yogesh Rathi

คำตอบ:


183

ด้านล่างนี้เป็นรหัสสำหรับวัตถุประสงค์ของคุณ:

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

รับขนาด RAM

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 สำหรับการคำนวณ Internal Storage ฉันได้รับผลลัพธ์บางอย่าง .. ซึ่งหมายถึงหน่วยความจำภายในหน่วยความจำอื่น ..
AK Joshi

3
@DineshPrajapati .. ทดสอบกับ MOTO G2 รับข้อมูลผิดสำหรับ External Storage
AK Joshi

1
อาจเกิดขึ้นได้ที่ API สองตัวถูกเลิกใช้งานโปรดดูที่ developer.android.com
Dinesh Prajapati

1
ใช้ Long ในตอนท้ายสำหรับระดับ API ที่ใหม่กว่า (> 18)
Gun2sh

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

3
แต่นี่คือการยกเลิก :(
abbasalim

@ ArMo372 พวกคุณหารหัสทดแทนสำหรับสิ่งนี้หรือไม่?
SimpleCoder

3
เพียงแค่เปลี่ยนgetBlockSizeและgetAvailableBlocksด้วยและgetBlockSizeLong getAvailableBlocksLong
smg

1
นี่ไม่ใช่พื้นที่ว่างที่ถูกต้อง นี่คือรับ 1141 แทน 1678 @smg

1
วิธีแก้ปัญหาไม่ทำงานเมื่อฉันฟอร์แมตเป็นที่จัดเก็บข้อมูลภายใน ... คุณช่วยฉันหน่อยได้ไหมจะทำอย่างไรให้สำเร็จ
Yogesh Rathi

27

ตั้งแต่ API 9 คุณสามารถทำได้:

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

2
File.getUsableSpace () น่าจะดีกว่าเพราะคุณอาจไม่ได้รันในฐานะรูท
ทำเครื่องหมาย

ดูเหมือนเป็นวิธีที่ง่ายต่อการใช้มากกว่าการใช้File.getUsableSpace() StatFsทำไมฉันถึงใช้StatFs@MarkCarter?
StuStirling

1
@ DiscoS2 คุณจะใช้ StatF หาก minSdkVersion ของคุณน้อยกว่า 9
มาร์ค

1
คุณจะตรวจสอบการเปลี่ยนแปลงที่เก็บข้อมูลอย่างไร
นักพัฒนา Android

26

ในการรับโฟลเดอร์จัดเก็บข้อมูลทั้งหมดที่มีอยู่ (รวมถึงการ์ด 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);

โปรดทราบว่าฉันคิดว่าที่เก็บข้อมูลภายในอาจเหมือนกับที่จัดเก็บข้อมูลภายนอกตัวแรกเนื่องจากที่เก็บข้อมูลแรกเป็นที่จำลอง


แก้ไข: การใช้ 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)
ขึ้น

@isabsent Nexus 5 ไม่มีช่องเสียบการ์ด SD คุณตรวจสอบได้อย่างไร?
นักพัฒนา Android

ฉันได้ตรวจสอบด้วยแฟลชไดรฟ์ USB OTG
ขึ้น

@isabsent ฉันไม่เคยใช้มัน ขออภัย. ทำงานได้ดีกับ API 22 และต่ำกว่าหรือไม่
นักพัฒนา Android

1
@Smeet เป็นไปได้ไหมที่คุณจะลองใช้ Android 6 ขึ้นไป? ถ้าเป็นเช่นนั้นอาจเป็นปัญหาเช่นนี้code.google.com/p/android/issues/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
Acuna

วิธีแก้ปัญหาไม่ทำงานเมื่อฉันฟอร์แมตเป็นที่จัดเก็บข้อมูลภายใน ... คุณช่วยฉันหน่อยได้ไหมจะทำอย่างไรให้สำเร็จ
Yogesh 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 สำหรับความพยายาม
นักพัฒนา android

1
@androiddeveloper ขอบคุณที่รักสำหรับการโหวต ฉันต้องการการสนับสนุนจากทุกคนเพื่อทดสอบรหัสนี้ในอุปกรณ์ของคุณเนื่องจากฉันไม่มีอุปกรณ์ทั้งหมด แต่ทดสอบในอุปกรณ์ 4 เครื่องและทำงานได้ดี โปรดแสดงความคิดเห็นที่นี่ไม่ได้ทำงานในมือถือของร่างกายใด ๆ
Smeet

วิธีแก้ปัญหาไม่ทำงานเมื่อฉันฟอร์แมตเป็นที่จัดเก็บข้อมูลภายใน ... คุณช่วยฉันหน่อยได้ไหมจะทำอย่างไรให้สำเร็จ
Yogesh Rathi

4

เพิ่มเติมอย่างรวดเร็วในหัวข้อหน่วยความจำภายนอก

อย่าสับสนกับชื่อวิธีการexternalMemoryAvailable()ในคำตอบของ Dinesh Prajapati

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 บางเครื่องอาจมีการ์ด SD 2 ใบดังนั้นหากคุณต้องการทั้งหมดให้ปรับรหัสด้านบน


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

หลังจากตรวจสอบโซลูชันอื่นแล้วให้เขียนโค้ดด้วยตัวเองนี่คือรหัสที่สมบูรณ์สำหรับการค้นหา

  • หน่วยความจำภายนอกทั้งหมด
  • หน่วยความจำภายนอกฟรี
  • ใช้หน่วยความจำภายนอก
  • หน่วยความจำภายใน 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)
        }
    }

}}

0

ไม่สามารถใช้โซลูชันใดที่กล่าวถึงในที่นี้สำหรับหน่วยความจำภายนอก นี่คือรหัสของฉัน (สำหรับ RAM, ROM, ที่เก็บข้อมูลระบบและที่เก็บข้อมูลภายนอก) คุณสามารถคำนวณพื้นที่เก็บข้อมูลฟรีโดยใช้ (พื้นที่เก็บข้อมูลทั้งหมด - พื้นที่เก็บข้อมูลที่ใช้) และห้ามใช้Environment.getExternalStorageDirectory()สำหรับจัดเก็บข้อมูลภายนอก ไม่จำเป็นต้องชี้ไปที่การ์ด SD ภายนอก นอกจากนี้โซลูชันนี้จะใช้ได้กับ Android ทุกเวอร์ชัน (ทดสอบ API 16-30 บนอุปกรณ์จริงและอีมูเลเตอร์)

    // Divide by (1024*1024*1024) to get in GB, by (1024*1024) to get in MB, by 1024 to get in KB..

    // RAM
    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    manager.getMemoryInfo(memoryInfo);
    long totalRAM=memoryInfo.totalMem;
    long availRAM=memoryInfo.availMem;  // remember to convert in GB,MB or KB.
    long usedRAM=totalRAM-availRAM;

    // ROM
    getTotalStorageInfo(Environment.getDataDirectory().getPath());
    getUsedStorageInfo(Environment.getDataDirectory().getPath());

    // System Storage
    getTotalStorageInfo(Environment.getRootDirectory().getPath());
    getUsedStorageInfo(Environment.getRootDirectory().getPath());

    // External Storage (SD Card)
    File[] files = ContextCompat.getExternalFilesDirs(context, null);
    if(Build.VERSION.SDK_INT<=Build.VERSION_CODES.JELLY_BEAN_MR2){
        if (files.length == 1) {
            Log.d("External Storage Memory","is present");
            getTotalStorageInfo(files[0].getPath());
            getUsedStorageInfo(files[0].getPath());
        }
    } else {
        if (files.length > 1 && files[0] != null && files[1] != null) {
            Log.d("External Storage Memory","is present");
            long t=getTotalStorageInfo(files[1].getPath());
            long u=getUsedStorageInfo(files[1].getPath());
            System.out.println("Total External Mem: "+t+" Used External Mem: "+u+" Storage path: "+files[1].getPath());
        }
    }
}

public long getTotalStorageInfo(String path) {
    StatFs statFs = new StatFs(path);
    long t;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        t = statFs.getTotalBytes();
    } else {
        t = statFs.getBlockCount() * statFs.getBlockCount();
    }
    return t;    // remember to convert in GB,MB or KB.
}

public long getUsedStorageInfo(String path) {
    StatFs statFs = new StatFs(path);
    long u;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
        u = statFs.getTotalBytes() - statFs.getAvailableBytes();
    } else {
        u = statFs.getBlockCount() * statFs.getBlockSize() - statFs.getAvailableBlocks() * statFs.getBlockSize();
    }
    return u;  // remember to convert in GB,MB or KB.
}

ตอนนี้สำหรับ ROM ฉันใช้ path เป็น "/ data" และสำหรับ System Storage path คือ "/ system" และสำหรับ External Storage ฉันได้ใช้ContextCompat.getExternalFilesDirs(context, null);ดังนั้นมันจะทำงานบน Android Q และ Android R ด้วย ฉันหวังว่านี่จะช่วยคุณได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.