Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
01a2c6a
[Mission] 3주차 미션제출
bongbak Oct 9, 2025
cb51c19
locker 저장곡, album 수록곡 recycleView 추가
bongbak Oct 9, 2025
2ea906f
locker, SongFragment 로직 구현
bongbak Oct 9, 2025
222364c
동기화 로직 구현
bongbak Oct 9, 2025
1cdee1f
저장한 곡 목록 item_saved_more_01_iv 클릭 시 삭제 기능 추가.
bongbak Oct 10, 2025
1891ad3
[mission] 5주차 Splash Screen 구현
bongbak Oct 30, 2025
32adcee
[mission] 5주차 재생바 재생/멈춤 Thread 구현
bongbak Oct 30, 2025
e8e312b
[mission] 5주차 미션 저장앨범 더보기 버튼 클릭 시 앨범 삭제 기능 추가
bongbak Oct 30, 2025
73b9641
[mission] 5주차 미션 재생 버튼 클릭시 정지 버튼 변경 기능 추가
bongbak Oct 30, 2025
cb74238
[mission] 5주차 미션 다음곡/이전곡 버튼 클릭 시 seekbar 내용 초기화
bongbak Oct 31, 2025
20ede25
[mission] 6주차 음악 재생 기능 추가
bongbak Nov 4, 2025
ebfde97
[mission] 6주차 메인화면 SeekBar 구현 추가
bongbak Nov 4, 2025
e873f30
[mission] 6주차 메인화면 SeekBar 구현 추가
bongbak Nov 11, 2025
ff3058b
[mission] 6주차 자동 페이지 넘김&indicator 구현
bongbak Nov 11, 2025
5519897
[Mission] 7주차 미션 수행 - SongTable 구현
bongbak Nov 17, 2025
1ef7b7e
[Mission] 7주차 미션 수행 - 좋아요 보관함 기능 구현
bongbak Nov 17, 2025
8032b02
[Mission] 7주차 미션 수행 - 좋아요 보관함 기능 구현
bongbak Nov 17, 2025
feb47cf
[Mission] 7주차 미션 수행 - MainActivity.kt Next, Previous 동기화
bongbak Nov 17, 2025
323b245
[Mission] 8주차 미션 수행 - 회원가입, 로그인, 로그아웃 기능 추가
bongbak Nov 23, 2025
c2f79e2
[Mission] 8주차 미션 좋아요 앨범 기능 구현
bongbak Nov 23, 2025
02106fd
[Mission] 둘러보기 화면 추가
bongbak Nov 23, 2025
1ad7bdc
[Mission] 9주차 미션 SignUp 기능 구현
bongbak Nov 24, 2025
6dbf1ba
[Mission] 9주차 미션 Login 기능 구현
bongbak Nov 24, 2025
02ea560
[Mission] 9주차 Jwt 토큰 인증 테스트
bongbak Nov 24, 2025
79dace0
[Mission] 9주차 Jwt 토큰 인증 테스트
bongbak Nov 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 0 additions & 34 deletions .gitignore

This file was deleted.

49 changes: 0 additions & 49 deletions README.md

This file was deleted.

Empty file removed backy/test.txt
Empty file.
6 changes: 6 additions & 0 deletions bongbak/week2/.idea/studiobot.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions bongbak/week2/.kotlin/errors/errors-1762774619558.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kotlin version: 2.0.21
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

4 changes: 4 additions & 0 deletions bongbak/week2/.kotlin/errors/errors-1762851684314.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kotlin version: 2.0.21
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
1. Kotlin compile daemon is ready

19 changes: 18 additions & 1 deletion bongbak/week2/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import org.jetbrains.kotlin.storage.CacheResetOnProcessCanceled.enabled

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
kotlin("kapt")

}

Expand Down Expand Up @@ -45,6 +45,7 @@ android {
}

dependencies {
implementation("com.google.code.gson:gson:2.10.1")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
Expand All @@ -54,4 +55,20 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("me.relex:circleindicator:2.1.6")
implementation("androidx.room:room-ktx:2.6.1")
implementation("androidx.room:room-runtime:2.6.1")
kapt("androidx.room:room-compiler:2.6.1")

// Retrofit2
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.retrofit2:adapter-rxjava2:2.9.0")
//okHttp3
implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
//glide
implementation("com.github.bumptech.glide:glide:4.16.0")
kapt("com.github.bumptech.glide:compiler:4.16.0")
}
23 changes: 15 additions & 8 deletions bongbak/week2/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Mission2">
android:theme="@style/Theme.Mission2"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"/>

<activity
android:name=".SplashActivity"
android:exported="true"
android:theme="@style/Theme.Mission2">
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SongActivity"
android:exported="true"/>

<activity
android:name=".SongActivity"
android:exported="true"/>
<activity android:name=".LoginActivity" />
<activity android:name=".SignUpActivity" />

</application>

</manifest>
13 changes: 13 additions & 0 deletions bongbak/week2/app/src/main/java/com/example/mission2/Album.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.mission2

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName="AlbumTable")
data class Album(
@PrimaryKey(autoGenerate = false) var id:Int=0,
var title:String?="",
var singer:String?="",
var coverImg : Int? =null,
var isLike: Boolean = false,
)
28 changes: 28 additions & 0 deletions bongbak/week2/app/src/main/java/com/example/mission2/AlbumDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.example.mission2

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query

@Dao
interface AlbumDao {

@Insert
fun insert(albume:Album)

@Query("SELECT*FROM AlbumTable")
fun getAlbums():List<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) : 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<Album>

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@ 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.mission2.databinding.FragmentAlbumBinding
import com.example.mission2.databinding.FragmentSongBinding
import com.google.android.material.tabs.TabLayoutMediator
import com.google.gson.Gson

class AlbumFragment : Fragment() {

private val information=arrayListOf("수록곡","상세정보","영상")

lateinit var binding : FragmentAlbumBinding
private var gson: Gson =Gson()

private var isLiked:Boolean=false

override fun onCreateView(
inflater : LayoutInflater,
Expand All @@ -30,6 +35,15 @@ class AlbumFragment : Fragment() {
.replace(R.id.main_frm, HomeFragment()).commitAllowingStateLoss()

}


val albumJson=arguments?.getString("album")
val album=gson.fromJson(albumJson,Album::class.java)
isLiked=isLikedAlbum(album.id)

setInit(album)
setOnClickListeners(album)

val albumAdapter = AlbumVPAdapter(this,titleFromTextView,composerFromTextView)
binding.albumContentVp.adapter=albumAdapter
TabLayoutMediator(binding.albumContentTb, binding.albumContentVp) { tab, position ->
Expand All @@ -38,4 +52,55 @@ class AlbumFragment : Fragment() {

return binding.root
}
private fun setInit(album:Album){
binding.albumAlbumIv.setImageResource(album.coverImg!!)
binding.albumMusicTitleTv.text=album.title.toString()
binding.albumSingerNameTv.text=album.singer.toString()
if(isLiked){
binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_on)
}
else{
binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_off)
}
}
private fun getJwt(): Int {
val spf = activity?.getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE)
return spf!!.getInt("jwt", 0)
}
private fun likeAlbum(userId:Int,albumId:Int){
val songDB=SongDatabase.getInstance(requireContext())!!
val like=Like(userId,albumId)

songDB.AlbumDao().likeAlbum(like)
}

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
}

private fun disLikedAlbum(albumId:Int){
val songDB= SongDatabase.getInstance(requireContext())!!
val userId=getJwt()

val likeId : Int? =songDB.AlbumDao().disLikedAlbum(userId,albumId)
}

private fun setOnClickListeners(album:Album){
val userId=getJwt()
binding.albumLikeIv.setOnClickListener {
if(isLiked){
binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_off)
disLikedAlbum(album.id)
}
else{
binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_on)
likeAlbum(userId, album.id)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.example.mission2

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.mission2.databinding.ItemAlbumBinding

class AlbumRVAdapter(private val albumList:ArrayList<Album>): RecyclerView.Adapter<AlbumRVAdapter.ViewHolder>(){

interface MyItemClickListener{
fun onItemClick(album: Album)
fun onRemoveAlbum(position:Int)
fun onPlayClick(album: Album)
}

private lateinit var myItemClickListener: MyItemClickListener
fun setMyItemClickListener(itemClickListener: MyItemClickListener){
myItemClickListener=itemClickListener
}

fun addItem(album:Album){
albumList.add(album)
notifyDataSetChanged()
}
fun removeItem(position:Int){
albumList.removeAt(position)
notifyDataSetChanged()
}

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 { myItemClickListener.onItemClick(albumList[position])}
// holder.binding.itemAlbumTitleTv.setOnClickListener { myItemClickListener.onRemoveAlbum(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.itemAlbumSingerNameTv.text=album.singer
binding.itemAlbumCoverImgIv.setImageResource(album.coverImg!!)

binding.itemAlbumPlayImgIv.setOnClickListener {
myItemClickListener.onPlayClick(album)
}

}
}
}
Loading