1.  파일 처리의 응용

음악, 영상, 그림 파일 등은 여러 응용 프로그램에서 사용되는 경우가 많음.
  📍  예를 들어 MP3 파일을 안드로이드에 내장된 앱에서 들을 수도 있고 별도의 음악 플레이어로 들을 수도 있음
         ➡️  이런 경우 SD 카드에 저장하여 활용

안드로이드에서는 SD 카드에 저장된 데이터에 특별한 인증 절차 없이 접근 가능하며 제한된 공간의 내장 메모리보다 훨씬 큰 공간을 사용할 수 있으며 확장성도 뛰어남. 실제 안드로이드폰의 경우 주로 마이크로 SD 카드를 장착하여 사용. AVD에도 가상 SD 카드를 장착할수 있음.

 

AVD Manager를 실행 후 해당 AVD 이름의 오른쪽에 있는 Edit 아이콘을 클릭한후 Show Advanced Settings를 클릭하면 사용하는 AVD에 장착된 SD 카드를 확인할 수 있다. 만약 가상 SD 카드가 만들어져 있지 않으면 원하는 크기를 새로 입력.

 

 

Target SDK 버전 변경


    Android SDK 30 버전에서 SD 카드의 처리 방법이 대폭 변경되어 접근 거부가 발생할 수 있음
      ➡️  이럴 때는 Target SDK 버젼을 29로 변경

android {
    compileSdk 32

    defaultConfig {
        applicationId "kr.somin.sdkstream"
        minSdk 26
        targetSdk 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

 

1)  SD 카드에서 파일 읽기

💫  폴더 경로가 다른 것만 제외하면 SD 카드의 기본적인 경로는 내장 메모리에서 파일을 읽을 때와 별다른 차이가 없음
💫  먼저 Device File Explorer에서 /sdcard 폴더 또는 /storage/emulated/0 폴더에 적당한 텍스트 파일을 upload
💫  AVD에서 sd 카드의 경로는 절대적인 것이 아니며 SDK 버전에 따라 달라질수 있음

 

 

💫  AndroidManifest.xml 파일에 SD 카드를 사용할 수 있도록 퍼미션을 지정해야 함
       ➡️  AndroidManifest.xml에 퍼미션 및 application 관련 속성을 추가

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        android:requestLegacyExternalStorage="true"

 

SD 카드에서 파일 읽기
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnRead"
        android:text="SD 카드에서 파일 읽기" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/editSD"
        android:lines="10" />

</LinearLayout>
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val btnRead = findViewById<Button>(R.id.btnRead)
        val editSD = findViewById<EditText>(R.id.editSD)
        
        ActivityCompat.requestPermissions(this, 
            arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
            Context.MODE_PRIVATE)
        
        btnRead.setOnClickListener {
            try {
                val inputStream = FileInputStream("/storage/emulated/0/Download/test.txt")
                val txt = ByteArray(inputStream.available())
                inputStream.read(txt)
                editSD.setText(txt.toString(Charsets.UTF_8))
                inputStream.close()
            } catch (e: IOException) {
                println(e.printStackTrace())
                Toast.makeText(applicationContext, "에러", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

 

ActivityCompat.requestPermissions(this,
    arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
    Context.MODE_PRIVATE)


    앱에서 파일 엑세스 작업을 허용할지를 묻는 창이 나옴. <허용>을 클릭.

val inputStream = FileInputStream("/storage/emulated/0/Download/test.txt")


    파일 입력 스트림을 생성할 때 SD 카드의 절대 경로를 FileInputStream() 생성자에 지정

 


2)  SD 카드에 폴더 및 파일 생성

SD 카드의 파일을 좀 더 정밀하게 처리하려면 우선 Environment 클래스의 정적 메소드를 이용하여 SD 카드의 동작 여부와 관련 폴더 경로를 구해야 함

SD 카드에 폴더 및 파일 생성
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnMkDir"
        android:text="SD 카드에 디렉토리 생성" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnRmDir"
        android:text="SD 카드에 디렉토리 삭제" />

</LinearLayout>
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_01)
        
        ActivityCompat.requestPermissions(this, 
            arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
            Context.MODE_PRIVATE)

        val btnMkdir = findViewById<Button>(R.id.btnMkDir)
        val btnRmdir = findViewById<Button>(R.id.btnRmDir)

        val strSDpath = Environment.getExternalStorageDirectory().absolutePath
        val myDir = File("${strSDpath}/MyDir")

        btnMkdir.setOnClickListener {
            myDir.mkdir()
        }

        btnRmdir.setOnClickListener {
            myDir.delete()
        }
    }
}

 

val strSDpath = Environment.getExternalStorageDirectory().absolutePath

 

    ✓  SD 카드의 절대 경로를 돌려주는데, 대개 /sdcard 폴더 또는 /storage/emulated/0

    ✓  getExternalStorageDirectory() 이외에도 시스템 폴더를 반환하는 getRootDirectory(),

         데이터 폴더를 반환하는 getDataDirectory()등이 있음

 

val myDir = File("${strSDpath}/MyDir")


    ✓  SD 카드의 경로 아래에 MyDir 폴더를 생성하기 위한 File형 변수를 설정

 

 

 


3)  특정 폴더의 하위 폴더 및 파일 목록

지정한 폴더의 하위 폴더 및 파일 목록에 접근하려면 File.listFiles() 메서드를 사용  ➡️  반환형은 File[] 형

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btnFileList"
        android:text="시스템 폴더의 폴더/파일 목록" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/editFileList" />

</LinearLayout>
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_02)

        val btnFileList = findViewById<Button>(R.id.btnFileList)
        val editFileList = findViewById<EditText>(R.id.editFileList)
        btnFileList.setOnClickListener {
            val sysDir = Environment.getRootDirectory().absolutePath
            val sysFiles = File(sysDir).listFiles()

            var strFname: String
            for (i in sysFiles.indices) {
                if (sysFiles[i].isDirectory == true)
                    strFname = "<폴더> " + sysFiles[i].toString()
                else
                    strFname = "<파일> " + sysFiles[i].toString()

                editFileList.setText(editFileList.text.toString() + "\n" + strFname)
            }
        }
    }
}

 

val sysDir = Environment.getRootDirectory().absolutePath


    ✓  안드로이드 시스템 경로를 반환

 

val sysFiles = File(sysDir).listFiles()

 

    ✓  시스템 폴더의 폴더 및 파일 목록을 구해서 배열로 반환

 

if (sysFiles[i].isDirectory == true)


    ✓  현재 파일이 폴더인지 파일인지 확인

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

+ Recent posts