일모도원(日暮途遠) 개발자

[안드로이드 개발] 아직도 헷갈리는 안드로이드 폴더 구조. 본문

안드로이드 개발/안드로이드

[안드로이드 개발] 아직도 헷갈리는 안드로이드 폴더 구조.

달님개발자 2023. 4. 7. 23:29

초창기 아이폰을 사용할때, 삼성이 안드로이드 장점으로 내세우던 것중 하나가 SD카드를 통해서 저장공간을 확장할수 있다는거였다.

 

안드로이드 개발을 시작할때 내부(internal) 저장공간, 외부(external) 저장공간 이라고 말할때, 나는 외부가 저 SD카드처럼 폰에 삽입해서 저장공간을 늘리는걸 말하는줄 알았다.

 

안드로이드 스튜디오에서 보면 이름이 떡하니 "sdcard"로 되어 있다. 근데 내 폰에는 sd카드가 없는데?

챗GPT에게 물어보니 요즘은 물리적인 sd카드를 안쓰는 추세이지만, 이전과 호환을 위해서 쓰는 이름이라고 한다. 4.0(아이스크림 샌드위치)까지는 물리적인 SD카드를 가리키는 이름이었다고 한다.

그리고 사실 저 sdcard폴더는 심볼릭링크로 나의 경우는 /storage/self/primary를 가리킨다. os버전에 따라서 /mnt/user/0/primary, /storage/emulated/0. 처럼 다양하다고 한다.

 

내 갤럭시 폰의 경우 메모리는 6인가 8기가이고 저장공간은 256기가인데, 내부(internal) 저장공간, 외부(external) 저장공간은 어떻게 나뉘냐니까 OS가 알아서 나눈다고 한다. 이건 뭐 그렇다고 치고.


앱내에 캐쉬폴더에 파일을 임시로 저장을 했는데 안보여서 한참 디버깅을 했었다.

캐쉬 폴더에 저장을하고 디버깅하면서 경로를 보는데 아래처럼 나온다.

/data/user/0/com.dalnimsoft.araconv/cache/20230407223019.mp4

 

평상시처럼 sdcard/Android/data/내 패키지 로 가서 봤는데 cache폴더 밑에 아무것도 없다. "이상하다? 저장이 되는 코드인데..."

 

삽질끝에 /data/data/내 패키지로가니까 여기에 있다.

 

 

즉 한개의 앱패키지가 두군데 있고 서로 다르다. 단순 링크가 아니라 내용물이 다르다.

/data/data/com.dalnimsoft.araconv/cache/
/sdcard/Android/data/com.dalnimsoft.araconv/cache

챗GPT가 말하길 /data/user/0/ 는 심볼릭 링크로  /data/data/를 가리킨다고 한다. 즉 아래 두개는 같은거다.

/data/user/0/com.dalnimsoft.araconv/cache/20230407223019.mp4
/data/data/com.dalnimsoft.araconv/cache/20230407223019.mp4

계속 물어보니 /data/data/com.dalnimsoft.araconv/cache/ 는 내부 저장공간이고

/sdcard/Android/data/com.dalnimsoft.araconv/cache는 외부 저장공간이라고 한다.

내부저장공간은 내 앱만 접근 가능하고, 외부저장공간은 권한을 가지고 있으면 다른앱도 내앱의 외부 저장공간에 접근이 가능하다고 한다.


내가 사용한 캐쉬폴더를 가져오는 코드가 "context.getCacheDir().getAbsolutePath()"였다. 이건 내부 저장공간의 캐쉬 폴더를 가져오는거였었다. 아무 생각없이 사용했었는데...

//내부 저장공간의 캐쉬 폴더 가져오기
File internalCacheDir = context.getCacheDir();

//외부 저장공간의 캐쉬 폴더 가져오기
File externalCacheDir = context.getExternalCacheDir();

 


폰에서 앱을 수동으로 지우면 내부저장공간만 지워지고 외부 저장공간은 안지워진다고 한다. 유저가 직접 외부 저장공간을 지워야 한다고 하는데, 누가 일일히 지우겠는가?

챗GPT에 물어보니 아래처럼 코드를 짜면 앱이 삭제 될때 외부 저장공간도 같이 지워진다고 한다. 혹시 앱이 지워져도 외부 저장공간에 저장된 파일을 다른 앱에서 사용하는 경우에는 이렇게 지워버리면 안되겠지?

<receiver android:name=".MyPackageRemovedReceiver">
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_REMOVED" />
        <data android:scheme="package" android:path="com.dalnimsoft.araconv" />
    </intent-filter>
</receiver>
public class MyPackageRemovedReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String packageName = intent.getData().getSchemeSpecificPart();
        if ("com.dalnimsoft.araconv".equals(packageName)) {
            File externalDir = context.getExternalFilesDir(null);
            if (externalDir != null) {
                deleteRecursive(externalDir);
            }
        }
    }

    private void deleteRecursive(File fileOrDirectory) {
        if (fileOrDirectory.isDirectory()) {
            for (File child : fileOrDirectory.listFiles()) {
                deleteRecursive(child);
            }
        }
        fileOrDirectory.delete();
    }
}

 

안드로이드 폴더구조는 여전히 어렵다.