일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- MSYS2
- 인증
- 앱리소스
- Android
- 안드로이드
- SSH
- WebAuthn
- apple
- FIDO2
- css
- git
- SWIFT
- kmip
- MYSQL
- albumbook
- otpkey
- SwiftUI
- 앱스토어
- OTP
- SSL
- Xcode
- openssl
- Nodejs
- MFA
- 2FA
- 앨범북
- fido
- OSX
- 애플
- appres
- Today
- Total
인디노트
Android 의 Storage Path 및 코드 구현 기술 본문
안드로이드 앱에서 스토리지에 파일을 쓰고 읽기 위해서는 메니페스트 (AndroidManifest.xml) 파일에 다음과 같은 권한을 기록해줘야 한다.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
# 외장 메모리 (SD CARD)의 절대 경로 알아내기
String sdcardPath = null;
String sdcardStat = Environment.getExternalStorageState();
if(sdcardStat.equals(Environment.MEDIA_MOUNTED))
{
sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
}
여기에서 생각해야 할 내용이 있다. 만약 안드로이드 기기에 외장 메모리가 한개 이상인 경우에는 어떠할까...
Android 에서 제공되는 Environment 클래스에서 getExternalStorageDirectory() 함수의 코드를 살펴보자.
public static File getExternalStorageDirectory() {
throwIfUserRequired();
return sCurrentUser.getExternalDirsForApp()[0];
}
이렇게 getExternalStorageDirectory 함수는 현재의 사용자 (기기에 로그온 한 사용자, 초기에는 이런 내용이 없었는데 모바일 기기를 개인용 혹은 업무용으로 병용으로 사용할 수 있게 하기 위해서 사용자 개념을 도입함) 의 해당 앱(App) 에 제공되는 외장 디렉토리 파일들의 핸들 첫번째를 가져오게 되어 있다.
현재 대부분의 안드로이드 기기는 외장 메모리를 1개 밖에 탑재하지 못한다. 그것은 기기의 크기 및 휴대성 등을 고려하고 또한 SD 카드의 단일 용량이 계속 증가하는 추세이기 때문에 굳이 앱에서 이를 고려할 필요는 없어 보인다. 하지만, 미래에는 어떤 기기가 나올지 모르기 때문에 대처하는 현명함이 필요할 것 같다.
참고로 getExternalStorageState() 함수도 첫번째 외장 스토리지 패스의 상태를 돌려준다.
public static String getExternalStorageState() {
final File externalDir = sCurrentUser.getExternalDirsForApp()[0];
return getExternalStorageState(externalDir);
}
이제 sdcardPath 를 가져온 결과의 예를 살펴보자.
Android SDK: 19 (4.4.4)
/storage/emulated/0
Android SDK: 21 (5.0.2)
/storage/sdcard
Android SDK: 23 (6.0)
/storage/emulated/0
이와같이 안드로이드의 빌드 버전 혹은 디바이스의 제조사 등에 따라서 다를 수 있다는것에 유의를 해야 할 것이다.
그런데 여기서 또하나 주의해야 할 사항이 있다. 과연 getExternalStorageDirectory 가 우리가 생각하는 외장 SD 카드를 뜻할까? 그렇게 오해할 수 있다. 함수 이름에 ExternalStorage 라는 내용이 있기 때문에 당연히 그렇게 오해 할 수 있다.
하지만 실상은 그렇지 않다. 여기서 말하는 External Storage 는 디바이스 장치의 내장 스토리지의 패스이다.
안드로이드는 크게 2 가지의 (혹은 그 이상)의 스토리지 영역을 가진다.
- System Storage
- External Storage(s)
"/" 로 표현되는 루트 폴더가 System 영역이다. 또한 모든 Storage Path 는 System 영역에 특정 패스로 마운트 되어진다.
# 슬롯에 꽂은 외장 메모리의 절대 경로 알아내기
아쉽게도 지금까지의 안드로이드에서 제공하는 API 중에 슬롯에 꽂아져 있는 외장 메모리의 패스 (마운트 포인트) 를 알려주는 API 는 없는것 같다.
단, 다음과 같은 방법으로 해당 패스를 알아내는 방법이다.
String legacyPath = System.getenv("EXTERNAL_STORAGE");
String secondaryPath = System.getenv("SECONDARY_STORAGE");
각각의 출력은 다음과 같다. (제조사 마다 다를 수 있음)
/storage/emulated/legacy
/storage/extSdCard
public class SDCard
{
public static String getExternalSDCardPath()
{
HashSet<String> hs = getExternalMounts();
for(String extSDCardPath : hs)
{
return extSDCardPath;
}
return null;
}
public static HashSet<String> getExternalMounts()
{
final HashSet<String> out = new HashSet<String>();
//String reg = "(?i).*vold.*(vfat|ntfs|exfat|fat32|ext3|ext4).*rw.*";
String reg = "(?i).*media_rw.*(storage).*(sdcardfs).*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") && !part.toLowerCase(Locale.US).contains("/mnt/"))
{
out.add(part);
}
}
}
}
}
}
return out;
}
}
'소스 팁 > Java, Android, Kotlin' 카테고리의 다른 글
안드로이드 버전별 이름 (별거 아니지만 이게 자주 헷갈린다.) (0) | 2016.10.02 |
---|---|
안드로이드 Activity중복 안되게 설정하는 방법 (0) | 2016.07.28 |
안드로이드에서 띄울수 있는 여러가지 다이얼로그 (0) | 2016.05.26 |
Create Horizontal ListView using GridView (0) | 2016.05.22 |
Android Studio Code Style 바꾸기 (0) | 2016.05.19 |