ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Storage] Legacy Storage 외부저장소 공유공간에 파일쓰기
    Android/Storage 2021. 10. 29. 16:59

    안드로이드 저장소 정리 포스팅

    [Android/Storage] - [Android] 안드로이드 저장소 정리

     

    Android 9이하에서 공유저장공간에 파일을 write해보고 권한이 없을 때 파일을 write하면 어떤 결과가 나타나는지 확인해본다.

     

    필요한 내용만 정리하였기 때문에 권한이 획득, 거부 상태인지 체크하고 권한을 얻어오는 코드는 넣지 않았다.

    단순히 앱 권한 설정으로 가서 저장공간 권한 체크박스만 설정/해제하자

    권한 처리는 아래의 포스팅을 참고

    [Android/Permission] - [Android] 권한 체크, 획득

    [Android/Permission] - [Android] 전반적인 권한 처리 로직


    Android 9이하에서는 WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE 권한만 있으면 외부저장소에 접근이 가능하다.

     

    • 앱에서 권한을 사용하도록 매니페스트에 외부저장소 읽기, 쓰기 권한을 선언하자.

     

    • 파일명과 파일내용에 해당하는 EditText 두개를 사용

    (경로까지 테스트해보고 싶으면 경로를 넣어줄 EditText를 추가적으로 이용해도 좋다)

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <EditText
            android:id="@+id/et_file_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="파일명"
            android:inputType="textPersonName" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:orientation="vertical">
    
            <EditText
                android:id="@+id/et_file_content"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:ems="10"
                android:gravity="start|top"
                android:hint="파일 내용"
                android:inputType="textPersonName|textMultiLine" />
        </LinearLayout>
    
        <Button
            android:id="@+id/btn_write_file_external_shared_storage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:onClick="onClick"
            android:text="공용공간 텍스트 파일쓰기" />
    
        <Button
            android:id="@+id/btn_when_no_permission"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:onClick="onClick"
            android:text="권한이 없을때는 어떻게 될까" />
        
    </LinearLayout>

    액티비티 코드

     

    • EditText 선언, 참조

     

    • 권한 체크상태 확인 메서드 정의

    write,read 권한 모두 획득 상태이면 true를 리턴, 이외에 false 리턴하도록 하였음

     

    • File을 String으로 변환한 파라메터를 받아 파일을 write하는 메서드

     

    • File 인스턴스에 해당하는 추상경로(abstarct path)의 유효성 검사 메서드

    File 인스턴스를 참조하여 파일을 바로 써도 파일이 써지지 않는 경우중

    외부저장소 권한을 가지고 있지 않아서일수도 있겠지만

     

    File 인스턴스에 해당하는 추상경로에 실제로 하나라도 디렉토리로 만들어져있지 않은 경우에 파일이 써지지 않는다.

    (추상경로에 실제로 폴더가 존재하지 않으면 파일이 써지지 않는다.)

     

    또는 추상경로의 중간에 파일이 껴있는지도 확인해볼 필요가 있겠다.

     

    File클래스의 createNewFile() 메서드를 사용하면 기존에 동일한 이름의 파일이 존재하면 파일을 생성하지 않고 false를 리턴하고, 동일한 이름의 파일이 존재하지 않으면 새 빈 파일을 생성하고 true를 리턴해주지만 

    createNewFile()메서드를 사용하지 않고 짜봤다.

    [Android/Storage] - [Android] Java File 클래스 공부

     

    파일이 포함될 디렉토리 경로의 유효성 검사 메서드이다.

    //파일이 저장될 상위 경로 유효성 검사
    private fun checkAbstractPath(file: File): Boolean {
    
        log("파일이 저장될 상위경로 유효성 검사")
    
        val value: Boolean
    
        if (file.exists()) {//상위 경로에 파일,디렉토리 둘중하나 존재
            log("상위경로에 동일한 이름의 파일,디렉토리 무엇인가 존재")
    
            if (file.isDirectory) {//디렉토리에 해당
                log("상위경로에 해당하는 것이 디렉토리")
    
                //디렉토리 내부에 동일한 이름의 파일또는 디렉토리가 있는지 확인
                val savedFile = File(file.toString() + "/" + editFileName.text.toString())
    
                if (savedFile.exists()) {
                    log("디렉토리 내부에 동일이름의 무엇인가 존재")
                    log("파일 생성 불가")
                    log("(동일한 이름의 파일이 있을 때만 생성이 불가능한 것이 아니라")
                    log("(같은 이름의 디렉토리가 있을 때도 파일 생성이 불가능하다)")
                    value = false
                } else {
                    log("저장될 파일경로에 아무것도 존재하지 않음")
                    log("파일 생성 가능")
                    value = true
                }
    
            } else { //파일에 해당
                log("상위 경로가 파일이라 하위에 파일 생성 불가")
                value = false
            }
    
        } else { //추상 경로에 실제 파일이나, 디렉토리나 아무것도 존재하지 않음
            log("상위 경로에 물리적인 것이 존재하지 않음")
    
            if (file.mkdirs()) { //mkdirs: 최하위까지 연쇄적으로 폴더 생성, 성공- true 실패 -false
                value = true
                log("상위 경로까지 디렉토리를 생성")
            } else {
                log("mkdirs() 알수 없는 문제 발생")
                value = false
            }
    
        }
    
        return value
    
    }

    exists()메서드가 true이면 -> isDirectory(), isFile()메서드는 서로 반대의 Boolean값을 가진다.

    (isDirectory(),  isFile() 둘중하나로 검사하면 된다)

     

    exists()메서드가 false이면 -> isDirectory(), isFile() 모두 false

    메서드의 리턴값이 true이면 "/파일명"을 붙여서 파일을 write한다.

     

     

    • 파일 쓰기 메서드

    path 유효성 검사후에 true라면 파일을 저장할 메서드

    내부에서 EditText에 입력된 값들을 파일명, 파일 내용으로 한다.

     

    • 위에서 정의한 메서드들을 사용하여 버튼 리스너 onClick처리

    테스트에서는 공용공간의 Environment.DIRECTORY_DOCUMENTS 에 해당하는 경로 밑에다 파일을 저장했다.

     

    • 권한이 거부되어있는 상태일 때 파일을 write하는 경우


    테스트 전 상태( 초기화해놓은 디바이스라 Pictures 폴더가 있었는데 테스트를 위해 지운 상태)

     

    앱 권한 설정으로 들어가서 저장소권한의 체크박스를 허용으로 변경한다.

     

    EditText 각각에 test, 테스트 입력후

    공용공간 텍스트 파일쓰기 버튼 클릭

     

    같은 상태에서 공용공간 텍스트 파일쓰기 버튼을 한번 더 누르면 방금 만든 파일이 존재하여 저장되지 않는다

     

    권한이 없을 때를 테스트하기 위하여 권한 설정으로 가서 거부로 바꾸자

    우리의 메서드에서 동일한 이름의 파일이나 디렉토리가 있으면 파일을 못쓰게 해놨으므로

    처음에 만들었던 파일이름과는 다른 파일이름을 사용하여 두번째 버튼을 눌러보면

     파일을 생성이 가능한 상태이지만 권한이 없어서 우리가 만들어 놓은 writeFileToExternalSharedStorage 메서드 내부에서 파일을 쓰지 못하고 예외가 발생한 것을 볼 수 있다.

     

     

     

    댓글

Designed by Tistory.