diff --git a/Lize/.idea/misc.xml b/Lize/.idea/misc.xml index 0c26a0c..fd639dc 100644 --- a/Lize/.idea/misc.xml +++ b/Lize/.idea/misc.xml @@ -14,17 +14,26 @@ + + + + + + + - + + + diff --git a/Lize/app/build.gradle b/Lize/app/build.gradle index 813348c..57b14e1 100644 --- a/Lize/app/build.gradle +++ b/Lize/app/build.gradle @@ -2,6 +2,7 @@ plugins { id 'com.android.application' id 'kotlin-android' + id 'kotlin-kapt' } android { @@ -46,4 +47,9 @@ dependencies { testImplementation 'junit:junit:4.+' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + //RoomDB 라이브러리 + implementation 'androidx.room:room-ktx:2.4.2' + implementation 'androidx.room:room-runtime:2.4.2' + kapt 'androidx.room:room-compiler:2.4.2' } \ No newline at end of file diff --git a/Lize/app/src/main/AndroidManifest.xml b/Lize/app/src/main/AndroidManifest.xml index 4ab4d83..5967fd3 100644 --- a/Lize/app/src/main/AndroidManifest.xml +++ b/Lize/app/src/main/AndroidManifest.xml @@ -15,6 +15,14 @@ android:name=".SongActivity" android:exported="true"> + + + + ? = null //수록곡 + var coverImg: Int? = null + //, + //var songs: ArrayList? = null //수록곡 ) diff --git a/Lize/app/src/main/java/com/example/flo/AlbumDao.kt b/Lize/app/src/main/java/com/example/flo/AlbumDao.kt new file mode 100644 index 0000000..cfe4208 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/AlbumDao.kt @@ -0,0 +1,35 @@ +package com.example.flo + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface AlbumDao { + + @Insert + fun insert(album:Album) + + @Query("SELECT * FROM AlbumTable") + fun getAlbums():List + + //사용자가 좋아요를 누른 앨범 추가 + @Insert + fun likeAlbum(like:Like) + + @Query("SELECT id FROM LikeTable WHERE userId = :userId AND albumId = :albumId") + //AlbumFragment에 들어갈 때, 사용자가 좋아요를 눌렀는 지 누르지 않았는 지 확인 + fun isLikedAlbum(userId: Int, albumId : Int) : Int? + //정보가 없다면 null을 반환하므로 "?"처리 + + @Query("DELETE FROM LikeTable WHERE userId = :userId AND albumId = :albumId") + //AlbumFragment에 들어갈 때, 사용자가 좋아요를 취소할 경우 + fun disLikedAlbum(userId: Int, albumId : Int) + + //LikeTable as LT : LikeTable=LT + //LikeTable as LT LEFT JOIN AlbumTable as AT : 왼쪽의 LT를 기준으로 오른쪽의 AT를 join + //on LT.albumId = AT.id : albumId가 같은 것끼리 join + @Query("SELECT AT.* FROM LikeTable as LT LEFT JOIN AlbumTable as AT on LT.albumId = AT.id WHERE LT.userId = :userId") + //좋아요한 앨범을 가져오기 + fun getLikedAlbums(userId:Int):List +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/AlbumFragment.kt b/Lize/app/src/main/java/com/example/flo/AlbumFragment.kt index 006ca0b..f63d0ff 100644 --- a/Lize/app/src/main/java/com/example/flo/AlbumFragment.kt +++ b/Lize/app/src/main/java/com/example/flo/AlbumFragment.kt @@ -5,6 +5,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.example.flo.databinding.FragmentAlbumBinding import com.google.android.material.tabs.TabLayoutMediator @@ -16,6 +17,8 @@ class AlbumFragment : Fragment() { private val information = arrayListOf("수록곡", "상세정보", "영상") + private var isLiked : Boolean = false + private var gson: Gson = Gson() //activity : onCreate vs fragment : onCreateView @@ -29,7 +32,12 @@ class AlbumFragment : Fragment() { //argument에서 데이터를 꺼내와서 binding val albumJson = arguments?.getString("album") val album = gson.fromJson(albumJson, Album::class.java) + + //isLiked 초기설정 + isLiked = isLikedAlbum(album.id) + setInit(album) //binding작업 수행 + setOnClickListeners(album) //fragment_album에서 back누르면 다시 HomeFragment로 이동 binding.albumBackIv.setOnClickListener{ @@ -54,6 +62,61 @@ class AlbumFragment : Fragment() { binding.albumImgIv.setImageResource(album.coverImg!!) binding.albumTitleMainTv.text = album.title.toString() binding.albumSingerMainTv.text = album.singer.toString() + + //좋아요가 눌리면 하트 색 변경 + if(isLiked){ + binding.albumLikeOffIv.setImageResource(R.drawable.ic_my_like_on) + }else{ + binding.albumLikeOffIv.setImageResource(R.drawable.ic_my_like_off) + } + } + + //현재 로그인된 유저정보 가져오기 + private fun getJwt():Int{ + val spf = activity?.getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE) + return spf!!.getInt("jwt", 0) //shardPreferences에서 가져온 값이 없다면 0반환 + } + + //좋아요를 눌렀을 때 DB에 저장 + private fun likeAlbum(userId:Int, albumId:Int){ + val songDB = SongDatabase.getInstance(requireContext())!! + val like = Like(userId, albumId) + //좋아요 눌렀을 때, LikeTable에 정보 추가 + songDB.albumDao().likeAlbum(like) + } + + //Album에서 사용자의 좋아요여부를 알기위함 + private fun isLikedAlbum(albumId:Int):Boolean{ + val songDB = SongDatabase.getInstance(requireContext())!! + val userId = getJwt() + val likeId : Int? = songDB.albumDao().isLikedAlbum(userId, albumId) //어떤 유저가 해당 앨범을 좋아요 눌렀는가 + + return likeId != null //유저가 좋아요 눌렀다면 true / 좋아요X면 false + } + + //사용자가 좋아요를 취소하면, LikeTable에서 해당 앨범 지우기 + private fun disLikedAlbum(albumId:Int){ + val songDB = SongDatabase.getInstance(requireContext())!! + val userId = getJwt() + + songDB.albumDao().disLikedAlbum(userId, albumId) //어떤 유저가 해당 앨범을 좋아요 눌렀는가 + + } + + //좋아요를 눌렀을 때, 클릭이벤트 처리 + private fun setOnClickListeners(album: Album){ + val userId = getJwt() + binding.albumLikeOffIv.setOnClickListener{ + if(isLiked){ //좋아요눌려있는 상태 + //좋아요 취소 + binding.albumLikeOffIv.setImageResource(R.drawable.ic_my_like_off) + disLikedAlbum(album.id) + }else{ //좋아요가 눌려있지 않은 상태 + //좋아요 + binding.albumLikeOffIv.setImageResource(R.drawable.ic_my_like_on) + likeAlbum(userId, album.id) + } + } } diff --git a/Lize/app/src/main/java/com/example/flo/AlbumLockerRVAdapter.kt b/Lize/app/src/main/java/com/example/flo/AlbumLockerRVAdapter.kt new file mode 100644 index 0000000..f4fe8e9 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/AlbumLockerRVAdapter.kt @@ -0,0 +1,59 @@ +package com.example.flo + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.example.flo.databinding.ItemLockerAlbumBinding + +class AlbumLockerRVAdapter (): RecyclerView.Adapter() { + private val albums = ArrayList() + + interface MyItemClickListener{ + fun onRemoveSong(songId: Int) + } + + private lateinit var mItemClickListener: MyItemClickListener + + fun setMyItemClickListener(itemClickListener: MyItemClickListener){ + mItemClickListener = itemClickListener + } + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AlbumLockerRVAdapter.ViewHolder { + val binding: ItemLockerAlbumBinding = ItemLockerAlbumBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: AlbumLockerRVAdapter.ViewHolder, position: Int) { + holder.bind(albums[position]) + holder.binding.itemAlbumMoreIv.setOnClickListener { + mItemClickListener.onRemoveSong(albums[position].id) + removeSong(position) + } + } + + override fun getItemCount(): Int = albums.size + + @SuppressLint("NotifyDataSetChanged") + fun addAlbums(albums: ArrayList) { + this.albums.clear() + this.albums.addAll(albums) + + notifyDataSetChanged() + } + + fun removeSong(position: Int){ + albums.removeAt(position) + notifyDataSetChanged() + } + + inner class ViewHolder(val binding: ItemLockerAlbumBinding) : RecyclerView.ViewHolder(binding.root){ + fun bind(album: Album){ + binding.itemAlbumImgIv.setImageResource(album.coverImg!!) + binding.itemAlbumTitleTv.text = album.title + binding.itemAlbumSingerTv.text = album.singer + } + } + +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/HomeFragment.kt b/Lize/app/src/main/java/com/example/flo/HomeFragment.kt index c4de3a2..75dd1b2 100644 --- a/Lize/app/src/main/java/com/example/flo/HomeFragment.kt +++ b/Lize/app/src/main/java/com/example/flo/HomeFragment.kt @@ -16,6 +16,8 @@ class HomeFragment : Fragment() { private var albumDatas = ArrayList() + private lateinit var songDB : SongDatabase + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -31,14 +33,17 @@ class HomeFragment : Fragment() { // } //ArrayList에 데이터 추가 : 데이터 리스트 생성 더미 데이터 - albumDatas.apply { - add(Album("Butter", "방탄소년단 (BTS)", R.drawable.img_album_exp)) - add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2)) - add(Album("Next Level", "에스파 (AESPA)", R.drawable.img_album_exp3)) - add(Album("Boy with Luv", "방탄소년단 (BTS)", R.drawable.img_album_exp4)) - add(Album("BBoom BBoom", "모모랜드 (MOMOLAND)", R.drawable.img_album_exp5)) - add(Album("Weekend", "태연 (Tae Yeon)", R.drawable.img_album_exp6)) - } +// albumDatas.apply { +// add(Album("Butter", "방탄소년단 (BTS)", R.drawable.img_album_exp)) +// add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2)) +// add(Album("Next Level", "에스파 (AESPA)", R.drawable.img_album_exp3)) +// add(Album("Boy with Luv", "방탄소년단 (BTS)", R.drawable.img_album_exp4)) +// add(Album("BBoom BBoom", "모모랜드 (MOMOLAND)", R.drawable.img_album_exp5)) +// add(Album("Weekend", "태연 (Tae Yeon)", R.drawable.img_album_exp6)) +// } + //songDB에 추가 + songDB = SongDatabase.getInstance(requireContext())!! //songDB초기화 + albumDatas.addAll(songDB.albumDao().getAlbums()) //Adapter-datalist를 연결 val albumRVAdapter = AlbumRVAdapter(albumDatas) diff --git a/Lize/app/src/main/java/com/example/flo/Like.kt b/Lize/app/src/main/java/com/example/flo/Like.kt new file mode 100644 index 0000000..69c3c8f --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/Like.kt @@ -0,0 +1,12 @@ +package com.example.flo + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "LikeTable") +data class Like( + var userId : Int, + var albumId : Int +){ + @PrimaryKey(autoGenerate = true) var id:Int = 0 +} diff --git a/Lize/app/src/main/java/com/example/flo/LockerFragment.kt b/Lize/app/src/main/java/com/example/flo/LockerFragment.kt index c887e68..8f74e49 100644 --- a/Lize/app/src/main/java/com/example/flo/LockerFragment.kt +++ b/Lize/app/src/main/java/com/example/flo/LockerFragment.kt @@ -1,15 +1,19 @@ package com.example.flo +import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.example.flo.databinding.FragmentLockerBinding +import com.google.android.material.tabs.TabLayoutMediator class LockerFragment : Fragment() { lateinit var binding: FragmentLockerBinding + private var information = arrayListOf("저장한 곡", "음악파일", "저장앨범") override fun onCreateView( inflater: LayoutInflater, @@ -18,6 +22,53 @@ class LockerFragment : Fragment() { ): View? { binding = FragmentLockerBinding.inflate(inflater, container, false) + val lockerAdapter = LockerVPAdapter(this) + binding.lockerContentVp.adapter = lockerAdapter + TabLayoutMediator(binding.lockerContentTb, binding.lockerContentVp){ + tab, position -> tab.text = information[position] + }.attach() + + //fragment_locker.xml의 로그인버튼을 누르면 -> activity_login.xml로 이동 + binding.lockerLoginTv.setOnClickListener{ + startActivity(Intent(activity, LoginActivity::class.java)) + } + return binding.root } + + override fun onStart() { + super.onStart() + initViews() + } + + //로그인 상태일 경우 : 로그아웃 텍스트뜨기 + //로그아웃 상태일 경우 : 로그인 텍스트뜨기 + private fun getJwt():Int{ + val spf = activity?.getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE) + return spf!!.getInt("jwt", 0) //shardPreferences에서 가져온 값이 없다면 0반환 + } + + private fun initViews(){ + val jwt : Int = getJwt() + if(jwt == 0){ + binding.lockerLoginTv.text = "로그인" + binding.lockerLoginTv.setOnClickListener{ + startActivity(Intent(activity, LoginActivity::class.java)) + } + }else{ + binding.lockerLoginTv.text = "로그아웃" + binding.lockerLoginTv.setOnClickListener{ + //로그아웃 진행 + logout() + startActivity(Intent(activity, MainActivity::class.java)) + } + } + } + + private fun logout(){ //jwt=0으로 만들기 : 저장된 값X + val spf = activity?.getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE) + val editor = spf!!.edit() + editor.remove("jwt") + editor.apply() + } } \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/LockerVPAdapter.kt b/Lize/app/src/main/java/com/example/flo/LockerVPAdapter.kt new file mode 100644 index 0000000..092c47f --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/LockerVPAdapter.kt @@ -0,0 +1,18 @@ +package com.example.flo + +import androidx.fragment.app.Fragment +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.example.flo.fragment.MusicFileFragment + +class LockerVPAdapter (fragment: Fragment) :FragmentStateAdapter(fragment){ + override fun getItemCount(): Int = 3 + + override fun createFragment(position: Int): Fragment { + return when(position){ + 0 -> SavedSongFragment() + 1 -> MusicFileFragment() + else -> SavedAlbumFragment() + } + } + +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/LoginActivity.kt b/Lize/app/src/main/java/com/example/flo/LoginActivity.kt new file mode 100644 index 0000000..b20d712 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/LoginActivity.kt @@ -0,0 +1,75 @@ +package com.example.flo + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.example.flo.databinding.ActivityLoginBinding + +class LoginActivity : AppCompatActivity(){ + lateinit var binding: ActivityLoginBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityLoginBinding.inflate(layoutInflater) + setContentView(binding.root) + + //회원가입버튼 누르면 activity_login.xml -> activity_signup.xml로 이동 + binding.loginSignUpTv.setOnClickListener{ + startActivity(Intent(this, SignUpActivity::class.java)) + } + + //로그인 버튼을 누르면 아래 코드 실행 + binding.loginSignInBtn.setOnClickListener{ + login() + } + } + + //로그인 + private fun login(){ + //이메일이 입력되지 않은 경우 + if(binding.loginIdEt.text.toString().isEmpty() || binding.loginDirectInputEt.text.toString().isEmpty()){ + Toast.makeText(this, "이메일을 입력해주세요.", Toast.LENGTH_SHORT).show() + return + } + //비밀번호가 입력되지 않은 경우 + if(binding.loginPasswordEt.text.toString().isEmpty()){ + Toast.makeText(this, "비밀번호를 입력해주세요.", Toast.LENGTH_SHORT).show() + return + } + + //정상적으로 입력된 경우 + val email : String = binding.loginIdEt.text.toString() + "@" + binding.loginDirectInputEt.text.toString() + val pwd : String = binding.loginPasswordEt.text.toString() + + //사용자가 입력한 이메일과 패스워드 정보가 회원가입된 정보인지 확인 + val songDB = SongDatabase.getInstance(this)!! + val user = songDB.userDao().getUser(email, pwd) + + //user가 null이 아닐 경우 : DB에서 해당 유저를 찾았을 경우 + user?.let{ + Log.d("LOGIN_ACT/GET_USER", "userId : ${user.id}, &user") + saveJwt(user.id) + startMainActivity() + } + + //user가 null일 경우 + Toast.makeText(this, "회원 정보가 존재하지 않습니다.", Toast.LENGTH_SHORT).show() + } + + //JWT를 저장하는 함수 + private fun saveJwt(jwt: Int){ + val spf = getSharedPreferences("auth", MODE_PRIVATE) + val editor = spf.edit() + + editor.putInt("jwt", jwt) + editor.apply() + } + + //로그인이 끝나면 MainActivity로 전환 + private fun startMainActivity(){ + val intent = Intent(this, MainActivity::class.java) + startActivity(intent) + } +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/MainActivity.kt b/Lize/app/src/main/java/com/example/flo/MainActivity.kt index c4b1118..1aff7cf 100644 --- a/Lize/app/src/main/java/com/example/flo/MainActivity.kt +++ b/Lize/app/src/main/java/com/example/flo/MainActivity.kt @@ -18,6 +18,7 @@ class MainActivity : AppCompatActivity() { lateinit var binding: ActivityMainBinding //binding선언 private var song:Song = Song() + //Song 초기화 방법 : SharedPreference를 통해서 id를 받아옴 -> onStart() 방법2. private var gson:Gson = Gson() override fun onCreate(savedInstanceState: Bundle?) { @@ -40,16 +41,30 @@ class MainActivity : AppCompatActivity() { //startActivity(Intent(this, SongActivity::class.java)) //방법2. SongActivity에서 택배상자를 받아주는 작업 필요 +// 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) +// startActivity(intent) + + //방법3. Data를 넘길 때 intent가 아니라 song의 Id를 넘겨줌 + val editor = getSharedPreferences("song", MODE_PRIVATE).edit() + editor.putInt("songId", song.id) + editor.apply() + 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) startActivity(intent) } + + //노래 DB에 넣기 + inputDummySongs() + + inputDummyAlbums() + initBottomNavigation() //Log메소드를 사용하면 Logcat에서 값 확인 가능 @@ -109,18 +124,141 @@ class MainActivity : AppCompatActivity() { //onResume()에서 실행해도 되지만, onResume()은 이미 액티비티가 실행되고 나서 실행 -> onStart()에서 미리 UI를 구성하는 것이 안정적 override fun onStart() { super.onStart() - //song data반영 - val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE) //sharedPreferences의 이름 : song - val songJson = sharedPreferences.getString("songData", null) //sharedPreferences의 안에 저장된 데이터의 이름 : songData + //방법1. +// //song data반영 +// val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE) //sharedPreferences의 이름 : song +// val songJson = sharedPreferences.getString("songData", null) //sharedPreferences의 안에 저장된 데이터의 이름 : songData +// +// //가져온 데이터를 song객체에 담기 +// song = if(songJson ==null){ //데이터가 존재하지 않을 때, 직접 데이터 지정 +// Song("라일락", "아이유(IU)", 0, 60, false, "music_lilac") +// }else{ //데이터가 존재하면 저장되어있는 데이터 불러오기 +// gson.fromJson(songJson, Song::class.java) //Json->java +// } + + //방법2. + val spf = getSharedPreferences("song", MODE_PRIVATE) + val songId = spf.getInt("songId", 0) - //가져온 데이터를 song객체에 담기 - song = if(songJson ==null){ //데이터가 존재하지 않을 때, 직접 데이터 지정 - Song("라일락", "아이유(IU)", 0, 60, false, "music_lilac") - }else{ //데이터가 존재하면 저장되어있는 데이터 불러오기 - gson.fromJson(songJson, Song::class.java) //Json->java + //DB에서 해당 id에 해당하는 song가져오기 + val songDB = SongDatabase.getInstance(this)!! + + song = if(songId == 0){ //songId가 없다면, + songDB.songDao().getSong(1) //디폴트로 1번 노래 가져오고 + }else{ //있다면, + songDB.songDao().getSong(songId) //해당 Id의 노래 가져오기 } + Log.d("song ID", song.id.toString()) + setMiniPlayer(song) } + + //데이터가 DB에 없다면 DB에 넣어주기 + private fun inputDummySongs(){ + val songDB = SongDatabase.getInstance(this)!! + val songs = songDB.songDao().getSongs() + + //데이터가 원래 있었다면 그냥 함수 종료 + if(songs.isNotEmpty()) return + + //없는 데이터라면 insert + songDB.songDao().insert( + Song( + "LILAC", + "아이유 (IU)", + 0, + 230, + false, + "music_lilac", + R.drawable.img_album_exp2, + false, + ) + ) + + songDB.songDao().insert( + Song( + "COIN", + "아이유 (IU)", + 0, + 230, + false, + "music_coin", + R.drawable.img_album_exp2, + false, + ) + ) + + songDB.songDao().insert( + Song( + "SAVAGE", + "에스파 (asepa)", + 0, + 230, + false, + "music_savage", + R.drawable.img_album_exp3, + false, + ) + ) + + songDB.songDao().insert( + Song( + "WEEKEND", + "태연 (taeyeon)", + 0, + 230, + false, + "music_weekend", + R.drawable.img_album_exp, + false, + ) + ) + + //데이터가 잘 들어갔는지 check용 + val _songs = songDB.songDao().getSongs() + Log.d("DB data", _songs.toString()) + } + + //데이터가 DB에 없다면 DB에 넣어주기 + private fun inputDummyAlbums(){ + val songDB = SongDatabase.getInstance(this)!! + val albums = songDB.albumDao().getAlbums() + + //데이터가 원래 있었다면 그냥 함수 종료 + if(albums.isNotEmpty()) return + + songDB.albumDao().insert( + Album( + 0, + "IU 5th Album 'LILAC'", "아이유 (IU)", R.drawable.img_album_exp2 + ) + ) + + songDB.albumDao().insert( + Album( + 1, + "Butter", "방탄소년단 (BTS)", R.drawable.img_album_exp + ) + ) + + songDB.albumDao().insert( + Album( + 2, + "iScreaM Vol.10 : Next Level Remixes", "에스파 (AESPA)", R.drawable.img_album_exp3 + ) + ) + + songDB.albumDao().insert( + Album( + 3, + "MAP OF THE SOUL : PERSONA", "방탄소년단 (BTS)", R.drawable.img_album_exp4 + ) + ) + + //데이터가 잘 들어갔는지 check용 + val _songs = songDB.songDao().getSongs() + Log.d("DB data", _songs.toString()) + } } \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/MusicFileFragment.kt b/Lize/app/src/main/java/com/example/flo/MusicFileFragment.kt new file mode 100644 index 0000000..5a15337 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/MusicFileFragment.kt @@ -0,0 +1,18 @@ +package com.example.flo.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.example.flo.databinding.FragmentLockerMusicfileBinding + +class MusicFileFragment : Fragment() { + lateinit var binding: FragmentLockerMusicfileBinding + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = FragmentLockerMusicfileBinding.inflate(inflater, container, false) + + return binding.root + } +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/SavedAlbumFragment.kt b/Lize/app/src/main/java/com/example/flo/SavedAlbumFragment.kt new file mode 100644 index 0000000..16ff7d1 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/SavedAlbumFragment.kt @@ -0,0 +1,58 @@ +package com.example.flo + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.flo.databinding.FragmentLockerSavedalbumBinding + +class SavedAlbumFragment : Fragment() { + lateinit var binding: FragmentLockerSavedalbumBinding + lateinit var albumDB: SongDatabase + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = FragmentLockerSavedalbumBinding.inflate(inflater, container, false) + + albumDB = SongDatabase.getInstance(requireContext())!! + + return binding.root + } + + override fun onStart() { + super.onStart() + initRecyclerview() + } + + private fun initRecyclerview(){ + binding.lockerSavedSongRecyclerView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + + val albumRVAdapter = AlbumLockerRVAdapter() + //리스너 객체 생성 및 전달 + + albumRVAdapter.setMyItemClickListener(object : AlbumLockerRVAdapter.MyItemClickListener{ + override fun onRemoveSong(songId: Int) { + albumDB.albumDao().getLikedAlbums(getJwt()) + } + }) + + binding.lockerSavedSongRecyclerView.adapter = albumRVAdapter + + albumRVAdapter.addAlbums(albumDB.albumDao().getLikedAlbums(getJwt()) as ArrayList) + } + + private fun getJwt() : Int { + val spf = activity?.getSharedPreferences("auth" , AppCompatActivity.MODE_PRIVATE) + val jwt = spf!!.getInt("jwt", 0) + Log.d("MAIN_ACT/GET_JWT", "jwt_token: $jwt") + + return jwt + } +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/SavedSongFragment.kt b/Lize/app/src/main/java/com/example/flo/SavedSongFragment.kt new file mode 100644 index 0000000..cb7097c --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/SavedSongFragment.kt @@ -0,0 +1,46 @@ +package com.example.flo + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.flo.databinding.FragmentLockerSavedsongBinding + +class SavedSongFragment : Fragment(){ + + lateinit var binding: FragmentLockerSavedsongBinding + lateinit var songDB: SongDatabase + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + + binding = FragmentLockerSavedsongBinding.inflate(inflater, container, false) + songDB = SongDatabase.getInstance(requireContext())!! + return binding.root + } + + override fun onStart() { + super.onStart() + initRecyclerview() + } + + private fun initRecyclerview(){ + binding.lockerSavedSongRecyclerView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + + val songRVAdapter = SavedSongRVAdapter() + + //DB update + songRVAdapter.setMyItemClickListener(object : SavedSongRVAdapter.MyItemClickListener{ + override fun onRemoveSong(songId: Int) { + //좋아요 해제 상태로 만들기 + songDB.songDao().updateIsLikebyId(false, songId) + } + + }) + + binding.lockerSavedSongRecyclerView.adapter = songRVAdapter + + songRVAdapter.addSongs(songDB.songDao().getLikedSongs(true) as ArrayList) + } +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/SavedSongRVAdapter.kt b/Lize/app/src/main/java/com/example/flo/SavedSongRVAdapter.kt new file mode 100644 index 0000000..e539020 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/SavedSongRVAdapter.kt @@ -0,0 +1,66 @@ +package com.example.flo + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.example.flo.databinding.ItemSongBinding + +class SavedSongRVAdapter() : +RecyclerView.Adapter(){ + private val songs = ArrayList() + + //more버튼 누르면 DB에서도 좋아요눌린 노래 지우기 + interface MyItemClickListener{ + fun onRemoveSong(songId: Int) + } + private lateinit var mItemClickListener: MyItemClickListener + + fun setMyItemClickListener(itemClickListener: MyItemClickListener){ + mItemClickListener = itemClickListener + } + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): SavedSongRVAdapter.ViewHolder{ + val binding: ItemSongBinding = ItemSongBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: SavedSongRVAdapter.ViewHolder, position: Int) { + holder.bind(songs[position]) + + //more버튼 누르면 좋아요한 노래 지우기 + holder.binding.itemSongListMoreIv.setOnClickListener{ + mItemClickListener.onRemoveSong(songs[position].id) + removeSong(position) + + } + } + + override fun getItemCount(): Int = songs.size + + //recyclerView에 모든 좋아요랑 노래를 추가하기 + @SuppressLint("NotifyDataSetChanged") + fun addSongs(songs: ArrayList){ + this.songs.clear() + this.songs.addAll(songs) + + notifyDataSetChanged() + } + + @SuppressLint("NotifyDataSetChanged") + fun removeSong(position: Int){ + songs.removeAt(position) + notifyDataSetChanged() + } + + inner class ViewHolder(val binding: ItemSongBinding) : RecyclerView.ViewHolder(binding.root){ + fun bind(song: Song){ + binding.itemSongImgIv.setImageResource(song.coverImg!!) + binding.itemSongTitleTv.text = song.title + binding.itemSongSingerTv.text = song.singer + } + } + + +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/SignUpActivity.kt b/Lize/app/src/main/java/com/example/flo/SignUpActivity.kt new file mode 100644 index 0000000..f155182 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/SignUpActivity.kt @@ -0,0 +1,54 @@ +package com.example.flo + +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.example.flo.databinding.ActivitySignupBinding + +class SignUpActivity : AppCompatActivity() { + lateinit var binding: ActivitySignupBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivitySignupBinding.inflate(layoutInflater) + setContentView(binding.root) + + //가입완료 버튼을 누르면 회원가입 끝 + binding.signUpSignUpBtn.setOnClickListener{ + signUp() + finish() //회원가입액티비티 끄고 로그인 화면으로 이동 + } + + } + + //회원가입 + //사용자가 입력한 값 가져오기 + private fun getUser() : User{ + //이메일, 비밀번호, 비밀번호 확인 : EditText (사용자가 입력가능) -> 일반 Text를 가져올 때랑 동일하게 사용 + //EditText값을 가져왔다면, String으로 사용할 경우 반드시 toString()처리 해줄것 + val email : String = binding.signUpIdEt.text.toString() + "@" + binding.signUpDirectInputEt.text.toString() + val pwd : String = binding.signUpPasswordEt.text.toString() + + return User(email, pwd) + } + + //실제 회원가입 진행 + private fun signUp(){ + //이메일 형식이 잘못된 경우 + if(binding.signUpIdEt.text.toString().isEmpty() || binding.signUpDirectInputEt.text.toString().isEmpty()){ + Toast.makeText(this, "이메일 형식이 잘못되었습니다.", Toast.LENGTH_SHORT).show() + return + } + //비밀번호와 비밀번호 확인이 일치하지 않는 경우 + if(binding.signUpPasswordEt.text.toString().isEmpty() != binding.signUpPasswordCheckEt.text.toString().isEmpty()){ + Toast.makeText(this, "비밀번호가 일치하지 않습니다.", Toast.LENGTH_SHORT).show() + return + } + + //정상적으로 입력된 경우 + val userDB = SongDatabase.getInstance(this)!! + userDB.userDao().insert(getUser()) + + } +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/Song.kt b/Lize/app/src/main/java/com/example/flo/Song.kt index 1c5ca2a..c478f24 100644 --- a/Lize/app/src/main/java/com/example/flo/Song.kt +++ b/Lize/app/src/main/java/com/example/flo/Song.kt @@ -1,10 +1,18 @@ package com.example.flo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "SongTable") data class Song( val title : String = "", val singer : String = "", var second : Int = 0, //몇 초 인지 var playTime : Int =0, //노래가 얼마나 재생이 되었나 var isPlaying : Boolean = false, //노래가 재생중인가 - var music : String = "" //재생중인 음악을 알 수 있는 변수 -) + var music : String = "", //재생중인 음악을 알 수 있는 변수 + var coverImg: Int? = null, + var isLike: Boolean = false +){ + @PrimaryKey(autoGenerate = true) var id: Int = 0 +} diff --git a/Lize/app/src/main/java/com/example/flo/SongActivity.kt b/Lize/app/src/main/java/com/example/flo/SongActivity.kt index ce0c1db..30972d1 100644 --- a/Lize/app/src/main/java/com/example/flo/SongActivity.kt +++ b/Lize/app/src/main/java/com/example/flo/SongActivity.kt @@ -4,6 +4,7 @@ import android.media.MediaPlayer import android.os.Bundle import android.util.Log import android.view.View +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.example.flo.databinding.ActivitySongBinding import com.google.gson.Gson @@ -19,7 +20,7 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 //var 변수명 : 타입 = 초기화 값 lateinit var binding : ActivitySongBinding //lateinit 전방 선언(java) : 나중에 초기화 //MainActivity에서는 ActivityMainBinding타입 지정 : layout->activity_main.xml 불러오기 - lateinit var song : Song //Song (data class)의 값을 초기화시키기 위한 변수 + //lateinit var song : Song //Song (data class)의 값을 초기화시키기 위한 변수 lateinit var timer : Timer //Timer //음악 재생 @@ -28,6 +29,13 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 //Gson사용 private var gson: Gson = Gson() + //노래 관리 (기존의 song대신) + val songs = arrayListOf() + //DB + lateinit var songDB: SongDatabase + //initSong + var nowPos = 0 + //activity생성 시 처음으로 실행되는 함수 : onCreate //override : 상속받아 변경 / fun : function override fun onCreate(savedInstanceState: Bundle?) { @@ -36,9 +44,24 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 //Inflater : xml에 표기된 layout를 memory에 객체화 시키기 setContentView(binding.root) //setContentView(xml id) : xml에 있는 걸 가져와서 마음대로 쓰기 + initPlayList() initSong() - setPlayer(song) + //setPlayer(song) -> InitSong에서 호출 + + initClickListener() + + + Log.d("test","왜 안됨 개짱나") + } + //리스트에 있는 노래를 불러와서 songs에 저장 + private fun initPlayList(){ + songDB = SongDatabase.getInstance(this)!! + songs.addAll(songDB.songDao().getSongs()) + } + + //clickListener 모음집 + private fun initClickListener(){ //SongActivity에서 down버튼 누르면 MainActivity로 이동 = SongActivity끄기 binding.songDownIb.setOnClickListener{ finish() //현 화면 끄기 @@ -52,12 +75,9 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 setPlayerStatus(false) } - //like버튼을 누르면 off->on으로 전환 + //좋아요 버튼 기능 수행 binding.songLikeOffIv.setOnClickListener{ - setLikeStatus(false) - } - binding.songLikeOnIv.setOnClickListener{ - setLikeStatus(true) + setLike(songs[nowPos].isLike) } //Unlike버튼을 누르면 off->on으로 전환 @@ -67,33 +87,105 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 binding.songUnlikeOnIv.setOnClickListener{ setUnlikeStatus(true) } + + //다음곡으로 넘어가기 + binding.songNextIv.setOnClickListener{ + moveSong(1) + } + + //이전곡으로 넘어가기 + binding.songPreviousIv.setOnClickListener{ + moveSong(-1) + } + } - Log.d("test","왜 안됨 개짱나") + //처음 보여질 음악 초기화 + private fun initSong(){ + //방법1. intent사용 +// 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")!! +// ) +// } + + //방법2. songs에서 index를 통해 관리 -> nowPos사용 + val spf = getSharedPreferences("song", MODE_PRIVATE) + val songId = spf.getInt("songId", 0) + + nowPos = getPlayingSongPosition(songId) + + Log.d("now Song ID", songs[nowPos].id.toString()) + + startTimer() + setPlayer(songs[nowPos]) } - + //좋아요 기능 수행 + private fun setLike(isLike: Boolean){ + songs[nowPos].isLike = !isLike //아직 DB의 값 업데이트X + songDB.songDao().updateIsLikebyId(!isLike, songs[nowPos].id) - 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")!! - ) + if(!isLike){ + binding.songLikeOnIv.setImageResource(R.drawable.ic_my_like_on) + }else{ + binding.songLikeOffIv.setImageResource(R.drawable.ic_my_like_off) + } + } + + //노래 이동하기 + private fun moveSong(direct: Int){ + if(nowPos + direct < 0){ + Toast.makeText(this, "first song", Toast.LENGTH_SHORT).show() + return + } + if(nowPos + direct >= songs.size){ + Toast.makeText(this, "last song", Toast.LENGTH_SHORT).show() + return } + + nowPos += direct + + //새로운 노래 시작 + timer.interrupt() startTimer() + + mediaPlayer?.release() + mediaPlayer = null + + setPlayer(songs[nowPos]) + } + + //넘겨받은 songId값과 같은 노래 인덱스 찾기 in songs + private fun getPlayingSongPosition(songId: Int): Int{ + for(i in 0 until songs.size){ + if(songs[i].id == songId){ + return i + } + } + return 0 } private fun setPlayer(song : Song){ //SongActivity화면을 받아와서 초기화된 song에 대한 데이터를 view rendering - binding.songTitleTv.text = intent.getStringExtra("title") - binding.songSingerTv.text = intent.getStringExtra("singer") + //방법1. +// binding.songTitleTv.text = intent.getStringExtra("title") +// binding.songSingerTv.text = intent.getStringExtra("singer") + //방법2. + binding.songTitleTv.text = song.title + binding.songSingerTv.text = song.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.songAlbumImgIv.setImageResource(song.coverImg!!) binding.songProgressSb.progress = (song.second * 1000 / song.playTime) + + + //현재 재생되는 노래의 정보를 string값으로 가지고 있음 -> res폴더에서 해당 string값을 가진 res을 반환하는 과정이 필요 //resources.getIdentifier(string값, 폴더, this.packageName) 사용 @@ -101,11 +193,18 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 //반환받은 res를 mediaPlayer에게 물려줌 mediaPlayer = MediaPlayer.create(this, music) //이 음악을 재생할거야!라고 알려주기 + //songdata에 따라 좋아요버튼 표시 + if(song.isLike){ + binding.songLikeOnIv.setImageResource(R.drawable.ic_my_like_on) + }else{ + binding.songLikeOffIv.setImageResource(R.drawable.ic_my_like_off) + } + setPlayerStatus(song.isPlaying) } private fun startTimer(){ - timer = Timer(song.playTime, song.isPlaying) + timer = Timer(songs[nowPos].playTime, songs[nowPos].isPlaying) timer.start() } @@ -149,7 +248,7 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 setPlayerStatus(false) //앱을 종료했다가 다시 돌아왔을 때, 이전에 재생되고 있던 song데이터를 적용 //음악이 몇 초 동안 재생되고 있었는가? (밀리세컨드->세컨드 : /1000) - song.second = ((binding.songProgressSb.progress * song.playTime)/100)/1000 + songs[nowPos].second = ((binding.songProgressSb.progress * songs[nowPos].playTime)/100)/1000 //앱이 종료되어도 정보를 기억하고 있어야함 -> sharedPreferences 이용 (내부저장소에 데이터 저장) //데이터 저장 시 @@ -165,8 +264,11 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 // editor.putString("title", song.title) //intent하듯 사용 // editor.putString("singer", song.singer) //... //방법2. 방법1은 코드가 너무 길어지므로 Json 포맷으로 객체를 한번에 넘기기 (Gson이용) - val songJson = gson.toJson(song) //song객체를 Json포맷으로 변경 - editor.putString("songData", songJson) +// val songJson = gson.toJson(song) //song객체를 Json포맷으로 변경 +// editor.putString("songData", songJson) + //방법3. song이 아니라 songId를 보내주기 + editor.putInt("songId", songs[nowPos].id) + editor.apply() //반드시 apply()해야 실제 저장작업 완료 // apply() : git에서의 commit과 push를 담당 @@ -184,7 +286,7 @@ class SongActivity : AppCompatActivity() { //AppCompatActivity : 안드로이드 //함수정의방법 : fun 함수이름(인자){내용} fun setPlayerStatus(isPlaying : Boolean){ - song.isPlaying = isPlaying + songs[nowPos].isPlaying = isPlaying timer.isPlaying = isPlaying if(isPlaying){ diff --git a/Lize/app/src/main/java/com/example/flo/SongDao.kt b/Lize/app/src/main/java/com/example/flo/SongDao.kt new file mode 100644 index 0000000..bfedf35 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/SongDao.kt @@ -0,0 +1,28 @@ +package com.example.flo + +import androidx.room.* + +@Dao +interface SongDao { + @Insert + fun insert(song: Song) + + @Update + fun update(song: Song) + + @Delete + fun delete(song: Song) + + @Query("SELECT * FROM SongTable") //SongTable로부터(FROM) 모든 값을(*) 가져와라(SELECT) + fun getSongs(): List + + @Query("SELECT * FROM SongTable WHERE id = :id") //id값이 넘겨받은 id값인 song을 가져와라(WHERE : 조건문) + fun getSong(id: Int): Song + + @Query("UPDATE SongTable SET isLike= :isLike WHERE id = :id") + fun updateIsLikebyId(isLike: Boolean, id: Int) + + //좋아요가 클릭된 애들만 addSongs + @Query("SELECT * FROM SongTable WHERE isLike = :isLike") + fun getLikedSongs(isLike: Boolean): List +} \ No newline at end of file diff --git a/Lize/app/src/main/java/com/example/flo/SongDatabase.kt b/Lize/app/src/main/java/com/example/flo/SongDatabase.kt new file mode 100644 index 0000000..b4b3805 --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/SongDatabase.kt @@ -0,0 +1,32 @@ +package com.example.flo + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + +@Database(entities = [Song::class, User::class, Like::class, Album::class], version = 1) +abstract class SongDatabase: RoomDatabase(){ + abstract fun songDao(): SongDao + abstract fun userDao(): UserDao + abstract fun albumDao(): AlbumDao + + companion object { + private var instance: SongDatabase? = null + + @Synchronized + fun getInstance(context: Context): SongDatabase? { + if(instance == null){ + synchronized(SongDatabase::class){ + instance = Room.databaseBuilder( + context.applicationContext, + SongDatabase::class.java, + "song-database" + ).allowMainThreadQueries().build() + } + } + + return instance + } + } +} diff --git a/Lize/app/src/main/java/com/example/flo/SongFragment.kt b/Lize/app/src/main/java/com/example/flo/SongFragment.kt index ab17cfa..94288f0 100644 --- a/Lize/app/src/main/java/com/example/flo/SongFragment.kt +++ b/Lize/app/src/main/java/com/example/flo/SongFragment.kt @@ -35,6 +35,7 @@ class SongFragment : Fragment(){ return binding.root } + //내취향MIX버튼 fun setMixStatus(isMix : Boolean){ if(isMix){ binding.albumMixToggleOffIv.visibility = View.VISIBLE diff --git a/Lize/app/src/main/java/com/example/flo/User.kt b/Lize/app/src/main/java/com/example/flo/User.kt new file mode 100644 index 0000000..6e6f5cc --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/User.kt @@ -0,0 +1,13 @@ +package com.example.flo + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "UserTable") +data class User( + var email : String, + var password : String +){ + //자동으로 userid부여 + @PrimaryKey(autoGenerate = true) var id : Int = 0 +} diff --git a/Lize/app/src/main/java/com/example/flo/UserDao.kt b/Lize/app/src/main/java/com/example/flo/UserDao.kt new file mode 100644 index 0000000..7e5d26b --- /dev/null +++ b/Lize/app/src/main/java/com/example/flo/UserDao.kt @@ -0,0 +1,20 @@ +package com.example.flo + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface UserDao { + @Insert + fun insert(user:User) + + //User (Data Class)에 저장된 모든 정보 가져오기 + @Query("SELECT*FROM UserTable") + fun getUsers() : List //List형태로 가져오기 + + //로그인 시에 입력한 email과 password가 똑같은 user의 정보 가져오기 + @Query("SELECT*FROM UserTable WHERE email = :email AND password = :password") + fun getUser(email: String, password: String) : User? + //입력된 정보가 있을 수도 있고 없을 수도(null) 있음 -> ? +} \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/activity_login.xml b/Lize/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..a2f05f8 --- /dev/null +++ b/Lize/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,284 @@ + +> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/activity_signup.xml b/Lize/app/src/main/res/layout/activity_signup.xml new file mode 100644 index 0000000..a8dd808 --- /dev/null +++ b/Lize/app/src/main/res/layout/activity_signup.xml @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/fragment_locker.xml b/Lize/app/src/main/res/layout/fragment_locker.xml index 38a93a5..9855b1d 100644 --- a/Lize/app/src/main/res/layout/fragment_locker.xml +++ b/Lize/app/src/main/res/layout/fragment_locker.xml @@ -5,12 +5,92 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/fragment_locker_musicfile.xml b/Lize/app/src/main/res/layout/fragment_locker_musicfile.xml new file mode 100644 index 0000000..485c763 --- /dev/null +++ b/Lize/app/src/main/res/layout/fragment_locker_musicfile.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/fragment_locker_savedalbum.xml b/Lize/app/src/main/res/layout/fragment_locker_savedalbum.xml new file mode 100644 index 0000000..a1534d6 --- /dev/null +++ b/Lize/app/src/main/res/layout/fragment_locker_savedalbum.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/fragment_locker_savedsong.xml b/Lize/app/src/main/res/layout/fragment_locker_savedsong.xml new file mode 100644 index 0000000..64d8354 --- /dev/null +++ b/Lize/app/src/main/res/layout/fragment_locker_savedsong.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/item_locker_album.xml b/Lize/app/src/main/res/layout/item_locker_album.xml new file mode 100644 index 0000000..11a3ab9 --- /dev/null +++ b/Lize/app/src/main/res/layout/item_locker_album.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/layout/item_song.xml b/Lize/app/src/main/res/layout/item_song.xml new file mode 100644 index 0000000..6ef4c69 --- /dev/null +++ b/Lize/app/src/main/res/layout/item_song.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Lize/app/src/main/res/raw/music_coin.mp3 b/Lize/app/src/main/res/raw/music_coin.mp3 new file mode 100644 index 0000000..8576f29 Binary files /dev/null and b/Lize/app/src/main/res/raw/music_coin.mp3 differ diff --git a/Lize/app/src/main/res/raw/music_savage.mp3 b/Lize/app/src/main/res/raw/music_savage.mp3 new file mode 100644 index 0000000..32424e5 Binary files /dev/null and b/Lize/app/src/main/res/raw/music_savage.mp3 differ diff --git a/Lize/app/src/main/res/raw/music_weekend.mp3 b/Lize/app/src/main/res/raw/music_weekend.mp3 new file mode 100644 index 0000000..de0ffb0 Binary files /dev/null and b/Lize/app/src/main/res/raw/music_weekend.mp3 differ