5주차. FLO 앱 클론 코딩 - MediaPlayer & SharedPreferences

변현섭·2023년 10월 22일
0

5th UMC Android Study

목록 보기
5/10

✅ 5주차 목표

  • MediaPlayer를 사용하여 MP3 파일을 재생할 수 있다.
  • Activity의 LifeCycle을 이해하고, 이를 적절히 활용할 수 있다.
  • SharedPreferences의 개념을 이해하고, 이를 사용할 수 있다.

1. MediaPlayer로 MP3 파일 재생하기

1) MP3 파일 재생하기

① res 디렉토리 하위로 raw 디렉토리를 생성하고, 그 안에 라일락 mp3 파일을 넣는다.

  • mp3 파일의 이름은 반드시 소문자로 작성하도록 한다.

② Song 클래스에 아래의 내용을 추가한다.

data class Song(
    val title : String = "",
    val singer : String = "",
    var second: Int = 0,
    var playTime: Int = 60,
    var isPlaying : Boolean = false,
    var music : String = "" // 재생할 MP3 파일의 이름
)

③ MainActivity에서 song을 생성할 때와 Intent로 전달할 때, music도 함께 전달해주어야 한다.

override fun onCreate(savedInstanceState: Bundle?) {
	val song = Song(binding.mainMiniplayerTitleTv.text.toString(),
    	binding.mainMiniplayerSingerTv.text.toString(), 0, 60, false, "music_lilac")
    
    activityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
            val data = result.data
            if (data != null) {
                val message = data.getStringExtra("message")
                Log.d("message", message!!)
                Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
            }
        }
    }
    
    binding.mainPlayerCl.setOnClickListener {
        val intent = Intent(this, SongActivity::class.java)
        intent.putExtra("title", song.title)
        intent.putExtra("singer",song.singer)
        intent.putExtra("second", song.second)
        intent.putExtra("playTime", song.playTime)
        intent.putExtra("isPlaying", song.isPlaying)
        intent.putExtra("music", song.music)
        activityResultLauncher.launch(intent)
    }
}

④ SongActivity를 아래와 같이 수정한다.

class SongActivity : AppCompatActivity() {

    lateinit var binding : ActivitySongBinding
    lateinit var song : Song
    lateinit var timer : Timer
    
    // 추후에 미디어 플레이어를 해제하기 위해 nullable로 선언
    private var mediaPlayer : MediaPlayer? = null 
    ...
    
    private fun initSong() {
        if(intent.hasExtra("title") && intent.hasExtra("singer")) {
            song = Song(
                intent.getStringExtra("title")!!,
                intent.getStringExtra("singer")!!,
                intent.getIntExtra("second", 0),
                intent.getIntExtra("playTime", 0),
                intent.getBooleanExtra("isPlaying", false),
                intent.getStringExtra("music")!!
            )
        }

        startTimer()
    }
    
    private fun setPlayer(song : Song) {
        binding.songMusicTitleTv.text = intent.getStringExtra("title")!!
        binding.songSingerNameTv.text = intent.getStringExtra("singer")!!
        binding.songStartTimeTv.text = String.format("%02d:%02d", song.second / 60, song.second % 60)
        binding.songEndTimeTv.text = String.format("%02d:%02d", song.playTime / 60, song.playTime % 60)
        binding.songProgressSb.progress = (song.second * 1000 / song.playTime)
        
        val music = resources.getIdentifier(song.music, "raw", this.packageName)
        mediaPlayer = MediaPlayer.create(this, music)
        setPlayerStatus(song.isPlaying)
    }

    fun setPlayerStatus (isPlaying : Boolean){
        song.isPlaying = isPlaying
        timer.isPlaying = isPlaying

        if(isPlaying){ // 재생중
            binding.songMiniplayerIv.visibility = View.GONE
            binding.songPauseIv.visibility = View.VISIBLE
            mediaPlayer?.start()
        } else { // 일시정지
            binding.songMiniplayerIv.visibility = View.VISIBLE
            binding.songPauseIv.visibility = View.GONE
            
            // 재생 중이 아닐 때, pause를 호출하면 에러가 나기 때문에 이를 방지하기 위한 조건문
            if(mediaPlayer?.isPlaying == true) { 
                mediaPlayer?.pause()
            }
        }
    }
    ...
  • resources.getIdentifier
    • 앱 리소스의 식별자를 알아내기 위해 사용한다.
    • 검색할 리소스의 이름, 리소스의 유형(디렉토리명), 리소스가 속한 패키지 이름(일반적으로 this.package를 사용)을 입력인자로 갖는다.
  • 즉, 이 패키지 안에 있는 raw(음악 파일 등의 원시 파일을 의미) 디렉토리에서 song.music의 이름을 가진 mp3 파일의 식별자를 반환한다.
  • MediaPlayer.create(this, music): context와 음악 리소스 ID를 입력 값으로 갖는 MediaPlayer 객체를 생성한다.

이제 코드를 실행시켜보자. 재생 버튼을 누르면 음악이 재생되고 일시정지 버튼을 누르면 음악이 일시정지될 것이다.

2) 백그라운드 재생 제한하기

현재는 SongActivity가 종료되거나, 홈 버튼을 눌러 보이지 않게 되더라도 음악이 계속해서 재생된다. SongActivity가 종료될 때에는 Activity LifeCycle의 onDestroy()가 호출되고, 홈 버튼을 눌렀을 때에는 onPause()가 호출되는데, 문제는 onDestroy가 호출될 때이다.

지난번 포스팅에서도 잠깐 설명했듯이 onDestroy가 호출되면, Activity에 할당된 쓰레드가 정리되기 때문에 Timer가 동작하지 않는다. 즉, 음악은 재생되고 있는데 재생 시간 및 SeekBar는 전혀 움직이지 않는, 다소 이상한 상황이 연출될 것이다.

이러한 문제를 해결하기 위해 LifeCycle의 개념을 사용할 수 있다. SongActivity에 아래의 내용을 추가한다.

override fun onPause() {
    super.onPause()
    setPlayerStatus(false)
}

override fun onDestroy() {
    super.onDestroy()
    timer.interrupt()
    mediaPlayer?.release() // 미디어 플레이어가 갖고 있던 리소스를 해제한다.
    mediaPlayer = null // 미디어 플레이어를 해제한다.
}

이제 코드를 실행시킨 후 음악을 재생시켜보자. SongActivity를 종료하거나, 홈 버튼을 누를 경우 음악이 멈추는 것을 확인할 수 있다.

2. SharedPreferences 사용하기

SongActivity가 pause 될 때, song에 대한 정보를 SharedPreferences에 저장하고, 이 정보를 MainActivity의 재생 Bar에서 보여줄 수 있도록 만들어보자.

1) SharedPreferences에 데이터 저장하기

song의 title, singer, second, playTime 등의 정보를 일일이 SharedPreferences에 putString 하는 방식이 아닌, song을 Json으로 변환하여 통째로 SharedPrefernces에 putString 하는 방식을 사용하도록 하겠다.

① Module 수준의 build.gradle 파일에 gson 관련 의존성을 추가한다.

implementation("com.squareup.retrofit2:converter-gson:2.9.0")

※ gson
Gson은 JSON(JavaScript Object Notation)과 Java 객체 간의 변환을 간단하게 처리할 수 있도록 도와주는 라이브러리로, Java 객체를 JSON 형식으로 직렬화하거나 JSON 데이터를 Java 객체로 역직렬화하는 작업을 수행한다.

② SongActivity에 아래의 내용을 추가한다.

class SongActivity : AppCompatActivity() {

    lateinit var binding : ActivitySongBinding
    lateinit var song : Song
    lateinit var timer : Timer
    
    // 추후에 미디어 플레이어 해제를 위해 nullable로 선언
    private var mediaPlayer : MediaPlayer? = null 
    private var gson : Gson = Gson()
    ...
    
    override fun onPause() {
        super.onPause()
        setPlayerStatus(false)
        
        song.second = (song.playTime * binding.songProgressSb.progress) / 100000
        val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE)
        val editor = sharedPreferences.edit()
        val songToJson = gson.toJson(song)
        editor.putString("songData", songToJson)
        Log.d("songData", songToJson.toString())
        editor.apply()
    }
    ...
  • (song.playTime * binding.songProgressSb.progress) / 100000
    • song이 현재 몇 초까지 재생되었는지는 동적으로 알아내야 하기 때문에 song.second를 계산하는 로직을 추가한다.
    • 십만분율에 현재까지의 playTime을 곱하여 몇 초까지 재생되었는지를 계산한다.
  • getSharedPreferences("song", MODE_PRIVATE)
    • 앱의 SharedPreferences 객체를 가져오기 위해 사용한다.
    • "song"은 SharedPreferences의 이름을 나타내며, MODE_PRIVATE은 접근 권한을 지정자로, 여기서는 현재 앱에서만 SharedPreferences에 접근 가능하도록 설정하고 있다.
  • sharedPreferences.edit(): 값을 추가, 수정, 삭제하기 위해 SharedPreferences 편집기를 가져온다.
  • putString("songData", songToJson)
    • SharedPreferences 편집기에 song 객체를 JSON 문자열 형태로 저장한다.
    • "songData"는 이 데이터의 키(key)가 되며, songToJson은 해당 키에 대한 값(value)이 된다.
  • apply() : SharedPreferences 편집기에 저장된 변경 사항을 적용한다. commit 대신 apply를 사용하는 것이 일반적으로 권장된다.

이로써, SharedPreferences의 song에 대한 정보 저장을 완료하게 된다.

2) SharedPrefernces에서 데이터 가져오기

① MainActivity에서 몇 초까지 재생되었는지를 나타내기 위해 activity_main.xml에 SeekBar를 추가해주자.

<SeekBar
    android:id="@+id/main_miniplayer_progress_sb"
    android:layout_width="match_parent"
    android:layout_height="10dp"
    android:background="@null"
    android:paddingEnd="0dp"
    android:paddingStart="0dp"
    android:layout_marginBottom="-4dp"
    android:progressBackgroundTint="@color/song_player_bg"
    android:progressTint="@color/song_player"
    android:progress="0"
    android:max="100000"
    android:thumb="@color/transparent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toTopOf="@id/main_player_cl" />

② 이제부터는 song을 직접 생성하는 대신, sharedPreferences에서 가져올 것이기 때문에 MainActivity에서 아래의 내용을 삭제해주도록 하자.

val song = Song(binding.mainMiniplayerTitleTv.text.toString(),
            binding.mainMiniplayerSingerTv.text.toString(), 0, 60, false, "music_lilac") 삭제

③ MainActivity를 아래와 같이 수정한다.

class MainActivity : AppCompatActivity() {

    lateinit var binding : ActivityMainBinding
    lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
    private var song : Song = Song()
    private var gson : Gson = Gson()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setTheme(R.style.Theme_UMCFlo)
		...

    override fun onStart() {
        super.onStart()
        val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE)
        val jsonToSong = sharedPreferences.getString("songData", null)
        Log.d("jsonToSong", jsonToSong.toString())
        song = if(jsonToSong == null) { // 최초 실행 시
            Song("라일락", "아이유(IU)", 0, 60, false, "music_lilac")
        } else { // SongActivity에서 노래가 한번이라도 pause 된 경우
            gson.fromJson(jsonToSong, Song::class.java)
        }

        setMiniPlayer(song)
    }

    private fun setMiniPlayer(song : Song) {
        binding.mainMiniplayerTitleTv.text = song.title
        binding.mainMiniplayerSingerTv.text = song.singer
        binding.mainMiniplayerProgressSb.progress = (song.second * 100000 / song.playTime)
    }
}
  • onStart(): 다른 Activity에서 다시 돌아올 때, ui를 업데이트하려면 onResume보다 onStart를 사용하는 것이 일반적이다. (onCreate는 호출되지 않으므로 주의한다.)
  • sharedPreferences
    • song이라는 이름을 가진 sharedPrefernces를 가져온다. 이 sharedPreferences에는 SongActivity에서 재생 중이던 노래에 대한 정보가 담겨있다.
    • getString: sondData라는 key에 매핑되는 value를 가져온다. 만약, 해당하는 value가 없다면 null을 가져온다.
  • setMiniPlayer
    • MainActivity의 재생 Bar에 나타날 정보를 설정하는 메서드이다.
    • 일단은, SongActivity에서 한번도 노래를 실행한 적이 없다하더라도 기본적으로 아이유의 라일락이 표시되도록 하였다.

이제 코드를 실행시켜보자. SongActivity에서 음악을 재생한 후, 홈 버튼을 눌러 onPause()를 호출한다. 이후 앱을 종료하고 다시 앱을 실행하면, 아래와 같이 MainActivity의 재생 Bar에서 음악이 몇 초까지 진행되었는지 나타나게 된다.

3. 메모장 만들기

실제 FLO 앱에는 없지만, LifeCycle과 SharedPreferences를 조금 더 확실하게 학습해보자는 차원에서 메모장을 만드는 실습을 진행해보겠다. 별도의 프로젝트를 만들어도 되지만, 여기서는 FLO 앱 내에서 구현해보기로 한다.

1) 메모 화면에서 작성한 내용을 확인 화면에서 보여주기

① memo 작성에 사용될 아이콘을 memo라는 이름으로 drawable 디렉토리에 추가한다.

  • 아이콘을 만들기 귀찮다면, 버튼으로 만들어도 된다.

② fragment_home.xml 파일에 아래와 같이 아이콘을 배치한다.

<ImageView
    android:id="@+id/home_pannel_btn_memo_iv"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:layout_marginTop="20dp"
    android:layout_marginLeft="20dp"
    android:src="@drawable/memo"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

③ 메모장 화면을 구성하기 위해 MemoActivity를 생성한다.

④ HomeFragment에 위 아이콘에 대한 클릭 이벤트 리스너를 작성해주자.

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentHomeBinding.inflate(inflater, container, false)
        ...
        
        binding.homePannelBtnMemoIv.setOnClickListener {
            val intent = Intent(requireActivity(), MemoActivity::class.java)
            startActivity(intent)
        }
        ...

⑤ activity_memo.xml 파일에 아래의 내용을 입력한다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MemoActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:text="My Memo"
        android:textSize="30sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="20dp"
        android:layout_marginTop="100dp"
        app:counterMaxLength="200"
        app:counterEnabled="true"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/memo_et"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="메모를 입력하세요" />

    </com.google.android.material.textfield.TextInputLayout>

    <Button
        android:id="@+id/next_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="20dp"
        android:layout_marginBottom="20dp"
        android:text="작성 완료"
        android:textSize="25sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

⑥ MemoCheckActivity를 생성한다.

⑦ MemoActivity에서 작성 완료 버튼을 클릭했을 때 MemoCheckActivity로 전환되도록 하는 클릭 이벤트 리스너를 추가하자.

class MemoActivity : AppCompatActivity() {

    lateinit var binding : ActivityMemoBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMemoBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.nextBtn.setOnClickListener {
            val intent = Intent(this, MemoCheckActivity::class.java)
            val memoTxt = binding.memoEt.text.toString()
            intent.putExtra("memo", memoTxt)
            startActivity(intent)
        }
    }
}

⑧ activity_memo_check.xml 파일에 아래의 내용을 입력한다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    tools:context=".MemoCheckActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        android:text="My Memo Check"
        android:textSize="30sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/memo_check_text"
        android:text="memo text"
        android:gravity="center"
        android:textSize="30sp"
        android:textStyle="bold"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

⑨ 이제 MemoCheckActivity에서 intent로 전달받은 메모를 띄워주기만 하면 된다.

class MemoCheckActivity : AppCompatActivity() {

    lateinit var binding : ActivityMemoCheckBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMemoCheckBinding.inflate(layoutInflater)
        setContentView(binding.root)

        if(intent.hasExtra("memo")) {
            binding.memoCheckText.text = intent.getStringExtra("memo")!!
        }
    }
}

이제 코드를 실행시켜보자. MemoActivity에서 입력한 내용이 MemoCheckActivity에 잘 나타날 것이다.

2) 작성 중이던 메모 복원하기

메모를 작성하던 도중 어떠한 이유로 onPause가 호출되었다고 가정해보자. 이 때, onPause() 콜백 메서드를 이용하여 작성 중이던 메모를 SharedPreferences에 저장하면, 나중에 다시 앱을 실행할 때 메모를 이어서 작성할 수 있다. (만약, 아무 것도 작성하지 않은 상태에서 onPause가 호출되면, 아무 것도 저장하지 않는다.) 이 기능을 직접 구현해보도록 하겠다.

① MemoActivity의 onPause 메서드를 오버라이딩하자.

override fun onPause() {
    super.onPause()
    val sharedPreferences = getSharedPreferences("memo", MODE_PRIVATE)
    val editor = sharedPreferences.edit()
    val tempMemo = binding.memoEt.text.toString()
    
    if(tempMemo.isNotEmpty()) {
        editor.putString("tempMemo", tempMemo)
        Log.d("tempMemo", tempMemo)
        editor.apply()
    }
}

② 재시작되었을 때, SharedPreferences에서 값을 가져오기 위해 onResume() 콜백 메서드도 오버라이딩 해주자.

override fun onResume() {
    super.onResume()
    val sharedPreferences = getSharedPreferences("memo", MODE_PRIVATE)
    val tempMemo = sharedPreferences.getString("tempMemo", null)
    
    if(tempMemo != null) {
        binding.memoEt.setText(tempMemo)
    }
}

이제 코드를 실행시킨 후 메모를 작성하다가 중간에 홈버튼을 누르거나, 액티비티가 종료시켜보자. 다시 메모장에 들어가면 작성 중이던 내용이 복원되는 것을 확인할 수 있을 것이다.

3) Dialog와 함께 사용하기

작성 중이던 메모가 있을 경우, 다이얼로그를 활용하여 사용자가 복원을 희망하는지 확인할 수 있다. 즉, "기존에 작성 중이던 메시지를 복원할까요?"라는 물음에 "네"로 응답하면 복원된 메모를 띄워주고, "아니오"로 응답하면 SharedPrefernences에서 기존 내용을 삭제하여 빈 메모를 띄워줄 것이다.

① 안드로이드 대화상자(Dialog)를 만들기 위해 layout 디렉토리 하위로 dialog라는 이름의 Layout Resource File을 추가한다.

② dialog.xml 파일에 아래의 내용을 입력한다.

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

    <TextView
        android:id="@+id/dialog_question"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="10dp"
        android:layout_marginTop="10dp"
        android:text="기존에 작성 중인던\n메모가 있습니다."
        android:textSize="25sp"
        android:textStyle="bold"
        android:textColor="#000000"
        android:gravity="center"
        android:background="@android:color/transparent"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="10dp"
        android:layout_marginTop="10dp"
        android:text="복원하시겠습니까?"
        android:textSize="20sp"
        android:textColor="#000000"
        android:gravity="center"
        android:background="@android:color/transparent"/>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="100dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_marginTop="30dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <Button
                android:id="@+id/yes"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginLeft="30dp"
                android:layout_marginRight="10dp"
                android:layout_weight="1"
                android:text="Yes"
                android:textSize="20sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <Button
                android:id="@+id/no"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginRight="30dp"
                android:layout_marginLeft="10dp"
                android:layout_weight="1"
                android:text="No"
                android:textSize="20sp"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>

③ HomeFragment의 메모장 아이콘 클릭 이벤트 리스너를 아래와 같이 수정한다.

binding.homePannelBtnMemoIv.setOnClickListener {
    val intent = Intent(requireActivity(), MemoActivity::class.java)
    val activity = requireActivity() // fragment에서 SharedPreferences에 접근하려면 context가 필요함.
    val sharedPreferences = activity.getSharedPreferences("memo", AppCompatActivity.MODE_PRIVATE)
    val tempMemo = sharedPreferences.getString("tempMemo", null)
    
    if(tempMemo != null) {
        val dialogView = LayoutInflater.from(activity).inflate(R.layout.dialog, null)
        val builder = AlertDialog.Builder(activity)
            .setView(dialogView)
            .setTitle("메모 복원하기")
            
        val alertDialog = builder.show()
        val yesBtn = alertDialog.findViewById<Button>(R.id.yes)
        val noBtn = alertDialog.findViewById<Button>(R.id.no)
        
        yesBtn!!.setOnClickListener {
            startActivity(intent)
        }
        
        noBtn!!.setOnClickListener {
            val editor = sharedPreferences.edit()
            editor.remove("tempMemo")
            editor.apply()
            startActivity(intent)
        }
        
    } else {
        startActivity(intent)
    }
}

코드를 실행해보자. 작성 중이던 메모가 있을 경우 아래와 같이 Android Dialog가 표시된다. 이 때 Yes를 누르면, 기존 방식대로 복원된 메모가 나타나고, No를 누르면 저장된 내용이 사라지면서 빈 메모가 나타나게 된다.

profile
LG전자 Connected Service 1 Unit 연구원 변현섭입니다.

0개의 댓글