Apakah ada cara universal untuk menemukan lokasi kartu SD eksternal?
Tolong, jangan bingung dengan Penyimpanan Eksternal .
Environment.getExternalStorageState()
mengembalikan path ke titik mount SD internal, seperti "/ mnt / sdcard". Tetapi pertanyaannya adalah tentang SD eksternal. Bagaimana cara mendapatkan jalur seperti "/ mnt / sdcard / external_sd" (ini mungkin berbeda dari perangkat ke perangkat)?
Saya kira saya akan mengakhiri dengan memfilter output dari mount
perintah dengan nama filesystem. Tapi saya tidak yakin cara ini cukup kuat.
Jawaban:
Tidak,
Environment.getExternalStorageDirectory()
mengacu pada apa pun yang oleh produsen perangkat dianggap sebagai "penyimpanan eksternal". Pada beberapa perangkat, ini adalah media yang dapat dilepas, seperti kartu SD. Pada beberapa perangkat, ini adalah sebagian dari flash pada perangkat. Di sini, "penyimpanan eksternal" berarti "barang-barang yang dapat diakses melalui mode Penyimpanan Massal USB ketika dipasang pada mesin host", setidaknya untuk Android 1.x dan 2.x.Android tidak memiliki konsep "SD eksternal", selain dari penyimpanan eksternal, seperti dijelaskan di atas.
Jika pabrikan perangkat telah memilih untuk memiliki penyimpanan eksternal menjadi flash on-board dan juga memiliki kartu SD, Anda harus menghubungi pabrikan itu untuk menentukan apakah Anda dapat menggunakan kartu SD (tidak dijamin) dan apa aturannya untuk menggunakannya, seperti jalur apa yang digunakan untuk itu.
MEMPERBARUI
Dua hal terbaru yang perlu diperhatikan:
Pertama, pada Android 4.4+, Anda tidak memiliki akses tulis ke media yang dapat dipindahkan (mis., "SD eksternal"), kecuali untuk lokasi mana pun di media yang mungkin dikembalikan oleh
getExternalFilesDirs()
dangetExternalCacheDirs()
. Lihat analisis luar biasa Dave Smith mengenai hal ini, terutama jika Anda menginginkan detail tingkat rendah.Kedua, jangan sampai ada orang yang berdalih tentang apakah akses media yang dapat dilepas atau tidak merupakan bagian dari Android SDK, di sini adalah penilaian Dianne Hackborn :
sumber
Saya datang dengan solusi berikut berdasarkan beberapa jawaban yang ditemukan di sini.
KODE:
PEMAKAIAN:
sumber
Saya memiliki aplikasi yang menggunakan
ListPreference
tempat pengguna diminta untuk memilih lokasi tempat mereka ingin menyimpan sesuatu.Dalam aplikasi itu, saya memindai
/proc/mounts
dan/system/etc/vold.fstab
untuk mount point sdcard. Saya menyimpan poin mount dari setiap file menjadi dua yang terpisahArrayList
s .Kemudian, saya membandingkan satu daftar dengan yang lain dan membuang barang-barang yang tidak ada di kedua daftar. Itu memberi saya daftar jalur root untuk setiap sdcard.
Dari sana, saya diuji jalan dengan
File.exists()
,File.isDirectory()
, danFile.canWrite()
. Jika salah satu dari tes itu salah, saya membuang jalur itu dari daftar.Apa pun yang tersisa dalam daftar, saya mengkonversi ke
String[]
array sehingga dapat digunakan olehListPreference
atribut nilai.Anda dapat melihat kode di sini: http://sapienmobile.com/?p=204
sumber
Anda dapat mencoba menggunakan fungsi pustaka dukungan yang disebut ContextCompat.getExternalFilesDirs () :
Yang pertama adalah penyimpanan eksternal utama, dan sisanya seharusnya menjadi jalur SD-card nyata.
Alasan untuk beberapa ".getParentFile ()" adalah untuk naik folder lain, karena jalur aslinya adalah
EDIT: inilah cara yang lebih komprehensif yang saya buat, untuk mendapatkan jalur sd-card:
sumber
App
,ContextCompact
,EnvironmentCompact
Untuk mengambil semua Penyimpanan Eksternal (apakah itu kartu SD atau penyimpanan internal yang tidak dapat dilepas ), Anda dapat menggunakan kode berikut:
Atau, Anda dapat menggunakan System.getenv ("EXTERNAL_STORAGE") untuk mengambil direktori Penyimpanan Eksternal utama (mis. "/ Storage / sdcard0" ) dan System.getenv ("SECONDARY_STORAGE") untuk menerima daftar semua direktori sekunder (mis. " / storage / extSdCard: / storage / UsbDriveA: / storage / UsbDriveB " ). Ingat bahwa, juga dalam hal ini, Anda mungkin ingin memfilter daftar direktori sekunder untuk mengecualikan drive USB.
Bagaimanapun, harap dicatat bahwa menggunakan jalur kode-keras selalu merupakan pendekatan yang buruk (khususnya ketika setiap produsen dapat mengubahnya sesuka hati).
sumber
System.getenv("SECONDARY_STORAGE")
juga bisa dilakukan dengan beberapa referensi, karena tampaknya tidak berdokumen./mnt
sana bisa ada berbagai pohon fs lainnya, juga, tidak hanya kartu SD dan drive USB. Kode Anda juga akan mencantumkan mount sistem file internal (bahkan mungkin virtual), jika saya memahaminya dengan benar, sementara pertanyaannya hanya menginginkan kartu sd saja .Seperti Richard, saya juga menggunakan file / proc / mounts untuk mendapatkan daftar opsi penyimpanan yang tersedia
sumber
printStackTrace
? Kapan kita punyaandroid.util.Log.e
?Hal ini dimungkinkan untuk menemukan di mana kartu SD tambahan yang dipasang dengan membaca
/proc/mounts
(file standar Linux) dan cross-checking terhadap vold data (/system/etc/vold.conf
). Dan perhatikan, bahwa lokasi yang dikembalikan olehEnvironment.getExternalStorageDirectory()
mungkin tidak muncul dalam konfigurasi yang lama (di beberapa perangkat penyimpanan internal yang tidak dapat dilepas), tetapi masih harus dimasukkan dalam daftar. Namun kami tidak menemukan cara yang baik untuk menggambarkannya kepada pengguna .sumber
mount
lebih kompatibel daripada membaca/proc
filesystem. Masalahnya adalah kartu SD tidak perlu diformat sebagai FAT. Selain itu, titik pemasangan kartu dapat bervariasi dari ROM ke ROM. Juga, mungkin ada beberapa partisi VFAT lainnya ...mount
executable, terutama karena launchable executable tidak disarankan.Saya mencoba semua solusi di dalam topik ini saat ini. Tetapi semuanya tidak bekerja dengan benar pada perangkat dengan satu kartu eksternal (dapat dilepas) dan satu kartu internal (tidak dapat dilepas). Jalur kartu eksternal tidak mungkin diperoleh dari perintah 'mount', dari file 'proc / mounts' dll.
Dan saya membuat solusi saya sendiri (di Paulo Luan):
sumber
Jika Anda melihat kode sumber untuk
android.os.Environment
Anda akan melihat bahwa Android sangat bergantung pada variabel lingkungan untuk jalur. Anda dapat menggunakan variabel lingkungan "SECONDARY_STORAGE" untuk menemukan jalur ke kartu sd yang dapat dilepas.Contoh penggunaan:
sumber
Cukup gunakan ini:
sumber
SECONDARY_STORAGE
memiliki beberapa jalur yang dipisahkan dengan titik dua (":"). Inilah sebabnya saya membagi String (lihat jawaban saya di atas).Secara universal , jika Anda maksud dengan cara resmi; ya ada satu.
Dalam API level 19 yaitu dalam versi Android 4.4 Kitkat, mereka telah menambahkan
File[] getExternalFilesDirs (String type)
diContext
Kelas yang memungkinkan aplikasi untuk menyimpan data / file dalam kartu micro SD.Android 4.4 adalah rilis pertama dari platform yang sebenarnya memungkinkan aplikasi untuk menggunakan kartu SD untuk penyimpanan. Setiap akses ke kartu SD sebelum API level 19 adalah melalui API pribadi yang tidak didukung.
getExternalFilesDirs (tipe String) mengembalikan jalur absolut ke direktori khusus aplikasi di semua perangkat penyimpanan bersama / eksternal. Ini berarti, itu akan mengembalikan jalur ke memori internal dan eksternal. Umumnya, jalur balik kedua balik penyimpanan untuk kartu microSD (jika ada).
Tapi perhatikan itu,
Terminologi Penyimpanan Internal dan Eksternal menurut Google / dokumen Android resmi sangat berbeda dari yang kami pikirkan.
sumber
getExternalFilesDirs()
sering mengembalikan kartu SD yang tidak dapat dilepas, jadi tidak, ini bukan cara universal untuk menemukan lokasi kartu SD yang dapat dilepas.Inilah cara yang saya gunakan untuk menemukan kartu eksternal. Gunakan mount cmd return lalu parsing bagian vfat.
sumber
Solusi ini menangani kenyataan itu
System.getenv("SECONDARY_STORAGE")
tidak ada gunanya dengan Marshmallow.Diuji dan bekerja pada:
Samsung Galaxy Tab A (Android 6.0.1 - Stock)
sumber
Karena jawaban asli saya di atas, pemindaian vold tidak lagi dapat digunakan di berbagai produsen.
Saya telah mengembangkan metode yang lebih andal dan lurus ke depan.
root akan berisi semua direktori root yang dapat ditulis pada sistem, termasuk semua perangkat usb yang terhubung.
CATATAN: Metode canWrite membutuhkan izin android.permission.WRITE_EXTERNAL_STORAGE.
sumber
/external_sd
adalah kartu microSD eksternal; pada beberapa Pemda, itu/_ExternalSD
; pada beberapa perangkat itu/sdcard
. Mungkin yang terakhir adalah symlink ke/storage/sdcard0
atau serupa, tetapi akankah orang lain ini benar-benar dilindungi oleh/storage/*
dan/mount/*
?pathname.canWrite()
dan meminta izin WRITE_EXTERNAL_STORAGE? Kenapa tidak telepon sajapathname.canRead()
?sudah sangat terlambat tetapi akhirnya saya mendapatkan sesuatu yang telah saya uji sebagian besar perangkat (oleh produsen dan versi android) yang bekerja pada Android 2.2+. jika ternyata tidak berfungsi, beri komentar dengan nama perangkat Anda. saya akan memperbaikinya. kalau ada yang tertarik saya akan menjelaskan cara kerjanya.
sumber
Dengan menulis kode di bawah ini Anda akan mendapatkan lokasi:
/ storage / 663D-554E / Android / data / app_package_name / file /
yang menyimpan data aplikasi Anda di / android / lokasi data di dalam sd_card.
Saya telah menguji kode ini pada moto g4 plus dan perangkat Samsung (semuanya berfungsi dengan baik).
Semoga ini bisa membantu.
sumber
Berikut adalah metode yang saya gunakan untuk menemukan yang dapat dilepas kartu SD yang . Ini rumit, dan mungkin berlebihan untuk beberapa situasi, tetapi bekerja pada berbagai versi Android dan produsen perangkat yang telah saya uji selama beberapa tahun terakhir. Saya tidak tahu perangkat apa pun karena API level 15 yang tidak menemukan kartu SD, jika ada yang terpasang. Dalam kebanyakan kasus, itu tidak akan menghasilkan positif palsu, terutama jika Anda memberikannya nama file yang dikenal untuk dicari.
Tolong beri tahu saya jika Anda mengalami kasus yang tidak berfungsi.
PS
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
di manifes. Dan pada API level 23 dan lebih tinggi, pastikan untuk menggunakancheckSelfPermission
/requestPermissions
.findSdCardPath(),
daripada menghitung ulang setiap kali Anda membutuhkannya.Log.d()
) dalam kode di atas. Ini membantu mendiagnosis setiap kasus di mana jalan yang benar tidak ditemukan. Beri komentar jika Anda tidak ingin masuk.sumber
Satu-satunya solusi yang saya temukan adalah yang menggunakan refleksi
sumber
Saya tidak tahu mengapa tetapi saya harus memanggil .createNewFile () pada File yang dibuat di direktori penyimpanan publik sebelum menggunakannya. Dalam kerangka komentar untuk metode itu mengatakan itu tidak berguna. Ini contohnya ...
sumber
Saya telah membuat metode utils untuk memeriksa kartu SD tersedia pada perangkat atau tidak, dan mendapatkan jalur kartu SD pada perangkat jika tersedia.
Anda dapat menyalin 2 metode di bawah ini ke kelas proyek yang Anda butuhkan. Itu saja.
sumber
Ini berfungsi untuk semua perangkat eksternal, tetapi pastikan hanya mendapatkan nama folder perangkat eksternal dan kemudian Anda perlu mendapatkan file dari lokasi yang diberikan menggunakan kelas File.
Panggilan:
Mendapatkan akses ke penyimpanan eksternal
Untuk membaca atau menulis file pada penyimpanan eksternal, aplikasi Anda harus memperoleh izin sistem READ_EXTERNAL_STORAGE atau WRITE_EXTERNAL_STORAGE . Sebagai contoh:
sumber
/ sdcard => Penyimpanan Internal (Ini adalah symlink tetapi harusnya berfungsi)
/ mnt / extSdCard => Sdcard Eksternal
Ini untuk Samsung Galaxy S3
Anda mungkin dapat mengandalkan ini menjadi kenyataan bagi sebagian besar ... namun periksa!
sumber
/sdcard
adalah symlink ke eksternal pada sony