-
TECHIT 앱 스쿨 2기: Android 46일차 (23.07.04)[THEC!T] 앱 스쿨2기 : Android 2023. 7. 5. 00:59728x90
자료 출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 내용
오늘은 어플리케이션 클래스에 대한 설명으로 시작하였습니다.
어플리케이션 클래스는 간단하게 말하면 같은 애플리케이션 당 하나씩 둘 수 있으며, 애플리케이션 내부라면 어디서든 가져다가 사용할 수 있습니다.
사용 예시
package com.test.android67_applicationclass import android.app.Application class AppClass: Application() { var value = 0 var value2 = 0.0 lateinit var value3: String }
package com.test.android67_applicationclass import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import com.test.android67_applicationclass.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { lateinit var activityMainBinding : ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activityMainBinding = ActivityMainBinding.inflate(layoutInflater) activityMainBinding.run{ buttonMain.setOnClickListener { //ApplicatonClass // 애플리케이션 당 하나씩 둘 수 있으며 어디서든지 접근이 가능하다. // Application을 상속받은 클래스를 만드로 프로퍼티들을 정의한다. // AndroidManfest.xml에 application 태그의 name 속성제 지정하여 사용한다. val appClass = application as AppClass appClass.value = 100 appClass.value2 = 11.11 appClass.value3 = "문자열" val secondIntent = Intent(this@MainActivity, SecondActivity::class.java) startActivity(secondIntent) } } setContentView(activityMainBinding.root) } }
package com.test.android67_applicationclass import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import com.test.android67_applicationclass.databinding.ActivitySecondBinding class SecondActivity : AppCompatActivity() { lateinit var activitySecondBinding: ActivitySecondBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) activitySecondBinding = ActivitySecondBinding.inflate(layoutInflater) activitySecondBinding.run{ // AppleicationClass 객체를 가져온다. val appClass = application as AppClass textViewSecond.text = "${appClass.value}\n" textViewSecond.append("${appClass.value2}\n") textViewSecond.append("${appClass.value3}") } setContentView(activitySecondBinding.root) } }
다음으로는 내외부 저장소와, FileStream 에 대해서 알려주셨습니다.
내부 저장소:
내부 저장소는 애플리케이션의 기본 저장 공간으로 사용됩니다. 앱이 설치되면 시스템에 의해 생성되고 관리됩니다. 일반적으로 앱 데이터, 데이터베이스, 설정, 캐시 파일 등을 저장하는 데 사용됩니다. 다른 앱에서 액세스할 수 없으며, 앱을 삭제하면 내부 저장소의 데이터도 함께 삭제됩니다. 따라서 내부 저장소에 저장된 데이터는 앱의 범위에 제한되어 있습니다.
외부 저장소:
외부 저장소는 디바이스의 외부에 위치한 저장 장치를 가리킵니다. 일반적으로 SD 카드 또는 기타 외부 저장 장치를 의미합니다. 외부 저장소는 앱 간 데이터 공유, 미디어 파일 (사진, 비디오, 음악 등) 저장 등에 사용됩니다. 사용자가 앱을 삭제하더라도 외부 저장소의 데이터는 보존됩니다. 다른 앱에서도 액세스할 수 있으며, 일부 권한을 통해 외부 저장소에 데이터를 읽고 쓸 수 있습니다.
내부 저장소와 외부 저장소의 주요 차이점은 다음과 같습니다:
앱의 범위: 내부 저장소는 앱 자체에서만 액세스할 수 있으며, 외부 저장소는 다른 앱과 공유할 수 있습니다.
데이터 보존: 앱 삭제 시 내부 저장소의 데이터는 함께 삭제되지만, 외부 저장소의 데이터는 보존됩니다.
용량 제한: 내부 저장소는 디바이스의 내부 메모리에 저장되기 때문에 제한된 용량을 가질 수 있지만, 외부 저장소는 추가적인 저장 장치로 확장할 수 있습니다.사용예시
내부저장소 쓰기
// MODE_PRIVATE : 덮어 씌우기 // MODE_APPEND : 이어서 쓰기 val fos = openFileOutput("data1.dat", MODE_PRIVATE) val dos = DataOutputStream(fos)
내부 저장소 읽기
val fis = openFileInput("data1.dat") val dis = DataInputStream(fis)
* 객체일 경우 : ObjectInputStream(fis)
이외에는 일반적인 FileStream 사용법과 동일합니다.
외부저장소 쓰기
val filePath = getExternalFilesDir(null).toString() val fos = FileOutputStream("${filePath}/data2.dat") val dos = DataOutputStream(fos)
외부저장소 읽기
// 외부 저장소의 경로를 가져온다 // emulated/Android/data/패키지명/files // getExtermalFilesDir 메서드의 매개변수에는 문자열을 넣어줄 수 있으며 // files의 하위 폴더 이름을 넣어서 사용할 수 있다. // null을 넣으면 files까지의 경로가 된다. val filePath = getExternalFilesDir(null).toString() val fis = FileInputStream("${filePath}/data2.dat") val dis = DataInputStream(fis)
그리고 마지막으로는 FileApp을 통한 접근에 대해서 알려주셨습니다.
사용예시
lateinit var writeActivityLauncer: ActivityResultLauncher<Intent> lateinit var readActivityLauncher: ActivityResultLauncher<Intent>
// FileApp을 통한 접근 button5.setOnClickListener { // 파일 관리 앱의 액티비티를 실행한다. val fileIntent = Intent(Intent.ACTION_CREATE_DOCUMENT) fileIntent.addCategory(Intent.CATEGORY_OPENABLE) // MimeType을 설정한다. // MimeType이란? 파일에 저장되어 있는 데이터의 양식이 무엇인지를 타나내는 문자열 // https://developer.mozilla.org/ko/docs/Web/HTTP/Basics_of_HTTP/MIME_types fileIntent.type = "*/*" writeActivityLauncer.launch(fileIntent) } button6.setOnClickListener { // 파일 관리 앱의 액티비티를 실행한다. val fileIntent = Intent(Intent.ACTION_OPEN_DOCUMENT) fileIntent.type = "*/*" readActivityLauncher.launch(fileIntent) }
// 쓰기용 런처 val contracts1 = ActivityResultContracts.StartActivityForResult() writeActivityLauncer = registerForActivityResult(contracts1){ // 사용자가 저장할 파일을 선택하고 돌아오면 ResultCode는 RESULT_OK 가 들어온다. if(it.resultCode == RESULT_OK){ // 사용자가 선택한 파일의 정보를 가지고 있는 Intent로 파일 정보를 가져온다. if(it.data != null){ // 저장할 파일에 접근할 수 있는 객체로 부터 파일 정보를 가져온다. // w : 쓰기, a : 이어쓰기, r : 읽기 val des1 = contentResolver?.openFileDescriptor(it.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() fos.close() activityMainBinding.textView.text = "Downloads 폴더에 저장." } } } // 읽기용 런처 val contracts2 = ActivityResultContracts.StartActivityForResult() readActivityLauncher = registerForActivityResult(contracts2){ if(it.resultCode == RESULT_OK){ // 가져온 데이터가 있을 경우에만 if(it.data != null){ // 선택한 파일의 경로 정보를 가져온다. val dest1 = contentResolver.openFileDescriptor(it.data?.data!! , "r") val fis = FileInputStream(dest1?.fileDescriptor) val dis = DataInputStream(fis) val data1 = dis.readInt() val data2 = dis.readDouble() val data3 = dis.readBoolean() val data4 = dis.readUTF() dis.close() activityMainBinding.textView.text = "data1 : ${data1}\n" activityMainBinding.textView.append("data2 : ${data2}\n") activityMainBinding.textView.append("data3 : ${data3}\n") activityMainBinding.textView.append("data4 : $data4") } } }
이후에는 하기 문제를 내주신 후에 각자 작성해볼 시간을 주신 후 같이 작성 및 설명을 해주셨습니다.
강사님이 작성해주시면서 설명해주신 코드와 제가 작성한 코드의 차이점으로는 파일을 읽어올때 예외처리에 대한 부분이였습니다. 저의 경우 읽어올 정보가 없을 때 예외가 발생되는 것을 이용하여 while문을 중지 시켰으나, 강사님께서는 저장한 테이터의 갯수 또한 별도로 저장하여 예외처리를 하지 않는 방향으로 작성하셨습니다.
해당 문제에 대한 설명을 마치신 후 상기문제에서 입력받을 데이터는 이름, 나이, 키, 몸무게 이다. 라는 조건으로 변경하여 문제를 내주셨습니다. (복습의 의미) 추가로 데이터가 입력되지 않은 것이 있을 때 팝업창으로 알려주는 기능을 추가해 보았습니다.
해당 문제에 대하여 작성한 애플리케이션의 작동 영상입니다.
마무리
요즘 더워서 그런지 아니면 내용의 난이도가 올라가서 그런지 모르겠지만, 약간 슬럼프 비슷하게 온 것 같습니다.
알고리즘 공부도 진전이 없고, 복습을 하고는 있지만 뭔가 막혀있는 듯한 느낌이고, 심지어 몸상태도 좋지않아 총체적 난국 인 것 같습니다. 그래도 다행인 것은 오늘 배운 내용에 대해서는 지금까지 배웠던 파일 입출력과 일부 차이만 있을 뿐 큰 차이는 없기에 이해하기 수월하여 좋았습니다.
오늘의 마음가짐
이또한 지나가리라.....
'[THEC!T] 앱 스쿨2기 : Android' 카테고리의 다른 글
TECHIT 앱 스쿨 2기: Android 51 ~ 52일차 (23.07.11 ~ 12) (0) 2023.07.12 TECHIT 앱 스쿨 2기: Android 47일차 (23.07.05) (0) 2023.07.05 TECHIT 앱 스쿨 2기: Android 44 ~ 45일차 (23.07.03) (0) 2023.07.03 TECHIT 앱 스쿨 2기: Android 43일차 (23.06.28) (0) 2023.06.29 TECHIT 앱 스쿨 2기: Android 42일차 (23.06.27) (0) 2023.06.27