Samsung Galaxy S3 에는 외부 SD 카드 슬롯이 /mnt/extSdCard
있습니다.
이 경로를 어떻게 얻을 수 Environment.getExternalStorageDirectory()
있습니까?
이 반환 mnt/sdcard
되고 외부 SD 카드에 대한 API를 찾을 수 없습니다. (또는 일부 태블릿의 이동식 USB 저장소.)
Samsung Galaxy S3 에는 외부 SD 카드 슬롯이 /mnt/extSdCard
있습니다.
이 경로를 어떻게 얻을 수 Environment.getExternalStorageDirectory()
있습니까?
이 반환 mnt/sdcard
되고 외부 SD 카드에 대한 API를 찾을 수 없습니다. (또는 일부 태블릿의 이동식 USB 저장소.)
답변:
public static HashSet<String> getExternalMounts() {
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
}
원래 방법을 테스트하고
테스트를 받았을 때 어떤 안드로이드 버전이 있었는지 잘 모르겠습니다.
수정 된 버전을 다음으로 테스트했습니다.
주 저장소로 sdcard를 사용하는 일부 단일 저장 장치
Incredible을 제외하고 이러한 모든 장치는 이동식 저장소 만 반환했습니다. 내가해야 할 몇 가지 추가 검사가있을 수 있지만 지금까지 찾은 솔루션보다 적어도 조금 더 낫습니다.
시스템의 모든 SD 카드에 대한 경로를 얻는 더 안정적인 방법을 찾았습니다. 이는 모든 Android 버전에서 작동하며 모든 저장소 (에뮬레이션 포함)에 대한 경로를 반환합니다.
내 모든 장치에서 올바르게 작동합니다.
PS : 환경 클래스의 소스 코드를 기반으로합니다.
private static final Pattern DIR_SEPORATOR = Pattern.compile("/");
/**
* Raturns all available SD-Cards in the system (include emulated)
*
* Warning: Hack! Based on Android source code of version 4.3 (API 18)
* Because there is no standart way to get it.
* TODO: Test on future Android versions 4.4+
*
* @return paths to all available SD-Cards in the system (include emulated)
*/
public static String[] getStorageDirectories()
{
// Final set of paths
final Set<String> rv = new HashSet<String>();
// Primary physical SD-CARD (not emulated)
final String rawExternalStorage = System.getenv("EXTERNAL_STORAGE");
// All Secondary SD-CARDs (all exclude primary) separated by ":"
final String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
// Primary emulated SD-CARD
final String rawEmulatedStorageTarget = System.getenv("EMULATED_STORAGE_TARGET");
if(TextUtils.isEmpty(rawEmulatedStorageTarget))
{
// Device has physical external storage; use plain paths.
if(TextUtils.isEmpty(rawExternalStorage))
{
// EXTERNAL_STORAGE undefined; falling back to default.
rv.add("/storage/sdcard0");
}
else
{
rv.add(rawExternalStorage);
}
}
else
{
// Device has emulated storage; external storage paths should have
// userId burned into them.
final String rawUserId;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
{
rawUserId = "";
}
else
{
final String path = Environment.getExternalStorageDirectory().getAbsolutePath();
final String[] folders = DIR_SEPORATOR.split(path);
final String lastFolder = folders[folders.length - 1];
boolean isDigit = false;
try
{
Integer.valueOf(lastFolder);
isDigit = true;
}
catch(NumberFormatException ignored)
{
}
rawUserId = isDigit ? lastFolder : "";
}
// /storage/emulated/0[1,2,...]
if(TextUtils.isEmpty(rawUserId))
{
rv.add(rawEmulatedStorageTarget);
}
else
{
rv.add(rawEmulatedStorageTarget + File.separator + rawUserId);
}
}
// Add all secondary storages
if(!TextUtils.isEmpty(rawSecondaryStoragesStr))
{
// All Secondary SD-CARDs splited into array
final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
Collections.addAll(rv, rawSecondaryStorages);
}
return rv.toArray(new String[rv.size()]);
}
Pattern
에 대한/
System.getenv("SECONDARY_STORAGE")
반환 /storage/sdcard1
. 해당 위치는 존재하지 않지만 실제 위치는입니다 /storage/42CE-FD0A
. 여기서 42CE-FD0A는 포맷 된 파티션의 볼륨 일련 번호입니다.
나는 이것을 사용해야하는 외부 sdcard를 사용한다고 생각합니다.
new File("/mnt/external_sd/")
또는
new File("/mnt/extSdCard/")
당신의 경우에는 ...
대신 Environment.getExternalStorageDirectory()
나를 위해 작동합니다. 먼저 mnt 디렉토리에있는 내용을 확인하고 거기에서 작업해야합니다.
사용할 sdcard를 선택하려면 몇 가지 유형의 선택 방법을 사용해야합니다.
File storageDir = new File("/mnt/");
if(storageDir.isDirectory()){
String[] dirList = storageDir.list();
//TODO some type of selecton method?
}
모든 외부 저장소 ( SD 카드 또는 내부 비 이동식 저장소 )를 검색하려면 다음 코드를 사용할 수 있습니다.
final String state = Environment.getExternalStorageState();
if ( Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state) ) { // we can read the External Storage...
//Retrieve the primary External Storage:
final File primaryExternalStorage = Environment.getExternalStorageDirectory();
//Retrieve the External Storages root directory:
final String externalStorageRootDir;
if ( (externalStorageRootDir = primaryExternalStorage.getParent()) == null ) { // no parent...
Log.d(TAG, "External Storage: " + primaryExternalStorage + "\n");
}
else {
final File externalStorageRoot = new File( externalStorageRootDir );
final File[] files = externalStorageRoot.listFiles();
for ( final File file : files ) {
if ( file.isDirectory() && file.canRead() && (file.listFiles().length > 0) ) { // it is a real directory (not a USB drive)...
Log.d(TAG, "External Storage: " + file.getAbsolutePath() + "\n");
}
}
}
}
또는 System.getenv ( "EXTERNAL_STORAGE") 를 사용하여 기본 외부 저장소 디렉터리 (예 : "/ storage / sdcard0" )를 검색하고 System.getenv ( "SECONDARY_STORAGE") 를 사용하여 모든 보조 디렉터리 목록 (예 : " / storage / extSdCard : / storage / UsbDriveA : / storage / UsbDriveB " ). 이 경우에도 USB 드라이브를 제외하기 위해 보조 디렉토리 목록을 필터링 할 수 있습니다.
어쨌든 하드 코딩 된 경로를 사용하는 것은 항상 잘못된 접근 방식입니다 (특히 모든 제조업체가 원하는대로 변경할 수있는 경우).
Asus Zenfone2 , Marshmallow 6.0.1 을 확인하고 솔루션이 작동하지 않을 때까지 Dmitriy Lozenko 의 솔루션 을 사용 하고있었습니다. EMULATED_STORAGE_TARGET , 특히 microSD 경로 (예 : / storage / F99C-10F4 /)를 가져올 때 솔루션이 실패했습니다 . 에뮬레이트 된 애플리케이션 경로에서 직접 에뮬레이트 된 루트 경로를 가져 오고 더 알려진 전화 모델 별 물리적 경로를 추가 하도록 코드를 편집했습니다 .context.getExternalFilesDirs(null);
우리의 삶을 더 쉽게 만들기 위해 여기 에 도서관을 만들었습니다 . gradle, maven, sbt 및 leiningen 빌드 시스템을 통해 사용할 수 있습니다.
구식 방식이 마음에 들면 여기 에서 직접 파일을 복사하여 붙여 넣을 수도 있지만 수동으로 확인하지 않고는 향후 업데이트가 있는지 알 수 없습니다.
질문이나 제안 사항이 있으면 알려주십시오.
context.getExternalFilesDirs(null)
반환 null
되고 다음 루프에서 예외가 발생합니다. if (file == null) continue;
루프의 첫 번째 줄로 추가하는 것이 좋습니다 .
좋은 소식! KitKat에는 이제 이러한 보조 공유 저장 장치와 상호 작용하기위한 공용 API가 있습니다.
새로운 Context.getExternalFilesDirs()
및 Context.getExternalCacheDirs()
메서드는 기본 및 보조 장치를 포함하여 여러 경로를 반환 할 수 있습니다. 그런 다음 파일을 반복하고 파일을 저장할 최적의 위치를 확인 Environment.getStorageState()
하고 File.getFreeSpace()
결정할 수 있습니다. 이러한 메서드는 ContextCompat
support-v4 라이브러리 에서도 사용할 수 있습니다.
또한에서 반환 한 디렉토리 만 사용하는 데 관심이있는 경우 Context
더 이상 READ_
또는 WRITE_EXTERNAL_STORAGE
권한이 필요하지 않습니다 . 앞으로는 추가 권한 없이도 이러한 디렉터리에 대한 읽기 / 쓰기 액세스 권한을 항상 갖게됩니다.
앱은 다음과 같이 권한 요청을 종료하여 이전 장치에서 계속 작업 할 수도 있습니다.
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
모든 외부 SD 카드에 액세스하기 위해 다음을 수행했습니다.
와:
File primaryExtSd=Environment.getExternalStorageDirectory();
기본 외부 SD에 대한 경로를 얻습니다.
File parentDir=new File(primaryExtSd.getParent());
기본 외부 저장소의 상위 디렉토리를 가져오고 모든 외부 SD의 상위 디렉토리이기도합니다. 이제 모든 저장소를 나열하고 원하는 저장소를 선택할 수 있습니다.
유용하기를 바랍니다.
SD 카드 경로 목록을 얻는 방법은 다음과 같습니다 (기본 외부 저장소 제외).
/**
* returns a list of all available sd cards paths, or null if not found.
*
* @param includePrimaryExternalStorage set to true if you wish to also include the path of the primary external storage
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static List<String> getSdCardPaths(final Context context,final boolean includePrimaryExternalStorage)
{
final File[] externalCacheDirs=ContextCompat.getExternalCacheDirs(context);
if(externalCacheDirs==null||externalCacheDirs.length==0)
return null;
if(externalCacheDirs.length==1)
{
if(externalCacheDirs[0]==null)
return null;
final String storageState=EnvironmentCompat.getStorageState(externalCacheDirs[0]);
if(!Environment.MEDIA_MOUNTED.equals(storageState))
return null;
if(!includePrimaryExternalStorage&&VERSION.SDK_INT>=VERSION_CODES.HONEYCOMB&&Environment.isExternalStorageEmulated())
return null;
}
final List<String> result=new ArrayList<>();
if(includePrimaryExternalStorage||externalCacheDirs.length==1)
result.add(getRootOfInnerSdCardFolder(externalCacheDirs[0]));
for(int i=1;i<externalCacheDirs.length;++i)
{
final File file=externalCacheDirs[i];
if(file==null)
continue;
final String storageState=EnvironmentCompat.getStorageState(file);
if(Environment.MEDIA_MOUNTED.equals(storageState))
result.add(getRootOfInnerSdCardFolder(externalCacheDirs[i]));
}
if(result.isEmpty())
return null;
return result;
}
/** Given any file/folder inside an sd card, this will return the path of the sd card */
private static String getRootOfInnerSdCardFolder(File file)
{
if(file==null)
return null;
final long totalSpace=file.getTotalSpace();
while(true)
{
final File parentFile=file.getParentFile();
if(parentFile==null||parentFile.getTotalSpace()!=totalSpace||!parentFile.canRead())
return file.getAbsolutePath();
file=parentFile;
}
}
externalCacheDirs[0].getParentFile().getParentFile().getParentFile().getParentFile().getAbsolutePath()
이것은 재난의 비결입니다. 이 작업을 수행하는 경우 원하는 경로를 하드 코딩하는 것이 좋습니다. 부모가 4 개가 아닌 다른 캐시 디렉터리를 가져 오면 NullPointerException 또는 잘못된 경로가 발생하기 때문입니다.
여러분, 특히 @SmartLemon이 제공 한 단서에 감사드립니다. 해결책을 찾았습니다. 다른 사람이 필요한 경우 여기에 최종 솔루션을 넣습니다 (첫 번째로 나열된 외부 SD 카드 찾기).
public File getExternalSDCardDirectory()
{
File innerDir = Environment.getExternalStorageDirectory();
File rootDir = innerDir.getParentFile();
File firstExtSdCard = innerDir ;
File[] files = rootDir.listFiles();
for (File file : files) {
if (file.compareTo(innerDir) != 0) {
firstExtSdCard = file;
break;
}
}
//Log.i("2", firstExtSdCard.getAbsolutePath().toString());
return firstExtSdCard;
}
외부 SD 카드가 없으면 온보드 저장소로 돌아갑니다. sdcard가 존재하지 않으면 사용하겠습니다. 변경해야 할 수도 있습니다.
내 코드를 참조하고 도움이되기를 바랍니다.
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("mount");
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
String line;
String mount = new String();
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
if (line.contains("secure")) continue;
if (line.contains("asec")) continue;
if (line.contains("fat")) {//TF card
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
mount = mount.concat("*" + columns[1] + "\n");
}
} else if (line.contains("fuse")) {//internal storage
String columns[] = line.split(" ");
if (columns != null && columns.length > 1) {
mount = mount.concat(columns[1] + "\n");
}
}
}
txtView.setText(mount);
실제로 일부 장치에서는 외부 sdcard 기본 이름이로 표시되고 extSdCard
다른 경우에는 sdcard1
.
이 코드 조각은 정확한 경로를 찾는 데 도움이되며 외부 장치의 경로를 검색하는 데 도움이됩니다.
String sdpath,sd1path,usbdiskpath,sd0path;
if(new File("/storage/extSdCard/").exists())
{
sdpath="/storage/extSdCard/";
Log.i("Sd Cardext Path",sdpath);
}
if(new File("/storage/sdcard1/").exists())
{
sd1path="/storage/sdcard1/";
Log.i("Sd Card1 Path",sd1path);
}
if(new File("/storage/usbcard1/").exists())
{
usbdiskpath="/storage/usbcard1/";
Log.i("USB Path",usbdiskpath);
}
if(new File("/storage/sdcard0/").exists())
{
sd0path="/storage/sdcard0/";
Log.i("Sd Card0 Path",sd0path);
}
예. 다른 제조업체는 Samsung Tab 3의 extsd와 같이 다른 SD 카드 이름을 사용하고 다른 삼성 장치는이 다른 제조업체가 다른 이름을 사용하는 것처럼 sdcard를 사용합니다.
나는 당신과 같은 요구 사항이있었습니다. 그래서 나는 내 프로젝트에서 당신을 위해 샘플 예제를 만들었습니다.이 링크 androi-dirchooser 라이브러리를 사용하는 Android 디렉토리 선택기 예제로 이동하십시오. 이 예에서는 SD 카드를 감지하고 모든 하위 폴더를 나열하며 기기에 SD 카드가 두 개 이상 있는지도 감지합니다.
코드의 일부는 다음과 같습니다. 전체 예제를 보려면 Android Directory Chooser 링크로 이동하십시오.
/**
* Returns the path to internal storage ex:- /storage/emulated/0
*
* @return
*/
private String getInternalDirectoryPath() {
return Environment.getExternalStorageDirectory().getAbsolutePath();
}
/**
* Returns the SDcard storage path for samsung ex:- /storage/extSdCard
*
* @return
*/
private String getSDcardDirectoryPath() {
return System.getenv("SECONDARY_STORAGE");
}
mSdcardLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
String sdCardPath;
/***
* Null check because user may click on already selected buton before selecting the folder
* And mSelectedDir may contain some wrong path like when user confirm dialog and swith back again
*/
if (mSelectedDir != null && !mSelectedDir.getAbsolutePath().contains(System.getenv("SECONDARY_STORAGE"))) {
mCurrentInternalPath = mSelectedDir.getAbsolutePath();
} else {
mCurrentInternalPath = getInternalDirectoryPath();
}
if (mCurrentSDcardPath != null) {
sdCardPath = mCurrentSDcardPath;
} else {
sdCardPath = getSDcardDirectoryPath();
}
//When there is only one SDcard
if (sdCardPath != null) {
if (!sdCardPath.contains(":")) {
updateButtonColor(STORAGE_EXTERNAL);
File dir = new File(sdCardPath);
changeDirectory(dir);
} else if (sdCardPath.contains(":")) {
//Multiple Sdcards show root folder and remove the Internal storage from that.
updateButtonColor(STORAGE_EXTERNAL);
File dir = new File("/storage");
changeDirectory(dir);
}
} else {
//In some unknown scenario at least we can list the root folder
updateButtonColor(STORAGE_EXTERNAL);
File dir = new File("/storage");
changeDirectory(dir);
}
}
});
이 솔루션 (이 질문에 대한 다른 답변에서 모아진) System.getenv("SECONDARY_STORAGE")
은 Marshmallow와 함께 사용되지 않는 사실 (@ono에서 언급 한대로)을 처리합니다 .
테스트 및 작업 :
Samsung Galaxy Tab A (Android 6.0.1-재고)
/**
* Returns all available external SD-Card roots in the system.
*
* @return paths to all available external SD-Card roots in the system.
*/
public static String[] getStorageDirectories() {
String [] storageDirectories;
String rawSecondaryStoragesStr = System.getenv("SECONDARY_STORAGE");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
List<String> results = new ArrayList<String>();
File[] externalDirs = applicationContext.getExternalFilesDirs(null);
for (File file : externalDirs) {
String path = file.getPath().split("/Android")[0];
if((Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Environment.isExternalStorageRemovable(file))
|| rawSecondaryStoragesStr != null && rawSecondaryStoragesStr.contains(path)){
results.add(path);
}
}
storageDirectories = results.toArray(new String[0]);
}else{
final Set<String> rv = new HashSet<String>();
if (!TextUtils.isEmpty(rawSecondaryStoragesStr)) {
final String[] rawSecondaryStorages = rawSecondaryStoragesStr.split(File.pathSeparator);
Collections.addAll(rv, rawSecondaryStorages);
}
storageDirectories = rv.toArray(new String[rv.size()]);
}
return storageDirectories;
}
rawSecondaryStoragesStr.contains(path)
따라 내부 저장소도 추가 될 수 있습니다. 우리는 그 조건을 더 잘 제거 할 수 있습니다. 내 장치는 내부 저장소 디렉토리를로 System.getenv("SECONDARY_STORAGE")
반환하지만 System.getenv(EXTERNAL_STORAGE)
KitKat 에서는 외부 메모리 카드 경로를 반환하기 때문에 그 문제에 직면했습니다 . 서로 다른 공급 업체가 어떤 빌어 먹을 표준없이 다른이를 구현 한 것 같다 ..
일부 장치 (예 : samsung galaxy sII)에서는 내부 메모리 카드가 vfat 일 수 있습니다. 이 경우 참조 마지막 코드를 사용하면 경로 내부 메모리 카드 (/ mnt / sdcad)를 얻지 만 외부 카드는 얻지 못합니다. 아래 코드 참조는이 문제를 해결합니다.
static String getExternalStorage(){
String exts = Environment.getExternalStorageDirectory().getPath();
try {
FileReader fr = new FileReader(new File("/proc/mounts"));
BufferedReader br = new BufferedReader(fr);
String sdCard=null;
String line;
while((line = br.readLine())!=null){
if(line.contains("secure") || line.contains("asec")) continue;
if(line.contains("fat")){
String[] pars = line.split("\\s");
if(pars.length<2) continue;
if(pars[1].equals(exts)) continue;
sdCard =pars[1];
break;
}
}
fr.close();
br.close();
return sdCard;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
File[] files = null;
File file = new File("/storage");// /storage/emulated
if (file.exists()) {
files = file.listFiles();
}
if (null != files)
for (int j = 0; j < files.length; j++) {
Log.e(TAG, "" + files[j]);
Log.e(TAG, "//--//--// " + files[j].exists());
if (files[j].toString().replaceAll("_", "")
.toLowerCase().contains("extsdcard")) {
external_path = files[j].toString();
break;
} else if (files[j].toString().replaceAll("_", "")
.toLowerCase()
.contains("sdcard".concat(Integer.toString(j)))) {
// external_path = files[j].toString();
}
Log.e(TAG, "--///--///-- " + external_path);
}
이 코드가 문제를 확실히 해결할 것이라고 확신합니다 ... 이것은 저에게 잘 작동합니다 ... \
try {
File mountFile = new File("/proc/mounts");
usbFoundCount=0;
sdcardFoundCount=0;
if(mountFile.exists())
{
Scanner usbscanner = new Scanner(mountFile);
while (usbscanner.hasNext()) {
String line = usbscanner.nextLine();
if (line.startsWith("/dev/fuse /storage/usbcard1")) {
usbFoundCount=1;
Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/usbcard1" );
}
}
}
if(mountFile.exists()){
Scanner sdcardscanner = new Scanner(mountFile);
while (sdcardscanner.hasNext()) {
String line = sdcardscanner.nextLine();
if (line.startsWith("/dev/fuse /storage/sdcard1")) {
sdcardFoundCount=1;
Log.i("-----USB--------","USB Connected and properly mounted---/dev/fuse /storage/sdcard1" );
}
}
}
if(usbFoundCount==1)
{
Toast.makeText(context,"USB Connected and properly mounted", 7000).show();
Log.i("-----USB--------","USB Connected and properly mounted" );
}
else
{
Toast.makeText(context,"USB not found!!!!", 7000).show();
Log.i("-----USB--------","USB not found!!!!" );
}
if(sdcardFoundCount==1)
{
Toast.makeText(context,"SDCard Connected and properly mounted", 7000).show();
Log.i("-----SDCard--------","SDCard Connected and properly mounted" );
}
else
{
Toast.makeText(context,"SDCard not found!!!!", 7000).show();
Log.i("-----SDCard--------","SDCard not found!!!!" );
}
}catch (Exception e) {
e.printStackTrace();
}
그건 사실이 아니야. / mnt / sdcard / external_sd는 SD 카드가 장착되어 있지 않아도 존재할 수 있습니다. 마운트되지 않은 경우 / mnt / sdcard / external_sd에 쓰려고하면 애플리케이션이 충돌합니다.
다음을 사용하여 먼저 SD 카드가 마운트되었는지 확인해야합니다.
boolean isSDPresent = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
getExternalStorageState()
외부 SD 카드가 아닌 내부 저장소를 반납하면 의미가 없다고 생각합니다.
String path = Environment.getExternalStorageDirectory()
+ File.separator + Environment.DIRECTORY_PICTURES;
File dir = new File(path);
Context.getExternalCacheDirs () 또는 Context.getExternalFilesDirs () 또는 Context.getObbDirs ()와 같은 것을 사용할 수 있습니다. 애플리케이션이 파일을 저장할 수있는 모든 외부 저장 장치에 애플리케이션 특정 디렉토리를 제공합니다.
따라서 다음과 같이-Context.getExternalCacheDirs () [i] .getParentFile (). getParentFile (). getParentFile (). getParent ()는 외부 저장 장치의 루트 경로를 가져올 수 있습니다.
이 명령은 다른 목적을위한 것이지만 다른 답변은 저에게 효과가 없었습니다.
이 링크는 나에게 좋은 포인터를 주었다-https: //possiblemobile.com/2014/03/android-external-storage/
System.getenv("SECONDARY_STORAGE")
Marshmallow에 대해 null을 반환합니다. 이것은 모든 외부 디렉토리를 찾는 또 다른 방법입니다. 내부 / 외부 여부를 결정하는 제거 가능한지 확인할 수 있습니다.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
File[] externalCacheDirs = context.getExternalCacheDirs();
for (File file : externalCacheDirs) {
if (Environment.isExternalStorageRemovable(file)) {
// It's a removable storage
}
}
}
내 Samsung Galaxy Tab S2 (모델 : T819Y) 에서 Dmitriy Lozenko 및 Gnathonic이 제공 한 솔루션을 사용해 보았지만 외부 SD 카드 디렉터리 경로를 검색하는 데 도움이되지 않았습니다. 명령 실행에 외부 SD 카드 디렉토리 (예 : / Storage / A5F9-15F4)에 대한 필수 경로가 포함 되었지만 정규 표현식과 일치하지 않아 반환되지 않았습니다. 삼성이 따르는 디렉토리 이름 지정 메커니즘을 얻지 못했습니다. 왜 그들이 표준 (예 : extsdcard) 에서 벗어나고 제 경우와 같이 정말 수상한 것을 생각해 냈습니다 (예 : / Storage / A5F9-15F4) . 내가 놓친 것이 있습니까? 어쨌든, Gnathonic의 정규 표현식 변경에 따라mount
솔루션은 유효한 sdcard 디렉토리를 얻는 데 도움이되었습니다.
final HashSet<String> out = new HashSet<String>();
String reg = "(?i).*(vold|media_rw).*(sdcard|vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String s = "";
try {
final Process process = new ProcessBuilder().command("mount")
.redirectErrorStream(true).start();
process.waitFor();
final InputStream is = process.getInputStream();
final byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
s = s + new String(buffer);
}
is.close();
} catch (final Exception e) {
e.printStackTrace();
}
// parse output
final String[] lines = s.split("\n");
for (String line : lines) {
if (!line.toLowerCase(Locale.US).contains("asec")) {
if (line.matches(reg)) {
String[] parts = line.split(" ");
for (String part : parts) {
if (part.startsWith("/"))
if (!part.toLowerCase(Locale.US).contains("vold"))
out.add(part);
}
}
}
}
return out;
이것이 유효한 솔루션인지 그리고 다른 삼성 태블릿에 대한 결과를 제공하는지 확실하지 않지만 현재 내 문제를 해결했습니다. 다음은 Android (v6.0)에서 이동식 SD 카드 경로를 검색하는 또 다른 방법입니다. 나는 안드로이드 마시맬로로 방법을 테스트했으며 작동합니다. 여기에 사용 된 접근 방식은 매우 기본적이며 다른 버전에서도 작동하지만 테스트는 필수입니다. 이에 대한 통찰력이 도움이 될 것입니다.
public static String getSDCardDirPathForAndroidMarshmallow() {
File rootDir = null;
try {
// Getting external storage directory file
File innerDir = Environment.getExternalStorageDirectory();
// Temporarily saving retrieved external storage directory as root
// directory
rootDir = innerDir;
// Splitting path for external storage directory to get its root
// directory
String externalStorageDirPath = innerDir.getAbsolutePath();
if (externalStorageDirPath != null
&& externalStorageDirPath.length() > 1
&& externalStorageDirPath.startsWith("/")) {
externalStorageDirPath = externalStorageDirPath.substring(1,
externalStorageDirPath.length());
}
if (externalStorageDirPath != null
&& externalStorageDirPath.endsWith("/")) {
externalStorageDirPath = externalStorageDirPath.substring(0,
externalStorageDirPath.length() - 1);
}
String[] pathElements = externalStorageDirPath.split("/");
for (int i = 0; i < pathElements.length - 1; i++) {
rootDir = rootDir.getParentFile();
}
File[] files = rootDir.listFiles();
for (File file : files) {
if (file.exists() && file.compareTo(innerDir) != 0) {
// Try-catch is implemented to prevent from any IO exception
try {
if (Environment.isExternalStorageRemovable(file)) {
return file.getAbsolutePath();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
이 문제를 처리하는 다른 방법이 있으면 친절하게 공유하십시오. 감사
//manifest file outside the application tag
//please give permission write this
//<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
File file = new File("/mnt");
String[] fileNameList = file.list(); //file names list inside the mnr folder
String all_names = ""; //for the log information
String foundedFullNameOfExtCard = ""; // full name of ext card will come here
boolean isExtCardFounded = false;
for (String name : fileNameList) {
if (!isExtCardFounded) {
isExtCardFounded = name.contains("ext");
foundedFullNameOfExtCard = name;
}
all_names += name + "\n"; // for log
}
Log.d("dialog", all_names + foundedFullNameOfExtCard);
다음 단계가 저에게 효과적이었습니다. 다음 줄을 작성하면됩니다.
String sdf = new String(Environment.getExternalStorageDirectory().getName());
String sddir = new String(Environment.getExternalStorageDirectory().getPath().replace(sdf,""));
첫 번째 줄은 sd 디렉터리의 이름을 제공하며 두 번째 문자열의 replace 메서드에서 사용하면됩니다. 두 번째 문자열에는 내부 및 이동식 sd (/ storage / 내 경우) 경로가 포함됩니다 . 내 앱에이 경로가 필요했지만 필요한 경우 더 나아갈 수 있습니다.