對 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")
- }
- }
- }
- }
- }
沒有留言:
張貼留言