Dev/Android

Android (파일 처리 응용, SD카드 폴더 / 파일 생성 및 삭제, SD카드 폴더 / 파일 목록 출력, 파일처리 - 프로젝트, 이미지 번호 표시)

Walker_ 2024. 5. 2. 17:18

1. 파일 처리 응용

 

 - Device Manager 클릭 후 > 연필 모양 클릭

 

 - Show Advanced Settings 클릭 > SD카드 용량 있는 지 확인

 - build.gradle(Module)에서 targetSdk 29로 변경

 - Device File Explorer를 통해 SD카드 파일 읽기 가능

 - Download 폴더에 Upload

 - text 파일 업로드

 - 매니페스트 파일 상단에

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

<application
    android:requestLegacyExternalStorage="true"

 

 - 코드 2줄 추가

<?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">

    <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>

 

- XML 작성

package kr.jeongmo.a0501proejct03

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log.println
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.core.app.ActivityCompat
import java.io.FileInputStream
import java.io.IOException

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

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


        val btnRead = findViewById<Button>(R.id.btnRead)
        val editSD = findViewById<EditText>(R.id.editSD)

        btnRead.setOnClickListener {
            try {
                val inputStream = FileInputStream("/storage/emulated/0/Download/text.txt")
                val txt = ByteArray(inputStream.available())
                inputStream.read(txt)
                editSD.setText(txt.toString(Charsets.UTF_8))
                inputStream.close()
            } catch (e : IOException) {
                Toast.makeText(applicationContext, "에러", Toast.LENGTH_SHORT).show()
            }
        }
    }
}

 

- 액티비티 코드 작성

 

 - Allow > SD 카드에서 파일 읽기

 

2. SD카드에 폴더 및 파일 생성, 삭제

<?xml version="1.0" encoding="utf-8"?>
<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>

 

// 2. SD카드 파일 생성, 삭제

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()
}

 

 

 - 디렉토리 생성 클릭 > MyDir 폴더 생성 확인

 

  - 디렉토리 삭제 클릭 > MyDir 폴더 삭제 확인

 

3. SD카드 폴더, 파일 목록 출력

<?xml version="1.0" encoding="utf-8"?>
<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>
// 3. SD카드 폴더, 파일 목록
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)
    }
}

 

 - 버튼 클릭하면 파일 목록 출력

 

4. 파일처리 - 프로젝트

 - 프로젝트 새로 생성

 - targetSDK 29로 변경

 

 - 메인 액티비티 동일 위치에 New > Kotlin Class 파일 생성

 - 파일 명 : MyPictureView

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.View
import java.util.jar.Attributes

class MyPictureView(context: Context, attrs: AttributeSet?) : View(context, attrs) {
    
}

 

 - 임포트 파일 추가 후 > onDraw 메서드 추가

package kr.jeongmo.a0502project

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.View
import java.util.jar.Attributes

class MyPictureView(context: Context, attrs: AttributeSet?) : View(context, attrs) {

    var imagePath : String? = null

    @SuppressLint("DrawAllocation")
    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        try {
            if (imagePath != null) {
                val bitmap = BitmapFactory.decodeFile(imagePath)
                canvas.scale(2f, 2f, 0f, 0f)
                canvas.drawBitmap(bitmap!!, 0f, 0f, null)
                bitmap.recycle()
            }
        } catch (e : Exception) {
            
        }
    }
}

 

 - MyPictureView 코드 작성

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="kr.jeongmo.a0502project">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:requestLegacyExternalStorage="true"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.0502Project">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

 - ManiFests 코드 2줄 추가

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btnPrev"
            android:layout_weight="1"
            android:text="이전 그림"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btnNext"
            android:layout_weight="1"
            android:text="다음 그림"/>
    </LinearLayout>

    <kr.jeongmo.a0502project.MyPictureView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/myPictureView"/>


</LinearLayout>

 

package kr.jeongmo.a0502project

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.util.Log.println
import android.widget.Button
import androidx.core.app.ActivityCompat
import java.io.File

class MainActivity : AppCompatActivity() {

    lateinit var btnPrev : Button
    lateinit var btnNext : Button
    lateinit var myPicture : MyPictureView
    var curNum : Int = 1
    var imageFiles : Array<File>? = null

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

        title = "간단 이미지 뷰어"
        ActivityCompat.requestPermissions(
            this,
            arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
            Context.MODE_PRIVATE
        )

        btnPrev = findViewById(R.id.btnPrev)
        btnNext = findViewById(R.id.btnNext)
        myPicture = findViewById(R.id.myPictureView)

        imageFiles =
            File(Environment.getExternalStorageDirectory().absolutePath + "/Pictures").listFiles()
        // 파일 목록 출력
        var fileName = ""
        for (i in imageFiles!!.indices) {
            if (imageFiles!![i].isDirectory == true)
                fileName = "<폴더> " + imageFiles!![i].toString()
            else
                fileName = "<파일> " + imageFiles!![i].toString()
        }
        imageFname = imageFiles!![1].toString()
        myPicture.imagePath = imageFname

    }
}

 - 프로젝트 실행 하면 이미지 출력 확인

package kr.jeongmo.a0502project

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.util.Log.println
import android.widget.Button
import android.widget.Toast
import androidx.core.app.ActivityCompat
import java.io.File

class MainActivity : AppCompatActivity() {

    lateinit var btnPrev : Button
    lateinit var btnNext : Button
    lateinit var myPicture : MyPictureView
    var curNum : Int = 1
    var imageFiles : Array<File>? = null

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

        title = "간단 이미지 뷰어"
        ActivityCompat.requestPermissions(
            this,
            arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
            Context.MODE_PRIVATE
        )

        btnPrev = findViewById(R.id.btnPrev)
        btnNext = findViewById(R.id.btnNext)
        myPicture = findViewById(R.id.myPictureView)

        imageFiles =
            File(Environment.getExternalStorageDirectory().absolutePath + "/Pictures").listFiles()
        // 파일 목록 출력
        var fileName = ""
        for (i in imageFiles!!.indices) {
            if (imageFiles!![i].isDirectory == true)
                fileName = "<폴더> " + imageFiles!![i].toString()
            else
                fileName = "<파일> " + imageFiles!![i].toString()
        }
        imageFname = imageFiles!![1].toString()
        myPicture.imagePath = imageFname

        btnPrev.setOnClickListener {
            if (curNum <= 1) {
                Toast.makeText(applicationContext, "첫번째 그림입니다.", Toast.LENGTH_SHORT).show()
            } else {
                curNum--
                imageFname = imageFiles!![curNum].toString()
                myPicture.imagePath=imageFname
                myPicture.invalidate()
            }
        }

        btnNext.setOnClickListener {
            if (curNum >= imageFiles!!.size-1) {
                Toast.makeText(applicationContext, "마지막 그림입니다.", Toast.LENGTH_SHORT).show()

            }  else {
                curNum++
                imageFname = imageFiles!![curNum].toString()
                myPicture.imagePath=imageFname
                myPicture.invalidate()
            }
        }
    }
}

 

 - 코드 추가

 

 - 프로젝트 실행 후 이미지 변화 확인

MyPictureView.imagePath = imageFiles!![curIndex].toString()

btnPrev.setOnClickListener {
    if (curIndex <= 1) {
        Toast.makeText(applicationContext, "첫번째 그림입니다.", Toast.LENGTH_SHORT).show()
    } else {
        MyPictureView.imagePath = imageFiles!![--curIndex].toString()
        MyPictureView.invalidate()
    }
}

btnNext.setOnClickListener {
    if (curIndex >= imageFiles!!.size-1) {
        Toast.makeText(applicationContext, "마지막 그림입니다.", Toast.LENGTH_SHORT).show()
    }  else {
        MyPictureView.imagePath = imageFiles!![++curIndex].toString()
        MyPictureView.invalidate()
    }
}

 

 - 아래 쪽 코드 위 처럼 축약 가능

 

5. 파일처리 - 파일 갯수 표시

age kr.jeongmo.a0502_project_02

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.core.app.ActivityCompat
import java.io.File

class MainActivity : AppCompatActivity() {

    lateinit var btnPrev : Button
    lateinit var btnNext : Button
    lateinit var textView : TextView
    lateinit var MyPictureView : MyPictureView
    var curIndex : Int = 1
    var imageFiles : Array<File>? = null

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

        title = "간단 이미지 뷰어"
        ActivityCompat.requestPermissions(
            this,
            arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
            Context.MODE_PRIVATE
        )

        btnPrev = findViewById(R.id.btnPrev)
        btnNext = findViewById(R.id.btnNext)
        textView = findViewById(R.id.textView)
        MyPictureView = findViewById(R.id.myPictureView)

        imageFiles =
            File(Environment.getExternalStorageDirectory().absolutePath + "/Pictures").listFiles()

        // 파일 목록 출력
        var fileName = ""
        for (i in imageFiles!!.indices) {
            if (imageFiles!![i].isDirectory == true)
                fileName = "<폴더> " + imageFiles!![i].toString()
            else
                fileName = "<파일> " + imageFiles!![i].toString()
        }
        MyPictureView.imagePath = imageFiles!![curIndex].toString()

        btnPrev.setOnClickListener {
            if (curIndex <= 1) {
                Toast.makeText(applicationContext, "첫번째 그림입니다.", Toast.LENGTH_SHORT).show()
                textView.text = "1/9"
            } else {
                MyPictureView.imagePath = imageFiles!![--curIndex].toString()
                textView.text = curIndex.toString() + "/9"
                MyPictureView.invalidate()
            }
        }

        btnNext.setOnClickListener {
            if (curIndex >= imageFiles!!.size-2) {
                Toast.makeText(applicationContext, "마지막 그림입니다.", Toast.LENGTH_SHORT).show()
                textView.text = "9/9"
            } else {
                MyPictureView.imagePath = imageFiles!![++curIndex].toString()
                textView.text = curIndex.toString() + "/9"
                MyPictureView.invalidate()
            }
        }
    }

 

 

 


공부 과정을 정리한 것이라 내용이 부족할 수 있습니다.

부족한 내용은 추가 자료들로 보충해주시면 좋을 것 같습니다.

읽어주셔서 감사합니다 :)