2014-01-23 31 views
1

我目前正在開發一個應用程序,在該應用程序中顯示關於它所安裝的設備的各種不同統計信息。其中一個統計數據被使用/ SD卡的總空間。我得到它的答案發現HereHereAndroid內部SD卡大小不返回「true」大小

事情是,我相信無論如何,沒有root權限,它不會返回內部(模擬)SD卡的「真實」值。下面是一些代碼:

如何獲取Sd中的位置(S)和大小(S):

new StorageUtils(); 
    ArrayList<StorageInfo> storageInfoList = StorageUtils.getStorageList(); 

    if (storageInfoList.size() > 0) { 
     tvStorageAName = (TextView) findViewById(R.id.tvStorageAName); 
     tvStorageAName.setText(storageInfoList.get(0).path); 

     devStorageA = StorageUtils.getReadableFileSize(
       (StorageUtils.getUsedSpace(storageInfoList.get(0).path)), 
       true) 
       + "/" 
       + StorageUtils.getReadableFileSize((StorageUtils 
         .getTotalSpace(storageInfoList.get(0).path)), true); 

     if (storageInfoList.size() > 1) { 

      tvStorageBName = (TextView) findViewById(R.id.tvStorageBName); 
      tvStorageBName.setText(storageInfoList.get(1).path); 

      devStorageB = StorageUtils.getReadableFileSize(
        StorageUtils.getUsedSpace(storageInfoList.get(1).path) 
          + (StorageUtils.getUsedSpace("system/")), true) 
        + "/" 
        + StorageUtils.getReadableFileSize((StorageUtils 
          .getTotalSpace(storageInfoList.get(1).path)), 
          true); 
     } else { 
      devStorageB = "N/A"; 
     } 
    } else { 
     devStorageA = "N/A"; 
     devStorageB = "N/A"; 
    } 

我StorageUtils類:

public class StorageUtils { 

private static final String TAG = "StorageUtils"; 

public static class StorageInfo { 

    public final String path; 
    public final boolean internal; 
    public final boolean readonly; 
    public final int display_number; 

    StorageInfo(String path, boolean internal, boolean readonly, 
      int display_number) { 
     this.path = path; 
     this.internal = internal; 
     this.readonly = readonly; 
     this.display_number = display_number; 
    } 
} 

public static ArrayList<StorageInfo> getStorageList() { 

    ArrayList<StorageInfo> list = new ArrayList<StorageInfo>(); 
    String def_path = Environment.getExternalStorageDirectory().getPath(); 
    boolean def_path_internal = !Environment.isExternalStorageRemovable(); 
    String def_path_state = Environment.getExternalStorageState(); 
    boolean def_path_available = def_path_state 
      .equals(Environment.MEDIA_MOUNTED) 
      || def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY); 
    boolean def_path_readonly = Environment.getExternalStorageState() 
      .equals(Environment.MEDIA_MOUNTED_READ_ONLY); 
    BufferedReader buf_reader = null; 
    try { 
     HashSet<String> paths = new HashSet<String>(); 
     buf_reader = new BufferedReader(new FileReader("/proc/mounts")); 
     String line; 
     int cur_display_number = 1; 
     Log.d(TAG, "/proc/mounts"); 
     while ((line = buf_reader.readLine()) != null) { 
      Log.d(TAG, line); 
      if (line.contains("vfat") || line.contains("/mnt")) { 
       StringTokenizer tokens = new StringTokenizer(line, " "); 
       String unused = tokens.nextToken(); // device 
       String mount_point = tokens.nextToken(); // mount point 
       if (paths.contains(mount_point)) { 
        continue; 
       } 
       unused = tokens.nextToken(); // file system 
       List<String> flags = Arrays.asList(tokens.nextToken() 
         .split(",")); // flags 
       boolean readonly = flags.contains("ro"); 

       if (mount_point.equals(def_path)) { 
        paths.add(def_path); 
        list.add(new StorageInfo(def_path, def_path_internal, 
          readonly, -1)); 
       } else if (line.contains("/dev/block/vold")) { 
        if (!line.contains("/mnt/secure") 
          && !line.contains("/mnt/asec") 
          && !line.contains("/mnt/obb") 
          && !line.contains("/dev/mapper") 
          && !line.contains("tmpfs")) { 
         paths.add(mount_point); 
         list.add(new StorageInfo(mount_point, false, 
           readonly, cur_display_number++)); 
        } 
       } 
      } 
     } 

     if (!paths.contains(def_path) && def_path_available) { 
      list.add(new StorageInfo(def_path, def_path_internal, 
        def_path_readonly, -1)); 
     } 

    } catch (FileNotFoundException ex) { 
     ex.printStackTrace(); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } finally { 
     if (buf_reader != null) { 
      try { 
       buf_reader.close(); 
      } catch (IOException ex) { 
      } 
     } 
    } 
    return list; 
} 

public static String getReadableFileSize(long bytes, boolean si) { 
    int unit = si ? 1000 : 1024; 
    if (bytes < unit) 
     return bytes + " B"; 
    int exp = (int) (Math.log(bytes)/Math.log(unit)); 
    String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) 
      + (si ? "" : "i"); 
    return String.format("%.1f %sB", bytes/Math.pow(unit, exp), pre); 
} 

@SuppressLint("NewApi") 
public static long getFreeSpace(String path) { 
    StatFs statFs = new StatFs(path); 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
     long sdAvailSize = statFs.getFreeBlocksLong() 
       * statFs.getBlockSizeLong(); 
     return sdAvailSize; 
    } else { 
     @SuppressWarnings("deprecation") 
     double sdAvailSize = (double) statFs.getFreeBlocks() 
       * (double) statFs.getBlockSize(); 

     return (long) sdAvailSize; 
    } 
} 

public static long getUsedSpace(String path) { 
    return getTotalSpace(path) - getFreeSpace(path); 
} 

@SuppressLint("NewApi") 
public static long getTotalSpace(String path) { 
    StatFs statFs = new StatFs(path); 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
     long sdTotalSize = statFs.getBlockCountLong() 
       * statFs.getBlockSizeLong(); 
     return sdTotalSize; 
    } else { 
     @SuppressWarnings("deprecation") 
     double sdTotalSize = (double) statFs.getBlockCount() 
       * statFs.getBlockSize(); 

     return (long) sdTotalSize; 
    } 
} 

} 

的問題是我猜,這是獲得這些大小(沒有root權限)的最準確的方法,還是有更好的方法來做到這一點?任何和所有的幫助非常感謝,感謝您花時間閱讀本文!

編輯:外部SD卡並沒有給我一個問題。內部SD卡(也似乎是數據/目錄)沒有顯示總計。它在我的測試設備上缺少〜5Gb。有任何想法嗎?

編輯2:我有一個朋友測試他們的電話,內部顯示36.0 GB(已用)/ 8.6 GB(總計),爲什麼這會返回這樣的零星結果?一個應用程序如何說文件管理器返回結果?

+0

模擬卷不具有** a *真*「大小」,因爲在使用該塊和使用同一塊塊用於其他目的之間存在權衡。仿真層可能會強加一個人爲限制,但這也不是真正的大小。 –

+0

感謝您的回覆。我在他們的手機上進行了朋友測試,內部顯示36.0 GB(使用)/ 8.6 GB(總計)。似乎會有辦法獲得更好的結果,有什麼想法?感謝您的時間。 – MattMatt

回答

0

經過一段時間的修補,我發現我的滿意。

在我的片段:

ArrayList<StorageInfo> storageInfoList = StorageUtils.getStorageList(); 

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 
     kitKatWorkaround(); 
    } else if (storageInfoList.size() > 0) { 

     tvStorageAName.setText(storageInfoList.get(0).path); 

     long usedA = StorageUtils.getUsedSpace(storageInfoList.get(0).path); 
     long totalA = StorageUtils 
       .getTotalSpace(storageInfoList.get(0).path); 

     devStorageA = StorageUtils.getReadableFileSize(usedA, true) + "/" 
       + StorageUtils.getReadableFileSize(totalA, true); 

     progA.setProgress(0); 
     progA.setProgress(Integer.parseInt(StorageUtils.getReadableFileSize(usedA, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", ""))); 
     progA.setMax(Integer.parseInt(StorageUtils.getReadableFileSize(totalA, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", ""))); 

     Log.d("Storage", usedA + "/" + totalA); 

     if (storageInfoList.size() > 1) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT 
        && !storageInfoList.get(0).internal) { 
       kitKatWorkaround(); 
      } 
      tvStorageBName.setText(storageInfoList.get(1).path); 

      long usedB = StorageUtils 
        .getUsedSpace(storageInfoList.get(1).path) 
        + (StorageUtils.getUsedSpace("system/")); 
      long totalB = StorageUtils 
        .getTotalSpace(storageInfoList.get(1).path); 

      devStorageB = StorageUtils.getReadableFileSize(usedB, true) 
        + "/" + StorageUtils.getReadableFileSize(totalB, true); 

      progB.setProgress(0); 
      progB.setProgress(Integer.parseInt(StorageUtils.getReadableFileSize(usedB, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", "").trim())); 
      progB.setMax(Integer.parseInt(StorageUtils.getReadableFileSize(totalB, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", "").trim())); 

      Log.d("Storage", usedB + "/" + totalB); 
     } else { 

      tvStorageBName.setVisibility(View.GONE); 
      tvStorageB.setVisibility(View.GONE); 
      progB.setVisibility(View.GONE); 
      devStorageB = "N/A"; 
     } 
    } else { 
     devStorageA = "N/A"; 

     tvStorageBName.setVisibility(View.GONE); 
     tvStorageB.setVisibility(View.GONE); 
     progB.setVisibility(View.GONE); 
     devStorageB = "N/A"; 
    } 
    // 
    // ################################# 

    // STORAGE 
    tvStorageA.setText(devStorageA); 

    tvStorageB.setText(devStorageB); 
    // 
    // ################################# 
} 

和修訂StorageUtils方法:

public static String getReadableFileSize(long bytes, boolean si) { 
    int unit = si ? 1000 : 1024; 
    if (bytes < unit) 
     return bytes + " B"; 
    int exp = (int) (Math.log(bytes)/Math.log(unit)); 
    String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) 
      + (si ? "" : "i"); 
    return String.format("%.1f %sB", bytes/Math.pow(unit, exp), pre); 
} 

@SuppressLint("NewApi") 
public static long getFreeSpace(String path) { 
    StatFs statFs = new StatFs(path); 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
     long sdAvailSize = statFs.getFreeBlocksLong() 
       * statFs.getBlockSizeLong(); 
     return sdAvailSize; 
    } else { 
     @SuppressWarnings("deprecation") 
     double sdAvailSize = (double) statFs.getFreeBlocks() 
       * (double) statFs.getBlockSize(); 

     return (long) sdAvailSize; 
    } 
} 

public static long getUsedSpace(String path) { 
    return getTotalSpace(path) - getFreeSpace(path); 
} 

@SuppressLint("NewApi") 
public static long getTotalSpace(String path) { 
    StatFs statFs = new StatFs(path); 
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { 
     long sdTotalSize = statFs.getBlockCountLong() 
       * statFs.getBlockSizeLong(); 
     return sdTotalSize; 
    } else { 
     @SuppressWarnings("deprecation") 
     double sdTotalSize = (double) statFs.getBlockCount() 
       * statFs.getBlockSize(); 

     return (long) sdTotalSize; 
    } 
} 

編輯 另外,KitKatWorkaround方法那些誰正在尋找:

@SuppressLint("NewApi") 
public void kitKatWorkaround() { 

    File[] sdCards = getActivity().getApplicationContext() 
      .getExternalCacheDirs(); 

    if (sdCards.length > 0 
      && sdCards[0] != null 
      && Environment.getStorageState(sdCards[0]).equals(
      Environment.MEDIA_MOUNTED)) { 

     File sdCard1 = sdCards[0]; 

     tvStorageAName.setText(sdCard1.getAbsolutePath() 
       .replace(
         "Android/data/" + getActivity().getPackageName() 
           + "/cache", "")); 

     long usedA = StorageUtils.getUsedSpace(sdCard1.getAbsolutePath()); 
     long totalA = StorageUtils.getTotalSpace(sdCard1.getAbsolutePath()); 

     devStorageA = StorageUtils.getReadableFileSize(usedA, true) + "/" 
       + StorageUtils.getReadableFileSize(totalA, true); 

     progA.setProgress(0); 
     progA.setProgress(Integer.parseInt(StorageUtils.getReadableFileSize(usedA, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", "").trim())); 
     progA.setMax(Integer.parseInt(StorageUtils.getReadableFileSize(totalA, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", "").trim())); 

     Log.d("Storage", usedA + "/" + totalA); 
    } else { 
     devStorageA = "N/A"; 
    } 

    if (sdCards.length > 1 
      && sdCards[1] != null 
      && Environment.getStorageState(sdCards[1]).equals(
      Environment.MEDIA_MOUNTED)) { 
     File sdCard2 = sdCards[1]; 

     tvStorageBName.setText(sdCard2.getAbsolutePath() 
       .replace(
         "Android/data/" + getActivity().getPackageName() 
           + "/cache", "")); 

     long usedB = StorageUtils.getUsedSpace(sdCard2.getAbsolutePath()); 
     long totalB = StorageUtils.getTotalSpace(sdCard2.getAbsolutePath()); 

     devStorageB = StorageUtils.getReadableFileSize(usedB, true) + "/" 
       + StorageUtils.getReadableFileSize(totalB, true); 
     progB.setProgress(0); 
     progB.setProgress(Integer.parseInt(StorageUtils.getReadableFileSize(totalB, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", "").trim())); 
     progB.setMax(Integer.parseInt(StorageUtils.getReadableFileSize(totalB, true).replace(".", "").replace("k", "").replace("M", "").replace("G", "").replace("T", "").replace("P", "").replace("B", "").trim())); 

     Log.d("Storage", usedB + "/" + totalB); 

    } else { 
     tvStorageBName.setVisibility(View.GONE); 
     tvStorageB.setVisibility(View.GONE); 
     progB.setVisibility(View.GONE); 
     devStorageB = "N/A"; 
    } 

    tvStorageA.setText(devStorageA); 
    tvStorageB.setText(devStorageB); 
} 
相關問題