Foggy day

[Android] Android read file 본문

Android

[Android] Android read file

jinhan38 2023. 8. 30. 01:19

이번 포스팅에서는 디바이스에 있는 file들을 불러오는 것을 해보겠습니다.

 

 

 

1. 권한처리

2. ReadDeviceFile

 

 

 

1. 권한처리

Android api level 29를 기점으로 권한 처리를 다르게 해야합니다.

만약에 29 이하라고 한다면 READ_EXTERNAL_STORAGE권한을 추가 해야하고 런타임 권한을 획득해야 합니다.

30 이상이라면 MANAGE_EXTERNAL_STORAGE 권한을 추가하고, 모든 파일에 대한 접근 권한을 허용할 수 있는 시스템 창을 호출해야 합니다. 또한 외부 폴더에 접근하기 위해서는 Manifest의 appliction 태그 안에 android:requestLegacyExternalStorage="true"를 추가해야 합니다.

 

Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

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

    <!--모든 파일에 대한 접근 권한 api level 30이상부터 필요-->
        <uses-permission
            android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
            tools:ignore="ScopedStorage" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:requestLegacyExternalStorage="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Android_storage_file_read"
        tools:targetApi="31">
        <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>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

 

MainActivity

package com.example.android_storage_file_read

import android.Manifest.permission.READ_EXTERNAL_STORAGE
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat


class MainActivity : AppCompatActivity() {
    companion object {
        private const val TAG = "MainActivity Log"
    }

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

        Log.d(TAG, "onCreate: Build.VERSION.SDK_INT : ${Build.VERSION.SDK_INT}")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (!Environment.isExternalStorageManager()) {
                val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
                startActivity(intent)
            }
        } else {
            checkStoragePermissions()
        }

        findViewById<Button>(R.id.button).setOnClickListener {
            try {
                ReadDeviceFile.apply {
                    val files = getFiles("/sdcard/Download")
                    Log.d(TAG, "onCreate: files : $files")
                    val file = getFileOne("/sdcard/Download", "readFile")
                    val result = readTextFile(file)
                    Log.d(TAG, "onCreate: result : $result")
                }
            } catch (e: Exception) {
                Log.e(TAG, "read error", e)
            }
        }

    }


    private fun checkStoragePermissions() {

        try {
            val permission = ContextCompat.checkSelfPermission(
                this,
                READ_EXTERNAL_STORAGE
            )

            if (permission == PackageManager.PERMISSION_DENIED) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    requestPermissions(
                        arrayOf(READ_EXTERNAL_STORAGE),
                        1000
                    )
                }
                return
            }
        } catch (e: Exception) {
            Log.d(TAG, "checkStoragePermissions error : $e")
        }

    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String?>, grandResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grandResults)
        if (requestCode == 1000) {
            var checkResult = true

            for (result in grandResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    checkResult = false
                    break
                }
            }
        }
    }


}

 

 

 

2. ReadDeviceFile

ReadDeviceFile obejct에는 3개의 함수가 있습니다. 

- getFile : 경로를 입력하면 해당 경로에 있는 모든 파일과 폴더들을 불러올 수 있습니다. 

- getFiles : 경로와 file이름을 입력하면 해당 파일을 리턴합니다.

- readTextFile : txt파일을 전달하면 내용을 읽을 수 있습니다. 

import java.io.BufferedReader
import java.io.File
import java.io.FileReader

object ReadDeviceFile {

    /**
     * Loads files in a specific path.
     */
    fun getFiles(path: String): ArrayList<File> {

        val files = File(path).listFiles()

        if (files.isNullOrEmpty()) return arrayListOf()

        return files.toCollection(ArrayList())
    }

    /**
     * Loads a file in a specific path.
     */
    fun getFileOne(path: String, fileName: String): File {
        val files = File(path).listFiles()

        if (files.isNullOrEmpty()) throw Exception("The files do not exist in the $path")

        var filePath = ""

        for (f in files) {
            if (f.name.contains(fileName)) {
                filePath = f.path
                break
            }
        }

        if (filePath.isEmpty()) throw Exception("$fileName does not exist in $path.")

        val file = File(filePath)

        if (!file.exists()) throw  Exception("File is not exists")

        return file
    }

    /**
     * Read the contents of a text file
     */
    fun readTextFile(file: File): StringBuilder {
        val fileType = file.name.toString().substring(file.name.length - 3, file.name.length)
        if (fileType != "txt") {
            throw Exception("${file.name} is not a text file")
        }
        val reader = BufferedReader(FileReader(file))
        val textBuilder = StringBuilder()
        var line: String?
        while (reader.readLine().also { line = it } != null) {
            textBuilder.append(line)
            textBuilder.append("\n")
        }
        return textBuilder
    }
}

 

 

 

소스코드 

https://github.com/jinhan38/android_storage_file_read