ความแตกต่างระหว่าง getExternalFilesDir และ getExternalStorageDirectory ()


90

ฉันเข้าใจว่าต้องใช้ ExternalFiles บน API 8 ขึ้นไปและ getExternalStorageDirectory ใช้สำหรับ 7 และลง อย่างไรก็ตามฉันสับสนเล็กน้อยระหว่างการใช้งาน ตัวอย่างเช่นฉันต้องการตรวจสอบว่าโฟลเดอร์ที่มีอยู่และก่อนหน้านี้คุณจะใช้สิ่งต่างๆเช่น:

File ChildFolder = new File(Environment.getExternalStorageDirectory() + "/ParentFolder/Child");

อย่างไรก็ตามทุกตัวอย่างที่ฉันเห็นบอกว่าให้ใช้ getExternalFilesDir (null), File.ext เนื่องจากฉันอยู่เหนือ API 8 ฉันจึงต้องการใช้วิธีนี้ แต่ฉันจะตรวจสอบโฟลเดอร์ได้อย่างไร ฉันจะตรวจสอบว่ามีไฟล์อยู่ที่จุดอื่น แต่ตอนนี้ต้องการดูว่ามีโฟลเดอร์อยู่หรือไม่?

คำตอบ:


133
getExternalFilesDir()

จะคืนเส้นทางไปยังโฟลเดอร์ไฟล์ภายในAndroid / data / data / your_package /บนการ์ด SD ของคุณ ใช้เพื่อจัดเก็บไฟล์ที่จำเป็นสำหรับแอปของคุณ (เช่นภาพที่ดาวน์โหลดจากเว็บหรือไฟล์แคช) เมื่อถอนการติดตั้งแอปแล้วข้อมูลที่เก็บไว้ในโฟลเดอร์นี้ก็จะหายไปด้วย

getExternalStorageDirectory()

จะส่งคืนเส้นทางรากไปยังการ์ด SD ของคุณ (เช่นmnt / sdcard / ) หากคุณบันทึกข้อมูลบนเส้นทางนี้และถอนการติดตั้งแอปข้อมูลนั้นจะไม่สูญหาย


4
Google Android ต้องการให้คุณใช้ทุกอย่างที่มีให้ภายในกรอบงาน ดังนั้นจึงขึ้นอยู่กับความต้องการทางเลือกและการออกแบบของคุณ หากคุณไม่ต้องการให้ไฟล์ค้างอยู่เมื่อถอนการติดตั้งแอปคุณควรใช้getExternalFilesDir ()หรือgetExternalCacheDir ()
waqaslam

5
เพราะใน API 8 พวกเขาแนะนำคุณสมบัติสื่อสแกนเนอร์ขั้นสูงซึ่งจะช่วยให้การสแกนข้อมูลจากโฟลเดอร์เช่นเพลง, ภาพ, เสียงเรียกเข้า, ฯลฯ ไดเรกทอรีเหล่านั้นจะถูกสร้างขึ้นโดยอัตโนมัติเท่านั้นถ้าคุณใช้getExternalFilesDir () ตั้งแต่ตอนนี้คุณลักษณะนี้ไม่สามารถใช้ได้ใน API 7 ที่ว่าทำไมพวกเขาแนะนำให้ใช้getExternalStorageDirectory () ง่ายๆ ...
waqaslam

2
ไม่เป็นไรให้เวลาเร็ว ๆ นี้จะมีช่วงเวลายูเรก้า :)
waqaslam

3
มันเป็นสิ่งสำคัญที่จะรู้ว่าgetExternalStorageDirectory()ไม่ไม่จำเป็นต้อง - แม้กระทั่งไม่ปกติ - "เส้นทางไปยัง SD card ของคุณ" กลับ แต่จะส่งคืน "ไดเร็กทอรีหน่วยเก็บข้อมูลภายนอกหลัก" แทน เอกสาร ( developer.android.com/reference/android/os/… ) พูดว่า:
LarsH

2
'หมายเหตุ: อย่าสับสนกับคำว่า "ภายนอก" ที่นี่ ไดเร็กทอรีนี้สามารถคิดเป็นสื่อ / พื้นที่เก็บข้อมูลที่ใช้ร่วมกันได้ดีกว่า เป็นระบบไฟล์ที่สามารถเก็บข้อมูลได้จำนวนมากและใช้ร่วมกันในทุกแอปพลิเคชัน (ไม่บังคับใช้สิทธิ์) ตามเนื้อผ้านี่คือการ์ด SDแต่อาจใช้เป็นที่เก็บข้อมูลในตัวในอุปกรณ์ที่แตกต่างจากที่จัดเก็บข้อมูลภายในที่มีการป้องกันและสามารถติดตั้งเป็นระบบไฟล์บนคอมพิวเตอร์ได้ '
LarsH

70

ก่อนอื่นเราต้องเข้าใจว่าความแตกต่างระหว่าง Internal Storage, External Storage (aka Primary External Storage) และ Secondary External Storage คืออะไร?

ที่เก็บข้อมูลภายใน:คือที่เก็บข้อมูลที่ผู้ใช้ไม่สามารถเข้าถึงได้ยกเว้นผ่านแอพที่ติดตั้ง (หรือโดยการรูทอุปกรณ์) ตัวอย่าง: data / data / app_packageName

ที่จัดเก็บข้อมูลภายนอกหลัก:ในที่เก็บข้อมูลที่ใช้ร่วมกันในตัวซึ่ง "ผู้ใช้สามารถเข้าถึงได้โดยการเสียบสาย USB และติดตั้งเป็นไดรฟ์บนคอมพิวเตอร์โฮสต์" ตัวอย่าง: เมื่อเราพูดว่า Nexus 5 32 GB

ที่เก็บข้อมูลภายนอกสำรอง: ที่เก็บข้อมูลแบบถอดได้ ตัวอย่าง: การ์ด SD

getExternalFilesDir (String type)

ส่งคืนเส้นทางไปยังโฟลเดอร์ไฟล์ภายใน Android / data / data / your_package / บนที่เก็บข้อมูลภายนอกหลัก ซึ่งเป็นที่เก็บข้อมูลในตัว.

Environment.getExternalStorageDirectory(type)

มันจะส่งคืนเส้นทางของไดเร็กทอรีหน่วยเก็บข้อมูลภายนอกสำรอง


ขอขอบคุณที่อธิบายประเภทต่างๆของพื้นที่เก็บข้อมูล อย่างไรก็ตามอาจแก้ไขรายการที่เก็บข้อมูลภายในเพื่อระบุว่าการเรียกใช้เมธอดเพื่อรับค่านั้นคือ getFilesDir () ฉันเดาว่าวิธีนั้นส่งคืน data / data / app_packageName / files จริง ๆ แต่ยังคงเป็นที่เก็บข้อมูลภายใน
raddevus

3
@VicJordan Please write about File getExternalStoragePublicDirectory (String type)and File getFilesDir ()as well
AnV

2
ขอบคุณ Vic Environment.getExternalStorageDirectory () เอาต์พุต / storage / จำลอง / 0
gimmegimme

คุณมีเอกสารประกอบสำหรับข้อความว่าที่เก็บข้อมูลภายนอกหลักอยู่ในตัวตลอดเวลาในขณะที่หน่วยความจำสำรองสามารถถอดออกได้เสมอหรือไม่? ฉันคิดว่าปัญหาเหล่านี้เป็นปัญหาที่เกิดขึ้นเอง ... โทรศัพท์บางรุ่นไม่มีที่เก็บข้อมูล "ภายนอก" ในตัวซึ่งในกรณีนี้ที่จัดเก็บข้อมูลภายนอกหลักอาจเป็นการ์ด SD แบบถอดได้
LarsH

@LarsH ตามความรู้ของฉันในขณะนี้ไม่มีโทรศัพท์ในตลาดหรือในอนาคตอันใกล้ซึ่งจะไม่มีที่เก็บข้อมูลภายนอกหลักในตัว มีโทรศัพท์ในช่วงเวลาของขนมปังขิงเมื่อโทรศัพท์ดังกล่าวมีอยู่ แต่ไม่ใช่ตอนนี้ คุณช่วยตั้งชื่อโทรศัพท์ "บางรุ่น" ที่ไม่มี "ที่เก็บข้อมูลภายนอกหลัก" ในตัวได้ไหม
Vikasdeep Singh

18

! การปรับปรุงที่สำคัญ!สำหรับใครก็ตามที่เจอคำถามนี้

เนื่องจากเป็นคำถามที่ค่อนข้างเก่าเพียงต้องการให้ข้อมูลเพิ่มเติม เนื่องจาก KitKat แม้แต่แอปที่ได้รับอนุญาตWRITE_EXTERNAL_STORAGEจะได้รับอนุญาตให้เขียนไปยังAndroid / data / data / your_package /บนที่จัดเก็บข้อมูลภายนอกaka getExternalFilesDir()

หากคุณจะพยายามเขียนถึงgetExternalStorageDirectory() + "/somefolder/anotherfolder/"คุณจะได้รับ SecurityException บนอุปกรณ์ส่วนใหญ่


9
ตามเอกสารแอปที่มีสิทธิ์ WRITE_EXTERNAL_STORAGE สามารถเขียนไปยังที่จัดเก็บข้อมูลภายนอกของแพ็คเกจอื่น ๆ ได้ไม่ใช่เฉพาะของตัวเอง เป็นแอปที่ไม่ได้รับอนุญาตให้เขียนลงในไดเร็กทอรีของตนเองได้เท่านั้น: developer.android.com/reference/android/content/… "เริ่มใน KITKAT ไม่จำเป็นต้องมีสิทธิ์ในการอ่านหรือเขียนไปยังเส้นทางที่ส่งคืนเสมอไป เข้าถึงแอปการโทร ... ในการเข้าถึงเส้นทางที่เป็นของแพ็คเกจอื่นต้องใช้ WRITE_EXTERNAL_STORAGE และ / หรือ READ_EXTERNAL_STORAGE "
Oded

นี่คือจุดที่ "บนอุปกรณ์ส่วนใหญ่" เริ่มมีความสำคัญในขณะที่เอกสาร Android กำหนดแนวคิดทั่วไป แต่บางครั้งผู้ผลิตก็มีสิ่งต่างๆเช่น InternalStorage (ที่เก็บข้อมูลในตัวสำหรับข้อมูลแอป), ExternalStorage-Primary (ที่เก็บข้อมูลในตัวที่มีขอบเขตการเข้าถึงที่ใหญ่กว่า) และ ExternalStorage-Secondary (สิ่งนี้จะติดตั้งเช่นการ์ด SD) ตอนนี้คุณสามารถเดาได้ว่าเส้นทางใดที่จะได้รับผลตอบแทนจากExternal StorageDirectory
SGal

7
นั่นไม่ได้ระบุข้อมูลที่ไม่ถูกต้องในคำตอบของคุณ "เนื่องจาก KitKat แม้แต่แอปที่ได้รับอนุญาต WRITE_EXTERNAL_STORAGE จะได้รับอนุญาตให้เขียนลงใน Android / data / data / your_package / บนที่จัดเก็บข้อมูลภายนอกหรือที่เรียกว่า getExternalFilesDir ()" ตามเอกสารนี้ไม่ถูกต้อง ด้วย WRITE_EXTERNAL_STORAGE แอปสามารถเขียนไปยังที่จัดเก็บข้อมูลภายนอกทั้งหมด
Oded

1
@ คุณได้ทดสอบสิ่งนี้หรือไม่? ความเข้าใจของฉันเกี่ยวกับเอกสารและประสบการณ์ของฉันกับ KitKat และอุปกรณ์ที่ใหม่กว่านั้นแตกต่างจากของคุณ (หวังว่าฉันจะมีเวลาแฮชรายละเอียดทั้งหมดตอนนี้อาจจะช้ากว่านี้) ประสบการณ์ของฉันคือ SGal ถูก นอกจากนี้ยังมี Lollipop ซึ่งแตกต่างกันเล็กน้อย
LarsH

2
คำตอบนี้เป็นเท็จอย่างชัดเจนตามเอกสารของ Android โปรดดูdeveloper.android.com/reference/android/… "ตั้งแต่ระดับ API 19 การอนุญาตนี้ไม่จำเป็นต้องอ่าน / เขียนไฟล์ในไดเร็กทอรีเฉพาะแอปพลิเคชันของคุณที่ส่งคืนโดย getExternalFilesDir (String) และ getExternalCacheDir ()" (โปรดทราบว่า API ระดับ 19 = KitKat) ไม่รู้ว่ามันได้รับคะแนนโหวตมากขนาดนี้ได้อย่างไร
Ajedi32

7

!! สำคัญ !!

Environment.getExternalStorageDirectory()จะเลิกและบริบท # getExternalFilesDir (String) MediaStore หรือเจตนา # ACTION_OPEN_DOCUMENT ควรจะนำมาใช้แทน

วิธีนี้เลิกใช้แล้วใน API ระดับ 29 เพื่อปรับปรุงความเป็นส่วนตัวของผู้ใช้การเข้าถึงโดยตรงไปยังอุปกรณ์จัดเก็บข้อมูลที่ใช้ร่วมกัน / ภายนอกจะถูกเลิกใช้ เมื่อแอปกำหนดเป้าหมาย Build.VERSION_CODES.Q เส้นทางที่ส่งกลับจากวิธีนี้จะไม่สามารถเข้าถึงแอปได้โดยตรงอีกต่อไป แอปสามารถเข้าถึงเนื้อหาที่จัดเก็บในที่จัดเก็บข้อมูลที่ใช้ร่วมกัน / ภายนอกต่อไปได้โดยการย้ายไปยังทางเลือกอื่นเช่น Context # getExternalFilesDir (String), MediaStore หรือ Intent # ACTION_OPEN_DOCUMENT

https://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory ()

นอกจากนี้ยังเริ่มต้นจากนักพัฒนา Android.M ต้องขอสิทธิ์ในขณะทำงาน

ดูรายละเอียดเพิ่มเติมในเอกสารที่นี่และคำถามนี้

Environment.getExternalStorageDirectory () เลิกใช้งานใน API ระดับ 29 java


หากใครกำลังมองหาลิงก์ stack overflow และไม่ใช่สิ่งที่ copy มาจาก google docs ดูได้ที่นี่stackoverflow.com/questions/57116335/…
Rowan Berry

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