본문 바로가기
안드로이드/데이터 입출력

안드로이드 파일 입출력

by 김어찐 2022. 6. 21.
728x90

안드로이드는 애플리케이션이 데이터를 저장할 수 있는 저장소를 두 가지로 제공하고 있다.
내부 저장소 : 애플리케이션을 통해서만 접근이 가능하다. 
외부 저장소 : 단말기 내부의 공유 영역으로 모든 애플리케이션이 접근 가능하다. 단말기를 컴퓨터에 연결하면 탐색기를 통해 접근할 수 있는 영역을 의미한다.

 

파일 입출력

내부 저장소 : openFileOutput, openFileInput
외부 저장소 : FileInputStream, FileOutputStream

 

안드로이드 10의 외부저장소

외부 저장소에 저장된 파일은 모든 애플리케이션이 자유롭게 접근할 수 있어 보안에 문제가 되었다.
이에 안드로이드 10에서는 외부 저장소에 제한을 두어 보안을 강화하게 되었다.
안드로이드 10에서는 외부 저장소의 정책을 무력화 할 수 있는 옵션이 있었으니 11부터는 이 옵션이 제거되어 외부 저장소의 자유로운 접근은 불가능하게 되었다.
이러한 외부 저장소를 Scoped Storage 정책이라 부른다.

 

Scoped Storage 정책

Scoped Storage는 다음과 같은 형태로 구성된다.
앱 데이터 폴더 : 읽고 쓰는데 권한이 필요가 없으며 해당 애플리이션만 접근이 가능하다. 애플리케이션 삭제 시 폴더도 같이 삭제된다.


미디어 파일들 :  사진, 동영상, 음원파일들을 저장하는 장소이다. 


공용 파일들 : Downloads 폴더. 이 폴더에 저장된 파일은 모든 애플리케이션이 접근할 수 있다. 단, 코드를 통한 직접 접근은 불가능하고 단말기에 설치된 파일 관리 어플을 통해서만 접근이 가능하다. 즉, 파일 관리 어플을 실행해 사용자가 직접 파일을 선택해줘야 가능하다.

 

package com.example.filedata

import android.content.Context
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.FileInputStream
import java.io.FileOutputStream

class MainActivity : AppCompatActivity() {

    // 내부 저장소의 앱 데이터 디랙토리의 경로
    lateinit var file_path:String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // null을 셋팅하면 앱 데이터 폴더의 경로를 얻어오고
        // Environment.DIRECTORY_종류 를 넣어주면 해당 경로를 얻어온다
        file_path = getExternalFilesDir(null).toString()
//        file_path = getExternalFilesDir(Environment.DIRECTORY_MUSIC).toString()
        Log.d("test",file_path)

        button.setOnClickListener {
            // MODE_PRIVATE : 덮어쓰기
            // MODE_APPEND : 잉서 쓰기
            val fos = openFileOutput("data1.dat",Context.MODE_PRIVATE)
            val dos = DataOutputStream(fos)

            // 데이터 쓰기
            dos.writeInt(100)
            dos.writeDouble(10.11)
            dos.writeBoolean(true)
            dos.writeUTF("문자열")
            dos.flush()
            dos.close()

            textView.text = "내부 저장소소 쓰기완료"
       }
        button2.setOnClickListener {
            val fis = openFileInput("data1.dat")
            val dis = DataInputStream(fis)

            val data1 = dis.readInt()
            val data2 = dis.readDouble()
            val data3 = dis.readBoolean()
            val data4 = dis.readUTF()

            dis.close()

            textView.text = "data1 : $data1\n"
            textView.append("data2 : $data2\n")
            textView.append("data3 : $data3\n")
            textView.append("data4 : $data4\n")

        }
        button3.setOnClickListener {
            val fos = FileOutputStream("$file_path/data2.dat")
            val dos = DataOutputStream(fos)

            // 데이터 쓰기
            dos.writeInt(200)
            dos.writeDouble(22.22)
            dos.writeBoolean(false)
            dos.writeUTF("문자열2")

            dos.flush()
            dos.close()

            textView.text = "외부 저장소의 앱 데이터 폴더에 저장장"
        }

        button4.setOnClickListener {
            val fis = FileInputStream("${file_path}/data2.dat")
            val dis = DataInputStream(fis)

            val data1 = dis.readInt()
            val data2 = dis.readDouble()
            val data3 = dis.readBoolean()
            val data4 = dis.readUTF()

            dis.close()

            textView.text = "data1 : $data1\n"
            textView.append("data2 : $data2\n")
            textView.append("data3 : $data3\n")
            textView.append("data4 : $data4\n")
        }

        button5.setOnClickListener {
            // 파일 관리 앱의 액티비티를 실행한다.
            val fileIntent = Intent(Intent.ACTION_CREATE_DOCUMENT)
            fileIntent.addCategory(Intent.CATEGORY_OPENABLE)
            // mime 타입 지정
            fileIntent.type = "*/*"
            startActivityForResult(fileIntent,100)

        }
        button6.setOnClickListener {
            // 파일 관리 앱이 액티비티를 실행한다.
            val fileIntent = Intent(Intent.ACTION_OPEN_DOCUMENT)
            fileIntent.type = "*/*"
            startActivityForResult(fileIntent,200)
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == 100) {
            if (resultCode == RESULT_OK) {
                val des1 = contentResolver.openFileDescriptor(data?.data!!,"w")
                val fos = FileOutputStream(des1?.fileDescriptor)
                val dos = DataOutputStream(fos)
                dos.writeInt(300)
                dos.writeDouble(33.33)
                dos.writeBoolean(true)
                dos.writeUTF("문자열3")

                dos.flush()
                dos.close()

                textView.text = "Downloads 폴더 저장장"
            }
        } else if (requestCode == 200) {
            if (resultCode == RESULT_OK) {
                val des2 = contentResolver.openFileDescriptor(data?.data!!,"r")
                val fis = FileInputStream(des2?.fileDescriptor)
                val dis = DataInputStream(fis)

                val data1 = dis.readInt()
                val data2 = dis.readDouble()
                val data3 = dis.readBoolean()
                val data4 = dis.readUTF()

                dis.close()

                textView.text = "data1 : $data1\n"
                textView.append("data2 : $data2\n")
                textView.append("data3 : $data3\n")
                textView.append("data4 : $data4\n")

            }
        }
    }}

 

 

728x90

'안드로이드 > 데이터 입출력' 카테고리의 다른 글

안드로이드 sqlite 1  (0) 2022.06.23
안드로이드 assets  (0) 2022.06.22
안드로이드 Application Class  (0) 2022.06.21
안드로이드 코드 View  (0) 2022.06.20
안드로이드 xml View  (0) 2022.06.20