이번에 외부 저장소의 파일 헤더를 수정하다가 하다가 알게된건데, Android 에서 SD card에 저장된 파일을 핸들링하려니까 권한이 없다며 진행되지 않았다.
의아하게 여겨 바로 한 일은 외부 저장소의 권한을 살펴본 일인데, 멀쩡히 권한이 존재할 것 이다.
대개, 이런식으로 되어 있을 것이다.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" ></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ></uses-permission>
꼼꼼한 개발자라면 해당 권한이 위험한 권한(dangerous permission)임을 인지하고 M 버전부터 처리코드를 넣어 다음과 같이 유저에게 request permission을 하고 있을지도 모른다.
requestPermissions(new String[] {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, MY_PERMISSION_REQUEST_CODE)
헌데 외부 저장소 권한을 설정하였는데, 왜 SD Cad에 저장된 파일을 컨트롤할 수 없는걸까? 그건 바로 Android의 기괴한 정책때문에 그렇다.
먼저, 본론으로 들어가기전에
알아두어야 될 점은 Android에서 얼마나 이상하게 SD Card를 다루느냐이다.
먼저,
Android에서 말하는 External Storage는 실제 External Storage (SD Card)를 의미하지 않는다.
여기서 가리키는 저장소는 '완전히 따로 관리되는 내부' 메모리와, 내부에 있는 '일반 파일 영역'을 의미한다.
이에 대한 근거는,
File Environment.getExternalStorageDirectory()
로 경로를 반환받을시, SD card를 가리키지 않기 때문이다. 어딜 가르키느냐? 일반 파일 영역을 나타내준다.
정말 이해가 안되는 일이지만 SD Card를 가리키는 경로는 제조사별로 다르기때문에 알아낼 도리가 없다.
굳이 알아내보려면 이런 느낌으로 써야한다.
filepath.contains('mnt/sdcard').. ? sd card!
filepath.contains('mnt/extCard')..? sd card!
filepath.contains('mnt/ext_sd')..? sd card!
정말 어이가 없는 일이다. 이건 제조사별로 다르다고 치고, 본론으로 돌아가서, 왜 SD Card 내에 파일을 쓰거나 수정할 수 없는걸까?
그런데, 지금 말하는 이야기가 얼토당토하지 않게 보이는 사람도 있을 것이다. "나는 잘되는데 뭔소리지?"
먼저, Froyo와 Gingerbread(2.2~2.3)의 Android는 권한 체크에 그리 꼼꼼하지 않았다.
그래서 External Storage_Write/Read 권한만 있어도 SD Card를 얼마든지 컨트롤 할 수 있었다.
그러다가, HoneyComb(3.0) 이상에서 추가 권한을 요구하게 되는데, 바로 우리를 곤경에 빠트리게 할,
WRITE_MEDIA_STORAGE 라는 권한의 등장이다. 이 문제는 LOLLIPOP 까지 지속된다. (5.0)
이 권한을 그럼 명세하면되지 않느냐? 라고 물을 수 있지만 해당 권한은 시스템권한으로, 일반 유저가 줄 수 없는 권한이다.
- 제조사에서는 제조사 기본앱에 이 권한을 주어 설치해놓은 경우도 존재함
3.0 부터 5,0 버전을 사용하는 유저들은 루팅후,
SDfix 라는 이상한 앱을 설치해 그룹 퍼미션을 줘가며 사용해야만 했었던 것이다.
앱이 하는 역할은 다음과 같다.
<permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
<group gid="sdcard_r" />
<group gid="sdcard_rw" />
<group gid="media_rw" />
</permission>
하지만 일반 논루팅 유저들은 해당 권한을 줄 수 없으므로, 결국 앱을 이용한 SD Card Write Access는 가질 수 없는 것이다.
그러다가 놀랍게도, Marshmallow(6.0)에서 부터는 External Storage 권한을 위험한 권한으로 규정하면서, 유저 추가 동의를 받을 경우 쓸 수 있게 바꿔버린것이다. 오마이 갓....
고로 결론은 다음과 같다. 이를 우회할 방법은 존재치 않으니 빨랑 포기하시라...