diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..16660f1
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 6479977..9f8b8ed 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -7,11 +7,12 @@ plugins {
id("dagger.hilt.android.plugin")
id("androidx.navigation.safeargs.kotlin")
id("org.jetbrains.kotlin.kapt")
+ id("kotlin-kapt")
}
android {
namespace = "umc.study.umc_7th"
- compileSdk = 34
+ compileSdk = 35
defaultConfig {
applicationId = "umc.study.umc_7th"
@@ -48,7 +49,7 @@ android {
compose = true
}
composeOptions {
- kotlinCompilerExtensionVersion = "1.5.1"
+ kotlinCompilerExtensionVersion = "1.5.13"
}
packaging {
resources {
@@ -69,6 +70,7 @@ dependencies {
implementation(libs.androidx.storage)
implementation(libs.androidx.lifecycle.runtime.compose.android)
implementation(libs.common)
+ implementation(libs.firebase.firestore.ktx)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
@@ -86,6 +88,8 @@ dependencies {
implementation(libs.androidx.navigation.fragment.ktx)
implementation(libs.androidx.navigation.ui.ktx)
+ implementation ("me.relex:circleindicator:2.1.6")
+ implementation ("androidx.viewpager2:viewpager2:1.0.0")
// Hilt Dependency Injection
implementation("com.google.dagger:hilt-android:2.49")
kapt("com.google.dagger:hilt-compiler:2.49")
@@ -99,6 +103,8 @@ dependencies {
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.retrofit2:converter-scalars:2.9.0")
+ implementation("com.squareup.retrofit2:converter-gson:2.9.0")
+
// https://github.com/square/okhttp
implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.2")
@@ -132,4 +138,22 @@ dependencies {
annotationProcessor("androidx.room:room-compiler:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")
+
+ implementation("androidx.room:room-migration:2.6.0")
+ implementation("androidx.room:room-runtime:2.6.0")
+ kapt("androidx.room:room-compiler:2.6.0")
+
+// Retrofit
+ implementation("com.squareup.retrofit2:retrofit:2.9.0")
+ implementation("com.squareup.retrofit2:converter-gson:2.9.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2")
+ implementation("com.squareup.retrofit2:adapter-rxjava2:2.9.0")
+
+// okHttp
+ implementation("com.squareup.okhttp3:okhttp:4.9.0")
+ implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
+
+// Glide
+ implementation("com.github.bumptech.glide:glide:4.12.0")
+ annotationProcessor("com.github.bumptech.glide:compiler:4.12.0")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0318547..31292ab 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
\
+ xmlns:tools="http://schemas.android.com/tools">
@@ -19,10 +19,9 @@
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
- android:theme="@style/Theme.Umc_7th">
+ android:theme="@style/SplashTheme">
-
@@ -31,4 +30,6 @@
android:exported="true"/>
+
+
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/Album.kt b/app/src/main/java/umc/study/umc_7th/Album.kt
new file mode 100644
index 0000000..d60cc90
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/Album.kt
@@ -0,0 +1,13 @@
+package umc.study.umc_7th
+
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "AlbumTable")
+data class Album(
+ // album의 pk는 임의로 지정해 줄 것이므로, autoGenerate 하지 않음
+ @PrimaryKey(autoGenerate = false) var id: Int = 0,
+ var title: String? = "",
+ var singer: String? = "",
+ var coverImage: Int? = null
+)
diff --git a/app/src/main/java/umc/study/umc_7th/AlbumDao.kt b/app/src/main/java/umc/study/umc_7th/AlbumDao.kt
new file mode 100644
index 0000000..8cbaafa
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/AlbumDao.kt
@@ -0,0 +1,37 @@
+package umc.study.umc_7th
+
+import androidx.room.Dao
+import androidx.room.Delete
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+
+@Dao
+interface AlbumDao {
+ @Insert
+ fun insert(album: Album)
+
+ @Update
+ fun update(album: Album)
+
+ @Delete
+ fun delete(album: Album)
+
+ @Query("SELECT * FROM AlbumTable") // 테이블의 모든 값을 가져온다.
+ fun getAlbums(): List
+
+ @Query("SELECT * FROM AlbumTable WHERE id = :id")
+ fun getAlbum(id: Int): Album
+
+ @Insert
+ fun likeAlbum(like : Like)
+
+ @Query("select id from LikeTable where userId =:userId and albumId = :albumId")
+ fun isLikedAlbum(userId : Int, albumId : Int) : Int?
+
+ @Query("delete from LikeTable where userId =:userId and albumId = :albumId")
+ fun dislikedAlbum(userId : Int, albumId : Int)
+
+ @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/app/src/main/java/umc/study/umc_7th/AlbumFragment.kt b/app/src/main/java/umc/study/umc_7th/AlbumFragment.kt
index b0c3ca1..f4e93f0 100644
--- a/app/src/main/java/umc/study/umc_7th/AlbumFragment.kt
+++ b/app/src/main/java/umc/study/umc_7th/AlbumFragment.kt
@@ -1,17 +1,32 @@
+package umc.study.umc_7th
+
+
import android.os.Bundle
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 androidx.fragment.app.setFragmentResultListener
+import com.google.android.material.tabs.TabLayoutMediator
+import com.google.gson.Gson
+import umc.study.umc_7th.AlbumRVAdapter
import umc.study.umc_7th.HomeFragment
+import umc.study.umc_7th.Like
import umc.study.umc_7th.MainActivity
import umc.study.umc_7th.R
+import umc.study.umc_7th.SongDatabase
import umc.study.umc_7th.databinding.FragmentAlbumBinding
class AlbumFragment : Fragment() {
lateinit var binding: FragmentAlbumBinding
+ private var gson: Gson = Gson()
+
+ private var isLiked : Boolean = false
+
+ private val information = arrayListOf("수록곡", "상세정보", "영상")
override fun onCreateView(
inflater: LayoutInflater,
@@ -20,37 +35,93 @@ class AlbumFragment : Fragment() {
): View? {
binding = FragmentAlbumBinding.inflate(inflater,container,false)
+ val albumToJson = arguments?.getString("album")
+ val album = gson.fromJson(albumToJson, Album::class.java)
+ isLiked = isLikedAlbum(album.id)
+ setInit(album)
+ setOnClickListener(album)
+
+ setFragmentResultListener("TitleInfo") { requestKey, bundle ->
+ binding.albumMusicTitleTv.text = bundle.getString("title")
+ }
+
+ setFragmentResultListener("SingerInfo") { requestKey, bundle ->
+ binding.albumSingerNameTv.text = bundle.getString("singer")
+ }
+
+ // binding.albumMusicTitleTv.text = arguments?.getString("title")
+ // binding.albumSingerNameTv.text = arguments?.getString("singer")
+
binding.albumBackIv.setOnClickListener {
(context as MainActivity).supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, HomeFragment())
.commitAllowingStateLoss()
}
- binding.songLalacLayout.setOnClickListener {
- Toast.makeText(activity, "LILAC", Toast.LENGTH_SHORT).show()
- }
+ val albumAdapter = AlbumVPAdapter(this)
+ binding.albumContentVp.adapter = albumAdapter
- binding.songFluLayout.setOnClickListener {
- Toast.makeText(activity,"FLU", Toast.LENGTH_SHORT).show()
- }
+ TabLayoutMediator(binding.albumContentTb, binding.albumContentVp) { tab, position ->
+ tab.text = information[position]
+ }.attach()
- binding.songCoinLayout.setOnClickListener {
- Toast.makeText(activity,"Coin", Toast.LENGTH_SHORT).show()
- }
+ return binding.root
+ }
- binding.songSpringLayout.setOnClickListener {
- Toast.makeText(activity,"봄 안녕 봄", Toast.LENGTH_SHORT).show()
- }
+ private fun setInit(album : Album) {
+ binding.albumAlbumIv.setImageResource(album.coverImage!!)
+ binding.albumMusicTitleTv.text = album.title.toString()
+ binding.albumSingerNameTv.text = album.singer.toString()
- binding.songCelebrityLayout.setOnClickListener {
- Toast.makeText(activity,"Celebrity", Toast.LENGTH_SHORT).show()
+ if(isLiked) {
+ binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_on)
}
- binding.songSingLayout.setOnClickListener {
- Toast.makeText(activity,"돌림노래 (Feat. DEAN)", Toast.LENGTH_SHORT).show()
+ else {
+ binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_off)
}
+ }
- return binding.root
+ private fun getJwt() : Int {
+ val spf = requireActivity().getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE)
+ return spf.getInt("jwt", 0)
+ }
+
+ private fun likeAlbum(userId : Int, albumId : Int) {
+ val songDB = SongDatabase.getInstance(requireActivity())!!
+ val like = Like(userId, albumId)
+
+ songDB.albumDao().likeAlbum(like)
+ }
+
+ private fun isLikedAlbum(albumId : Int) : Boolean {
+ val songDB = SongDatabase.getInstance(requireActivity())!!
+ val userId = getJwt()
+
+ val likeId : Int? = songDB.albumDao().isLikedAlbum(userId, albumId)
+ return likeId != null
}
+ private fun disLikeAlbum(albumId : Int) {
+ val songDB = SongDatabase.getInstance(requireActivity())!!
+ val userId = getJwt()
+
+ songDB.albumDao().dislikedAlbum(userId, albumId)
+ }
+
+ private fun setOnClickListener(album : Album) {
+ val userId = getJwt()
+ binding.albumLikeIv.setOnClickListener {
+ if(isLiked) {
+ binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_off)
+ disLikeAlbum(album.id)
+ }
+
+ else {
+ binding.albumLikeIv.setImageResource((R.drawable.ic_my_like_on))
+ likeAlbum(userId, album.id)
+ }
+ }
+
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/AlbumRVAapter.kt b/app/src/main/java/umc/study/umc_7th/AlbumRVAapter.kt
new file mode 100644
index 0000000..7f0d583
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/AlbumRVAapter.kt
@@ -0,0 +1,52 @@
+package umc.study.umc_7th
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import umc.study.umc_7th.databinding.ItemAlbumBinding
+
+class AlbumRVAdapter(private val albumList: ArrayList) : RecyclerView.Adapter(){
+
+ // 뷰홀더를 생성해줘야 할 때 호출되는 함수 => 아이템 뷰 객체를 만들어서 뷰홀더에 던져줍니다.
+ override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AlbumRVAdapter.ViewHolder {
+ val binding: ItemAlbumBinding = ItemAlbumBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
+
+ return ViewHolder(binding)
+ }
+
+ // 뷰홀더에 데이터를 바인딩해줘야 할 때마다 호출되는 함수 => 엄청나게 많이 호출
+ override fun onBindViewHolder(holder: AlbumRVAdapter.ViewHolder, position: Int) {
+ holder.bind(albumList[position])
+ holder.itemView.setOnClickListener {
+ itemClickListener.onItemClick(albumList[position])
+ }
+
+ holder.binding.itemAlbumPlayImgIv.setOnClickListener {
+ itemClickListener.onPlayAlbum(albumList[position])
+ }
+ }
+
+ // 데이터 세트 크기를 알려주는 함수 => 리사이클러뷰가 마지막이 언제인지를 알게 된다.
+ override fun getItemCount(): Int = albumList.size
+
+ // 뷰홀더
+ inner class ViewHolder(val binding: ItemAlbumBinding): RecyclerView.ViewHolder(binding.root){
+
+ fun bind(album: Album){
+ binding.itemAlbumTitleTv.text = album.title
+ binding.itemAlbumSingerTv.text = album.singer
+ binding.itemAlbumCoverImgIv.setImageResource(album.coverImage!!)
+ }
+ }
+
+ interface OnItemClickListener {
+ fun onItemClick(album : Album)
+ fun onPlayAlbum(album : Album)
+ }
+
+ private lateinit var itemClickListener : OnItemClickListener
+
+ fun setItemClickListener(onItemClickListener: OnItemClickListener) {
+ this.itemClickListener = onItemClickListener
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/AlbumVPAdpter.kt b/app/src/main/java/umc/study/umc_7th/AlbumVPAdpter.kt
new file mode 100644
index 0000000..6b31037
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/AlbumVPAdpter.kt
@@ -0,0 +1,16 @@
+package umc.study.umc_7th
+
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+class AlbumVPAdapter(fragment : Fragment) : FragmentStateAdapter(fragment) {
+ override fun getItemCount(): Int = 3
+
+ override fun createFragment(position: Int): Fragment {
+ return when(position) {
+ 0 -> SongFragment()
+ 1 -> DetailFragment()
+ else -> VideoFragment()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/ApiRepository.kt b/app/src/main/java/umc/study/umc_7th/ApiRepository.kt
new file mode 100644
index 0000000..2bc16d0
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/ApiRepository.kt
@@ -0,0 +1,7 @@
+package umc.study.umc_7th
+
+class ApiRepository {
+ companion object {
+ const val BASE_URL = "http://3.35.121.185/"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/AuthApi.kt b/app/src/main/java/umc/study/umc_7th/AuthApi.kt
new file mode 100644
index 0000000..397df80
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/AuthApi.kt
@@ -0,0 +1,13 @@
+////package umc.study.umc_7th
+//
+//import retrofit2.Call
+//import retrofit2.http.Body
+//import retrofit2.http.POST
+//
+//interface AuthApi {
+// @POST("/users")
+// fun signUp(@Body user: User): Call
+//
+// @POST("/users/login")
+// fun login(@Body user: User): Call
+//}
diff --git a/app/src/main/java/umc/study/umc_7th/AuthService.kt b/app/src/main/java/umc/study/umc_7th/AuthService.kt
new file mode 100644
index 0000000..14e80f8
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/AuthService.kt
@@ -0,0 +1,53 @@
+package umc.study.umc_7th
+
+import android.util.Log
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+
+class AuthService {
+ private lateinit var signUpView: SignUpView
+ private lateinit var loginView: LoginView
+
+ fun setSignUpView(signUpView: SignUpView) {
+ this.signUpView = signUpView
+ }
+
+ fun setLoginView(loginView: LoginView) {
+ this.loginView = loginView
+ }
+
+ fun signUp(user : User) {
+ RetrofitInstance.authApi.signUp(user).enqueue(object: Callback {
+ override fun onResponse(call: Call, response: Response) {
+ Log.d("SignUp-Success", response.toString())
+ val response : BaseResponse = response.body()!!
+ when(response.code) {
+ 1000 -> signUpView.onSignUpSuccess()
+ else -> signUpView.onSignUpFailure(response.message)
+ }
+ }
+ override fun onFailure(call: Call, t: Throwable) {
+ Log.d("SignUp-Failure", t.message.toString())
+ }
+ })
+ Log.d("SignUpActivity", "All Finished")
+ }
+
+ fun login(user : User) {
+ RetrofitInstance.authApi.login(user).enqueue(object: Callback {
+ override fun onResponse(call: Call, response: Response) {
+ Log.d("Login-Success", response.toString())
+ val response : BaseResponse = response.body()!!
+ when(val code = response.code) {
+ 1000 -> loginView.onLoginSuccess(code, response.result!!)
+ else -> loginView.onLoginFailure(response.message)
+ }
+ }
+ override fun onFailure(call: Call, t: Throwable) {
+ Log.d("Login-Failure", t.message.toString())
+ }
+ })
+ Log.d("LoginActivity", "All Finished")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/BannerFragment.kt b/app/src/main/java/umc/study/umc_7th/BannerFragment.kt
new file mode 100644
index 0000000..41594e9
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/BannerFragment.kt
@@ -0,0 +1,27 @@
+package umc.study.umc_7th
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import umc.study.umc_7th.databinding.FragmentBannerBinding
+
+class BannerFragment(val imgRes : Int) : Fragment() {
+
+ lateinit var binding : FragmentBannerBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentBannerBinding.inflate(inflater, container, false)
+ binding.bannerImageIv.setImageResource(imgRes)
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/BannerVPAdapter.kt b/app/src/main/java/umc/study/umc_7th/BannerVPAdapter.kt
new file mode 100644
index 0000000..78e400f
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/BannerVPAdapter.kt
@@ -0,0 +1,22 @@
+package umc.study.umc_7th
+
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+class BannerVPAdapter(fragment : Fragment) : FragmentStateAdapter(fragment) {
+
+ private val fragmentList : ArrayList = ArrayList()
+
+ override fun getItemCount(): Int {
+ return fragmentList.size
+ }
+
+ override fun createFragment(position: Int): Fragment {
+ return fragmentList[position]
+ }
+
+ fun addFragment(fragment: Fragment) {
+ fragmentList.add(fragment)
+ notifyItemInserted(fragmentList.size-1)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/BaseResponse.kt b/app/src/main/java/umc/study/umc_7th/BaseResponse.kt
new file mode 100644
index 0000000..b2df535
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/BaseResponse.kt
@@ -0,0 +1,15 @@
+package umc.study.umc_7th
+
+import com.google.gson.annotations.SerializedName
+
+data class BaseResponse(
+ @SerializedName("isSuccess") val isSuccess : Boolean,
+ @SerializedName("code") val code : Int,
+ @SerializedName("message") val message : String,
+ @SerializedName("result") val result : Result?
+)
+
+data class Result (
+ @SerializedName("userIdx") var userIdx : Int,
+ @SerializedName("jwt") var jwt : String
+)
diff --git a/app/src/main/java/umc/study/umc_7th/BottomSheetFragment.kt b/app/src/main/java/umc/study/umc_7th/BottomSheetFragment.kt
new file mode 100644
index 0000000..0281491
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/BottomSheetFragment.kt
@@ -0,0 +1,43 @@
+package umc.study.umc_7th
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import umc.study.umc_7th.databinding.FragmentBottomSheetBinding
+
+class BottomSheetFragment : BottomSheetDialogFragment() {
+
+ lateinit var binding : FragmentBottomSheetBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentBottomSheetBinding.inflate(inflater, container, false)
+
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ binding.bottomSheetIv1.setOnClickListener {
+ Toast.makeText(requireActivity(), "듣기 버튼 클릭", Toast.LENGTH_SHORT).show()
+ }
+
+ binding.bottomSheetIv2.setOnClickListener {
+ Toast.makeText(requireActivity(), "재생목록 버튼 클릭", Toast.LENGTH_SHORT).show()
+ }
+
+ binding.bottomSheetIv3.setOnClickListener {
+ Toast.makeText(requireActivity(), "내 리스트 버튼 클릭", Toast.LENGTH_SHORT).show()
+ }
+
+ binding.bottomSheetIv4.setOnClickListener {
+ Toast.makeText(requireActivity(), "삭제 버튼 클릭", Toast.LENGTH_SHORT).show()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/CommunicationInterface.kt b/app/src/main/java/umc/study/umc_7th/CommunicationInterface.kt
new file mode 100644
index 0000000..8d8d269
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/CommunicationInterface.kt
@@ -0,0 +1,6 @@
+package umc.study.umc_7th
+
+
+interface CommunicationInterface {
+ fun sendData(album: Album)
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/Constant.kt b/app/src/main/java/umc/study/umc_7th/Constant.kt
new file mode 100644
index 0000000..622b567
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/Constant.kt
@@ -0,0 +1,6 @@
+package umc.study.umc_7th
+
+object Constant {
+ const val CHANNEL_ID = "ch123" // 아무런 값이나 입력한다.
+ const val MUSIC_NOTIFICATION_ID = 123 // 아무런 값이나 입력한다.
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/CustomSnackbar.kt b/app/src/main/java/umc/study/umc_7th/CustomSnackbar.kt
new file mode 100644
index 0000000..2849624
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/CustomSnackbar.kt
@@ -0,0 +1,48 @@
+package umc.study.umc_7th
+
+import android.view.LayoutInflater
+import android.view.View
+import androidx.core.content.ContextCompat
+import androidx.databinding.DataBindingUtil
+import com.google.android.material.snackbar.Snackbar
+import umc.study.umc_7th.databinding.CustomSnackbarBinding
+
+class CustomSnackbar(view: View, private val message: String) {
+
+ companion object {
+
+ fun make(view: View, message: String) = CustomSnackbar(view, message)
+ }
+
+ private val context = view.context
+ private val snackbar = Snackbar.make(view, "", 5000)
+ private val snackbarLayout = snackbar.view as Snackbar.SnackbarLayout
+
+ private val inflater = LayoutInflater.from(context)
+ private val snackbarBinding: CustomSnackbarBinding = DataBindingUtil.inflate(inflater, R.layout.custom_snackbar, null, false)
+
+ init {
+ initView()
+ initData()
+ }
+
+ private fun initView() {
+ with(snackbarLayout) {
+ removeAllViews()
+ setPadding(0, 0, 0, 0)
+ setBackgroundColor(ContextCompat.getColor(context, android.R.color.transparent))
+ addView(snackbarBinding.root, 0)
+ }
+ }
+
+ private fun initData() {
+ snackbarBinding.customSnackbarTv.text = message
+ snackbarBinding.customSnackbarBtn.setOnClickListener {
+ // OK 버튼을 클릭했을 때 실행할 동작을 정의할 수 있다.
+ }
+ }
+
+ fun show() {
+ snackbar.show()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/DetailFragment.kt b/app/src/main/java/umc/study/umc_7th/DetailFragment.kt
new file mode 100644
index 0000000..dfba4ad
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/DetailFragment.kt
@@ -0,0 +1,26 @@
+package umc.study.umc_7th
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import umc.study.umc_7th.databinding.FragmentDetailBinding
+
+class DetailFragment : Fragment() {
+
+ lateinit var binding : FragmentDetailBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentDetailBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/ForegroundService.kt b/app/src/main/java/umc/study/umc_7th/ForegroundService.kt
new file mode 100644
index 0000000..ac08d52
--- /dev/null
+++ b/app/src/main/java/umc/study/umc_7th/ForegroundService.kt
@@ -0,0 +1,63 @@
+package umc.study.umc_7th
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.app.Service
+import android.content.Intent
+import android.os.Build
+import android.os.IBinder
+import androidx.annotation.RequiresApi
+
+class ForegroundService : Service() {
+
+ override fun onBind(intent: Intent): IBinder? {
+ return null // 사용하지 않음을 의미한다.
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+ createNotificationChannel()
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // 버전 확인
+ showNotification()
+ }
+
+ return START_STICKY
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ private fun showNotification() {
+ val notificationIntent = Intent(this, SongActivity::class.java)
+ val pendingIntent = PendingIntent.getActivity(
+ this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE
+ )
+ val notification = Notification
+ .Builder(this, Constant.CHANNEL_ID)
+ .setContentText("현재 음악이 재생 중입니다.")
+ .setSmallIcon(R.drawable.app_icon)
+ .setContentIntent(pendingIntent)
+ .build()
+
+ startForeground(Constant.MUSIC_NOTIFICATION_ID, notification)
+ }
+
+ private fun createNotificationChannel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val serviceChannel = NotificationChannel(
+ Constant.CHANNEL_ID, "Service Channel",
+ NotificationManager.IMPORTANCE_DEFAULT
+ )
+
+ val manager = getSystemService(
+ NotificationManager::class.java
+ )
+
+ manager.createNotificationChannel(serviceChannel)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/umc/study/umc_7th/HomeFragment.kt b/app/src/main/java/umc/study/umc_7th/HomeFragment.kt
index 2889fa0..da71022 100644
--- a/app/src/main/java/umc/study/umc_7th/HomeFragment.kt
+++ b/app/src/main/java/umc/study/umc_7th/HomeFragment.kt
@@ -2,16 +2,34 @@ package umc.study.umc_7th
import AlbumFragment
import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
+import androidx.fragment.app.setFragmentResult
+import androidx.viewpager2.widget.ViewPager2
import umc.study.umc_7th.databinding.FragmentHomeBinding
-class HomeFragment : Fragment() {
+class HomeFragment : Fragment(), CommunicationInterface {
lateinit var binding : FragmentHomeBinding
+ private var albumDatas = ArrayList()
+ private lateinit var songDB: SongDatabase
+
+ private val timer = SongActivity.Timer()
+ private val handler = Handler(Looper.getMainLooper())
+
+ override fun sendData(album: Album) { // MainActivity의 UI를 업데이트하기 위해 사용하는 메서드
+ if (activity is MainActivity) {
+ val activity = activity as MainActivity
+ activity.updateMainPlayerCl(album)
+ }
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
@@ -22,10 +40,174 @@ class HomeFragment : Fragment() {
): View? {
binding = FragmentHomeBinding.inflate(inflater, container, false)
- binding.homePannelAlbumImgIv.setOnClickListener {
- (context as MainActivity).supportFragmentManager.beginTransaction().replace(R.id.main_frm, AlbumFragment()).commitAllowingStateLoss()
+// binding.homeAlbumImgIv1.setOnClickListener {
+// val bundle = Bundle()
+// bundle.putString("title", binding.titleLilac.text.toString())
+// bundle.putString("singer", binding.singerIu.text.toString())
+//
+// val albumFragment = AlbumFragment()
+// albumFragment.arguments = bundle
+//
+// (context as MainActivity)
+// .supportFragmentManager.beginTransaction()
+// .replace(R.id.main_frm, albumFragment).commitAllowingStateLoss()
+// }
+
+ inputDummyAlbums()
+
+ songDB = SongDatabase.getInstance(requireContext())!!
+ albumDatas.addAll(songDB.albumDao().getAlbums())
+ Log.d("albumlist", albumDatas.toString())
+
+ val albumRVAdapter = AlbumRVAdapter(albumDatas)
+ binding.homeTodayMusicAlbumRv.adapter = albumRVAdapter
+ binding.homeTodayMusicAlbumRv.layoutManager = LinearLayoutManager(requireActivity(), LinearLayoutManager.HORIZONTAL, false)
+
+ albumRVAdapter.setItemClickListener(object : AlbumRVAdapter.OnItemClickListener {
+ override fun onItemClick(album : Album) {
+ changeAlbumFragment(album)
+ }
+
+ override fun onPlayAlbum(album: Album) {
+ sendData(album)
+ }
+ })
+
+ val bannerAdapter = BannerVPAdapter(this)
+ bannerAdapter.addFragment(BannerFragment(R.drawable.img_home_viewpager_exp))
+ bannerAdapter.addFragment(BannerFragment(R.drawable.img_home_viewpager_exp2))
+
+ binding.homeBannerVp.adapter = bannerAdapter
+ binding.homeBannerVp.orientation = ViewPager2.ORIENTATION_HORIZONTAL
+
+ binding.homeBannerIndicator.setViewPager(binding.homeBannerVp)
+
+ autoSlide(bannerAdapter)
+
+ val pannelAdpater = PannelVpAdapter(this)
+ pannelAdpater.addFragment(PannelFragment(R.drawable.img_first_album_default))
+ pannelAdpater.addFragment(PannelFragment(R.drawable.img_first_album_default))
+ binding.homePannelBackgroundVp.adapter = pannelAdpater
+ binding.homePannelBackgroundVp.orientation = ViewPager2.ORIENTATION_HORIZONTAL
+
+ binding.homePannelIndicator.setViewPager(binding.homePannelBackgroundVp)
+
+ 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