對 Android app,可儲存 app 自身專屬(用) 檔案於 內部儲存空間 和 外部儲存空間,內部儲存空間很小,只適合存放小容量的檔案,若不是有特殊需求,官方建議存於外部儲存空間。
雖然是使用外部儲存空間,但因為僅供 app 自身專用,所以並不須向系統請求權限。
class MainActivity : AppCompatActivity() { private val TAG = "MainActivity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 查詢磁碟區狀態 val sExternalStorage = Environment.getExternalStorageState() Log.d(TAG, "可用外部空間媒體資訊: $sExternalStorage") // mounted: 可讀/寫 // 狀態有: MEDIA_UNKNOWN, MEDIA_REMOVED, MEDIA_UNMOUNTED, MEDIA_CHECKING, MEDIA_NOFS, MEDIA_MOUNTED, MEDIA_MOUNTED_READ_ONLY, MEDIA_SHARED, MEDIA_BAD_REMOVAL, MEDIA_UNMOUNTABLE // 以前的 Android 因為 ROM 小, 多半會有 SD 卡插槽 // 現在 ROM 變大了, 也漸漸不提供 SD 卡插槽了, 並模擬出一塊虛擬 ROM val externalStorageVolumes: Array<out File> = ContextCompat.getExternalFilesDirs(applicationContext, null) Log.d(TAG, "可用外部空間媒體: ${externalStorageVolumes.size} 個") // 2 個, 1 個實體 SD 卡, 1 個虛擬 ROM for(xx in externalStorageVolumes.indices) { val primaryExternalStorage = externalStorageVolumes[xx] Log.d(TAG, "可用外部空間 $xx: $primaryExternalStorage") // 可用外部空間 0: /storage/emulated/0/Android/data/[您的 app 完整 package 名]/files, 虛擬 ROM 通常會是第 1 個 // 可用外部空間 1: /storage/9E1E-5F1E/Android/data/[您的 app 完整 package 名]/files, 實體 SD 卡 } if(Environment.getExternalStorageState()==Environment.MEDIA_MOUNTED) { // 有外部儲存空間媒體, 且可 讀/寫 // 官方強烈建議, 若沒有特殊需要, 優先使用第 1 個可用外部空間 val mFilePath = externalStorageVolumes[0] Log.d(TAG, "mFilePath: $mFilePath") // /storage/emulated/0/Android/data/[您的 app 完整 package 名]/files val mExtdir = File(getExternalFilesDir(null), "Chkspace") // 查詢可用空間 val mScope = CoroutineScope(Job() + Dispatchers.IO) mScope.launch { var mBytes: Long = 0 // 1. 由於在 Android8(Oreo) 推出新的 API26, // storageManager.getUuidForPath 不能在主執行緒呼叫, 因此要在 coroutine 內執行 // 2. 舊的 API 在未來會被棄用, 所以要分開處理 if(Build.VERSION.SDK_INT>=26) { val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager val uuid = storageManager.getUuidForPath(externalStorageVolumes[0]) try { mBytes = storageManager.getAllocatableBytes(uuid) } catch(err: IOException) { err.printStackTrace() } } else { val path = Environment.getDataDirectory() val stat = StatFs(path.path) val blockSize: Long = stat.blockSizeLong val availableBlocks: Long = stat.availableBlocksLong mBytes = availableBlocks * blockSize } val formatter = DecimalFormat("#,###") Log.d(TAG, "可用剩餘外部儲存空間 = ${formatter.format(mBytes)} ") if(mBytes>=1024) { val mKB = (mBytes/1024) // 換算為 kb if(mKB>=1024) { val mmMB = (mKB/1024) // 換算為 mb if(mmMB>=1024) { val mGB = (mmMB/1024) // 換算為 gb Log.d(TAG, "可用剩餘外部儲存空間 = $mGB gb") } else Log.d(TAG, "可用剩餘外部儲存空間 = $mmMB mb") } else { Log.d(TAG, "可用剩餘外部儲存空間 = $mKB kb") } } else { Log.d(TAG, "可用剩餘外部儲存空間 = $mBytes bytes") } } } } }
沒有留言:
張貼留言