ในหลายกรณี แอปของคุณจะสร้างไฟล์ที่แอปอื่นๆ ไม่จำเป็นต้องเข้าถึงหรือไม่ควรเข้าถึง ระบบมีตำแหน่งต่อไปนี้สำหรับจัดเก็บไฟล์เฉพาะแอปดังกล่าว
ไดเรกทอรีที่จัดเก็บข้อมูลภายใน: ไดเรกทอรีเหล่านี้มีทั้งตำแหน่งเฉพาะสำหรับจัดเก็บไฟล์ถาวร และตำแหน่งอื่นสำหรับจัดเก็บข้อมูลแคช ระบบจะป้องกันไม่ให้แอปอื่นๆ เข้าถึงตำแหน่งเหล่านี้ และมีการเข้ารหัสสถานที่ใน Android 10 (API ระดับ 29) ขึ้นไป ลักษณะเฉพาะเหล่านี้ทำให้ตำแหน่งเหล่านี้เป็นพื้นที่ที่ดีในการจัดเก็บข้อมูลที่ละเอียดอ่อน ซึ่งมีเพียงตัวแอปของคุณเท่านั้นที่เข้าถึงได้
ไดเรกทอรีพื้นที่เก็บข้อมูลภายนอก: ไดเรกทอรีเหล่านี้มีทั้งตำแหน่งเฉพาะสำหรับจัดเก็บไฟล์ถาวร และอีกตำแหน่งสำหรับจัดเก็บข้อมูลแคช แม้ว่าแอปอื่นอาจเข้าถึงไดเรกทอรีเหล่านี้ได้ หากแอปดังกล่าวมีสิทธิ์ที่เหมาะสม แต่ไฟล์ที่จัดเก็บไว้ในไดเรกทอรีเหล่านี้ มีไว้เพื่อการใช้งานโดยแอปของคุณเท่านั้น หากคุณตั้งใจที่จะสร้างไฟล์ที่แอปอื่นๆ ควรเข้าถึงได้โดยเฉพาะ แอปของคุณควรจัดเก็บไฟล์เหล่านี้ไว้ในส่วนพื้นที่เก็บข้อมูลที่ใช้ร่วมกันของที่จัดเก็บข้อมูลภายนอกแทน
เมื่อผู้ใช้ถอนการติดตั้งแอป ไฟล์ที่บันทึกไว้ในพื้นที่เก็บข้อมูลเฉพาะแอปจะถูกนำออก ด้วยเหตุนี้ คุณจึงไม่ควรใช้พื้นที่เก็บข้อมูลนี้เพื่อบันทึกข้อมูลใดๆ ที่ผู้ใช้คาดหวังว่าจะคงอยู่โดยไม่ขึ้นอยู่กับแอปของคุณ เช่น หากแอปของคุณอนุญาตให้ผู้ใช้จับภาพ ผู้ใช้จะคาดหวังว่าจะเข้าถึงรูปภาพเหล่านั้นได้แม้ว่าจะถอนการติดตั้งแอปแล้วก็ตาม คุณจึงควรใช้พื้นที่เก็บข้อมูลที่ใช้ร่วมกันเพื่อบันทึกไฟล์ประเภทเหล่านั้นลงในคอลเล็กชันสื่อที่เหมาะสมแทน
ส่วนต่อไปนี้อธิบายวิธีจัดเก็บและเข้าถึงไฟล์ภายในไดเรกทอรีเฉพาะแอป
การเข้าถึงจากที่จัดเก็บข้อมูลภายใน
สําหรับแต่ละแอป ระบบจะมีไดเรกทอรีภายในที่จัดเก็บข้อมูลภายในซึ่งแอปสามารถจัดระเบียบไฟล์ได้ ไดเรกทอรีหนึ่งออกแบบมาสำหรับไฟล์ถาวรของแอป และอีกไดเรกทอรีหนึ่งมีไฟล์แคชของแอป แอปของคุณไม่จําเป็นต้องมีสิทธิ์ของระบบในการอ่านและเขียนไฟล์ในไดเรกทอรีเหล่านี้
แอปอื่นๆ จะเข้าถึงไฟล์ที่จัดเก็บไว้ในที่จัดเก็บข้อมูลภายในไม่ได้ ซึ่งทำให้พื้นที่เก็บข้อมูลภายในเป็นพื้นที่ที่ดีสำหรับข้อมูลแอปที่ไม่ควรให้แอปอื่นๆ เข้าถึง
อย่างไรก็ตาม โปรดทราบว่าไดเรกทอรีเหล่านี้มักจะมีขนาดเล็ก ก่อนเขียนไฟล์เฉพาะแอปลงในพื้นที่เก็บข้อมูลภายใน แอปของคุณควรค้นหาพื้นที่ว่างในอุปกรณ์
เข้าถึงไฟล์ถาวร
ไฟล์ถาวรธรรมดาของแอปจะอยู่ในไดเรกทอรีที่คุณเข้าถึงได้โดยใช้พร็อพเพอร์ตี้ filesDir
ของออบเจ็กต์บริบท เฟรมเวิร์กนี้มีวิธีที่หลากหลายเพื่อช่วยให้คุณ
เข้าถึงและจัดเก็บไฟล์ในไดเรกทอรีนี้ได้
เข้าถึงและจัดเก็บไฟล์
คุณใช้ File
API เพื่อเข้าถึงและจัดเก็บไฟล์ได้
อย่าเปิดและปิดไฟล์เดียวกันหลายครั้งเพื่อช่วยรักษาประสิทธิภาพของแอป
ข้อมูลโค้ดต่อไปนี้แสดงวิธีใช้ File
API
Kotlin
val file = File(context.filesDir, filename)
Java
File file = new File(context.getFilesDir(), filename);
จัดเก็บไฟล์โดยใช้สตรีม
นอกจากการใช้ File
API แล้ว คุณยังเรียกใช้ openFileOutput()
เพื่อรับ FileOutputStream
ที่เขียนไปยังไฟล์ภายในไดเรกทอรี filesDir
ได้ด้วย
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเขียนข้อความลงในไฟล์
Kotlin
val filename = "myfile" val fileContents = "Hello world!" context.openFileOutput(filename, Context.MODE_PRIVATE).use { it.write(fileContents.toByteArray()) }
Java
String filename = "myfile"; String fileContents = "Hello world!"; try (FileOutputStream fos = context.openFileOutput(filename, Context.MODE_PRIVATE)) { fos.write(fileContents.toByteArray()); }
หากต้องการอนุญาตให้แอปอื่นๆ เข้าถึงไฟล์ที่จัดเก็บไว้ในไดเรกทอรีนี้ภายในที่จัดเก็บข้อมูลภายใน ให้ใช้ FileProvider
ที่มีแอตทริบิวต์ FLAG_GRANT_READ_URI_PERMISSION
เข้าถึงไฟล์โดยใช้สตรีม
หากต้องการอ่านไฟล์ในรูปแบบสตรีม ให้ใช้ openFileInput()
โดยทำดังนี้
Kotlin
context.openFileInput(filename).bufferedReader().useLines { lines -> lines.fold("") { some, text -> "$some\n$text" } }
Java
FileInputStream fis = context.openFileInput(filename); InputStreamReader inputStreamReader = new InputStreamReader(fis, StandardCharsets.UTF_8); StringBuilder stringBuilder = new StringBuilder(); try (BufferedReader reader = new BufferedReader(inputStreamReader)) { String line = reader.readLine(); while (line != null) { stringBuilder.append(line).append('\n'); line = reader.readLine(); } } catch (IOException e) { // Error occurred when opening raw file for reading. } finally { String contents = stringBuilder.toString(); }
ดูรายการไฟล์
คุณสามารถรับอาร์เรย์ที่มีชื่อของไฟล์ทั้งหมดภายในไดเรกทอรี filesDir
ได้โดยการเรียกใช้ fileList()
ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
Kotlin
var files: Array<String> = context.fileList()
Java
Array<String> files = context.fileList();
สร้างไดเรกทอรีที่ซ้อนกัน
คุณยังสร้างไดเรกทอรีที่ฝังอยู่หรือเปิดไดเรกทอรีภายในได้โดยเรียกใช้ getDir()
ในโค้ดที่ใช้ Kotlin หรือส่งไดเรกทอรีรูทและชื่อไดเรกทอรีใหม่ไปยังคอนสตรัคเตอร์ File
ในโค้ดที่ใช้ Java ดังนี้
Kotlin
context.getDir(dirName, Context.MODE_PRIVATE)
Java
File directory = context.getFilesDir(); File file = new File(directory, filename);
สร้างไฟล์แคช
หากต้องการจัดเก็บข้อมูลที่ละเอียดอ่อนเพียงชั่วคราว คุณควรใช้ไดเรกทอรีแคชที่กำหนดไว้ของแอปภายในที่จัดเก็บข้อมูลภายในเพื่อบันทึกข้อมูล ระบบจะนำไฟล์ที่จัดเก็บไว้ในไดเรกทอรีนี้ออกเมื่อผู้ใช้ถอนการติดตั้งแอปของคุณ เช่นเดียวกับพื้นที่เก็บข้อมูลเฉพาะแอปทั้งหมด แม้ว่าระบบอาจนำไฟล์ในไดเรกทอรีนี้ออกเร็วกว่านั้น
หากต้องการสร้างไฟล์ที่แคชไว้ ให้เรียกใช้
File.createTempFile()
:
Kotlin
File.createTempFile(filename, null, context.cacheDir)
Java
File.createTempFile(filename, null, context.getCacheDir());
แอปของคุณเข้าถึงไฟล์ในไดเรกทอรีนี้โดยใช้พร็อพเพอร์ตี้ cacheDir
ของออบเจ็กต์บริบทและ File
API ดังนี้
Kotlin
val cacheFile = File(context.cacheDir, filename)
Java
File cacheFile = new File(context.getCacheDir(), filename);
นำไฟล์แคชออก
แม้ว่าบางครั้ง Android จะลบไฟล์แคชออกเอง คุณก็ไม่ควรพึ่งพาระบบในการล้างไฟล์เหล่านี้ คุณควรดูแลไฟล์แคชของแอปไว้ในที่จัดเก็บข้อมูลภายในเสมอ
หากต้องการนำไฟล์ออกจากไดเรกทอรีแคชภายในที่เก็บข้อมูลภายใน ให้ใช้วิธีใดวิธีหนึ่งต่อไปนี้
เมธอด
delete()
บนออบเจ็กต์File
ที่แสดงไฟล์Kotlin
cacheFile.delete()
Java
cacheFile.delete();
วิธีการ
deleteFile()
ของบริบทของแอป โดยส่งชื่อไฟล์Kotlin
context.deleteFile(cacheFileName)
Java
context.deleteFile(cacheFileName);
การเข้าถึงจากที่จัดเก็บข้อมูลภายนอก
หากที่จัดเก็บข้อมูลภายในมีที่ว่างไม่พอสำหรับจัดเก็บไฟล์เฉพาะของแอป ให้พิจารณาใช้พื้นที่เก็บข้อมูลภายนอกแทน ระบบจะมีไดเรกทอรีภายในพื้นที่เก็บข้อมูลภายนอกที่แอปสามารถจัดระเบียบไฟล์ที่เป็นประโยชน์ต่อผู้ใช้ได้ภายในแอปเท่านั้น โดยไดเรกทอรีหนึ่งออกแบบมาสำหรับไฟล์ถาวรของแอป และอีกไดเรกทอรีหนึ่งมีไฟล์ที่แอปแคชไว้
ใน Android 4.4 (API ระดับ 19) ขึ้นไป แอปของคุณไม่จำเป็นต้องขอสิทธิ์เกี่ยวกับพื้นที่เก็บข้อมูลเพื่อเข้าถึงไดเรกทอรีเฉพาะแอปภายในพื้นที่เก็บข้อมูลภายนอก ระบบจะนำไฟล์ที่จัดเก็บไว้ในไดเรกทอรีเหล่านี้ออกเมื่อคุณถอนการติดตั้งแอป
ในอุปกรณ์ที่ใช้ Android 9 (API ระดับ 28) หรือต่ำกว่า แอปของคุณจะเข้าถึงไฟล์เฉพาะแอปที่เป็นของแอปอื่นๆ ได้ ในกรณีที่แอปมีสิทธิ์เข้าถึงพื้นที่เก็บข้อมูลที่เหมาะสม แอปที่กำหนดเป้าหมายเป็น Android 10 (API ระดับ 29) ขึ้นไปจะได้รับสิทธิ์เข้าถึงที่กําหนดขอบเขตในที่จัดเก็บข้อมูลภายนอกหรือพื้นที่เก็บข้อมูลที่กําหนดขอบเขตโดยค่าเริ่มต้น เพื่อให้ผู้ใช้ควบคุมไฟล์ได้มากขึ้นและจำกัดไฟล์ที่รก เมื่อเปิดใช้พื้นที่เก็บข้อมูลที่กำหนดขอบเขต แอปจะเข้าถึงไดเรกทอรีเฉพาะแอปที่เป็นของแอปอื่นไม่ได้
ตรวจสอบว่ามีพื้นที่เก็บข้อมูลเพียงพอ
เนื่องจากพื้นที่เก็บข้อมูลภายนอกอยู่ในระดับเสียงจริงที่ผู้ใช้อาจนำออกได้ โปรดยืนยันว่าวอลุ่มดังกล่าวเข้าถึงได้ก่อนที่จะพยายามอ่านข้อมูลเฉพาะแอปหรือเขียนข้อมูลเฉพาะแอปไปยังที่จัดเก็บข้อมูลภายนอก
คุณค้นหาสถานะของระดับเสียงได้โดยโทรไปที่ Environment.getExternalStorageState()
หากสถานะการแสดงผลคือ MEDIA_MOUNTED
คุณจะอ่านและเขียนไฟล์เฉพาะแอปภายในพื้นที่เก็บข้อมูลภายนอกได้ หากเป็น MEDIA_MOUNTED_READ_ONLY
คุณจะอ่านไฟล์เหล่านี้ได้เท่านั้น
ตัวอย่างเช่น วิธีการต่อไปนี้มีประโยชน์ในการระบุความพร้อมใช้งานของพื้นที่เก็บข้อมูล
Kotlin
// Checks if a volume containing external storage is available // for read and write. fun isExternalStorageWritable(): Boolean { return Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED } // Checks if a volume containing external storage is available to at least read. fun isExternalStorageReadable(): Boolean { return Environment.getExternalStorageState() in setOf(Environment.MEDIA_MOUNTED, Environment.MEDIA_MOUNTED_READ_ONLY) }
Java
// Checks if a volume containing external storage is available // for read and write. private boolean isExternalStorageWritable() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); } // Checks if a volume containing external storage is available to at least read. private boolean isExternalStorageReadable() { return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) || Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY); }
ในอุปกรณ์ที่ไม่มีพื้นที่เก็บข้อมูลภายนอกแบบถอดได้ ให้ใช้คำสั่งต่อไปนี้เพื่อเปิดใช้วอลุ่มเสมือนสำหรับการทดสอบตรรกะความพร้อมใช้งานของพื้นที่เก็บข้อมูลภายนอก
adb shell sm set-virtual-disk true
เลือกตำแหน่งพื้นที่เก็บข้อมูลจริง
บางครั้งอุปกรณ์ที่จัดสรรพาร์ติชันของหน่วยความจำภายในเป็นพื้นที่เก็บข้อมูลภายนอกจะมีช่องเสียบการ์ด SD ด้วย ซึ่งหมายความว่าอุปกรณ์มีวอลุ่มจริงหลายรายการที่อาจมีพื้นที่เก็บข้อมูลภายนอก คุณจึงต้องเลือกวอลุ่มที่จะใช้สำหรับพื้นที่เก็บข้อมูลเฉพาะแอป
หากต้องการเข้าถึงตำแหน่งต่างๆ ให้โทรไปที่ ContextCompat.getExternalFilesDirs()
ดังที่แสดงในข้อมูลโค้ด องค์ประกอบแรกในอาร์เรย์ที่แสดงผลจะพิจารณาปริมาณพื้นที่เก็บข้อมูลภายนอกหลัก ใช้ระดับเสียงนี้จนกว่าจะเต็ม
หรือไม่พร้อมใช้งาน
Kotlin
val externalStorageVolumes: Array<out File> = ContextCompat.getExternalFilesDirs(applicationContext, null) val primaryExternalStorage = externalStorageVolumes[0]
Java
File[] externalStorageVolumes = ContextCompat.getExternalFilesDirs(getApplicationContext(), null); File primaryExternalStorage = externalStorageVolumes[0];
เข้าถึงไฟล์ถาวร
หากต้องการเข้าถึงไฟล์เฉพาะแอปจากที่จัดเก็บข้อมูลภายนอก ให้เรียกใช้ getExternalFilesDir()
อย่าเปิดและปิดไฟล์เดียวกันหลายครั้ง เพื่อช่วยรักษาประสิทธิภาพของแอป
ข้อมูลโค้ดต่อไปนี้แสดงวิธีเรียก getExternalFilesDir()
Kotlin
val appSpecificExternalDir = File(context.getExternalFilesDir(null), filename)
Java
File appSpecificExternalDir = new File(context.getExternalFilesDir(null), filename);
สร้างไฟล์แคช
หากต้องการเพิ่มไฟล์เฉพาะแอปลงในแคชภายในพื้นที่เก็บข้อมูลภายนอก ให้รับการอ้างอิงถึง externalCacheDir
ดังนี้
Kotlin
val externalCacheFile = File(context.externalCacheDir, filename)
Java
File externalCacheFile = new File(context.getExternalCacheDir(), filename);
นำไฟล์แคชออก
หากต้องการนำไฟล์ออกจากไดเรกทอรีแคชภายนอก ให้ใช้เมธอด delete()
บนออบเจ็กต์ File
ที่แสดงไฟล์
Kotlin
externalCacheFile.delete()
Java
externalCacheFile.delete();
เนื้อหาสื่อ
หากแอปของคุณทำงานกับไฟล์สื่อที่ให้คุณค่าแก่ผู้ใช้ภายในแอปเท่านั้น คุณควรจัดเก็บไฟล์เหล่านั้นไว้ในไดเรกทอรีเฉพาะแอปภายในพื้นที่เก็บข้อมูลภายนอก ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
Kotlin
fun getAppSpecificAlbumStorageDir(context: Context, albumName: String): File? { // Get the pictures directory that's inside the app-specific directory on // external storage. val file = File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName) if (!file?.mkdirs()) { Log.e(LOG_TAG, "Directory not created") } return file }
Java
@Nullable File getAppSpecificAlbumStorageDir(Context context, String albumName) { // Get the pictures directory that's inside the app-specific directory on // external storage. File file = new File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName); if (file == null || !file.mkdirs()) { Log.e(LOG_TAG, "Directory not created"); } return file; }
คุณควรใช้ชื่อไดเรกทอรีที่ได้จากค่าคงที่ API เช่น DIRECTORY_PICTURES
ชื่อไดเรกทอรีเหล่านี้ช่วยให้ระบบจัดการไฟล์ได้อย่างถูกต้อง
หากไม่มีชื่อไดเรกทอรีย่อยที่กําหนดไว้ล่วงหน้าใดเหมาะกับไฟล์ของคุณ คุณสามารถส่ง null
ไปยัง getExternalFilesDir()
แทนได้ ซึ่งจะแสดงไดเรกทอรีรูทสำหรับแอปที่เฉพาะเจาะจงภายในที่จัดเก็บข้อมูลภายนอก
ค้นหาพื้นที่ว่าง
ผู้ใช้จำนวนมากมีพื้นที่เก็บข้อมูลในอุปกรณ์ไม่เพียงพอ แอปของคุณจึงควรใช้พื้นที่อย่างรอบคอบ
หากคุณทราบล่วงหน้าว่าคุณเก็บข้อมูลได้เท่าใด คุณสามารถดู
พื้นที่ที่อุปกรณ์จัดสรรแอปให้คุณได้โดยโทรหา
getAllocatableBytes()
ค่าที่ได้ getAllocatableBytes()
อาจมากกว่าพื้นที่ว่างปัจจุบันในอุปกรณ์ เนื่องจากระบบได้ระบุไฟล์ที่สามารถนำออกจากไดเรกทอรีแคชของแอปอื่นๆ ได้
หากมีพื้นที่เพียงพอที่จะบันทึกข้อมูลของแอป ให้โทรไปที่ allocateBytes()
หรือแอปจะขอให้ผู้ใช้นำไฟล์บางไฟล์ออกจากอุปกรณ์หรือนำไฟล์แคชทั้งหมดออกจากอุปกรณ์ก็ได้
ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างวิธีที่แอปสามารถค้นหาพื้นที่ว่างในอุปกรณ์
Kotlin
// App needs 10 MB within internal storage. const val NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L; val storageManager = applicationContext.getSystemService<StorageManager>()!! val appSpecificInternalDirUuid: UUID = storageManager.getUuidForPath(filesDir) val availableBytes: Long = storageManager.getAllocatableBytes(appSpecificInternalDirUuid) if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) { storageManager.allocateBytes( appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP) } else { val storageIntent = Intent().apply { // To request that the user remove all app cache files instead, set // "action" to ACTION_CLEAR_APP_CACHE. action = ACTION_MANAGE_STORAGE } }
Java
// App needs 10 MB within internal storage. private static final long NUM_BYTES_NEEDED_FOR_MY_APP = 1024 * 1024 * 10L; StorageManager storageManager = getApplicationContext().getSystemService(StorageManager.class); UUID appSpecificInternalDirUuid = storageManager.getUuidForPath(getFilesDir()); long availableBytes = storageManager.getAllocatableBytes(appSpecificInternalDirUuid); if (availableBytes >= NUM_BYTES_NEEDED_FOR_MY_APP) { storageManager.allocateBytes( appSpecificInternalDirUuid, NUM_BYTES_NEEDED_FOR_MY_APP); } else { // To request that the user remove all app cache files instead, set // "action" to ACTION_CLEAR_APP_CACHE. Intent storageIntent = new Intent(); storageIntent.setAction(ACTION_MANAGE_STORAGE); }
สร้างกิจกรรมการจัดการพื้นที่เก็บข้อมูล
แอปสามารถประกาศและสร้างกิจกรรมที่กําหนดเอง ซึ่งเมื่อเปิดใช้งานแล้ว จะช่วยให้ผู้ใช้จัดการข้อมูลที่แอปจัดเก็บไว้ในอุปกรณ์ของผู้ใช้ได้ คุณสามารถประกาศกิจกรรม "จัดการพื้นที่ทำงาน" ที่กําหนดเองนี้โดยใช้แอตทริบิวต์ android:manageSpaceActivity
ในไฟล์ Manifest แอปจัดการไฟล์สามารถเรียกใช้กิจกรรมนี้ได้แม้ว่าแอปของคุณจะไม่ส่งออกกิจกรรมก็ตาม กล่าวคือ เมื่อกิจกรรมตั้งค่า android:exported
เป็น false
ขอให้ผู้ใช้นำไฟล์บางรายการออกจากอุปกรณ์
หากต้องการขอให้ผู้ใช้เลือกไฟล์ในอุปกรณ์ที่จะนำออก ให้เรียกใช้ Intent ที่มีการดำเนินการ ACTION_MANAGE_STORAGE
Intent นี้จะแสดงข้อความแจ้งต่อผู้ใช้ โดยพรอมต์นี้จะแสดงปริมาณพื้นที่ว่างในอุปกรณ์ได้หากต้องการ หากต้องการแสดงข้อมูลนี้ที่ใช้งานง่าย ให้ใช้ผลลัพธ์ของการคำนวณต่อไปนี้
StorageStatsManager.getFreeBytes() / StorageStatsManager.getTotalBytes()
ขอให้ผู้ใช้นำไฟล์แคชทั้งหมดออก
หรือจะขอให้ผู้ใช้ล้างไฟล์แคชจากแอปทั้งหมดในอุปกรณ์ก็ได้ โดยเรียกใช้ Intent ที่มีการดำเนินการของ Intent ACTION_CLEAR_APP_CACHE
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกไฟล์ลงในพื้นที่เก็บข้อมูลของอุปกรณ์ได้ที่แหล่งข้อมูลต่อไปนี้