Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

부산대 Android_김현민 5주차 과제 Step2 #69

Open
wants to merge 82 commits into
base: khyeonm
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
04c907f
Initial commit
MyStoryG Jun 15, 2024
8b097b3
Initial commit
MyStoryG Jun 15, 2024
6b8ac02
Docs: Update README.md
khyeonm Jul 1, 2024
cacee4b
Feat: Complete search screen layout
khyeonm Jul 1, 2024
cb73f1e
Feat: Add data to the database
khyeonm Jul 1, 2024
6bd8cf7
Docs: Update README.md
khyeonm Jul 3, 2024
0fc0da3
Feat: Create item_view
khyeonm Jul 4, 2024
f94b9b8
Feat: Modify main view
khyeonm Jul 4, 2024
a400cbd
Feat: Implement search list
khyeonm Jul 4, 2024
60e50ab
Feat: Complete saved element view
khyeonm Jul 4, 2024
36ad032
Feat: Complete save action
khyeonm Jul 4, 2024
0644db3
Feat: Add persistent save function
khyeonm Jul 4, 2024
de2036d
부산대 Android_김현민_2주차_과제_Step1 (#2)
khyeonm Jul 5, 2024
8dcc8a7
Design: Modify save element design
khyeonm Jul 5, 2024
3959c94
Update README.md
khyeonm Jul 5, 2024
c03af09
Merge branch 'khyeonm' into step2
khyeonm Jul 6, 2024
bbf77e9
Initial commit
MyStoryG Jul 7, 2024
e708df9
Fix: Fix error
khyeonm Jul 8, 2024
39de52b
Merge branch 'step2-from-keyword' into step0
khyeonm Jul 8, 2024
1c5d9c2
Fix: Fix Week2 error
khyeonm Jul 9, 2024
a68d784
Docs: Update README.md
khyeonm Jul 9, 2024
2f45b6c
Feat: Add initial settings
khyeonm Jul 9, 2024
e3818d0
Feat: Add Document data class
khyeonm Jul 9, 2024
3521161
Feat: Add RetrofitService interface
khyeonm Jul 9, 2024
ab8d218
Refactor: Delete DB code
khyeonm Jul 9, 2024
7b38ee9
Feat: Add search function using API
khyeonm Jul 9, 2024
10c77c6
Feat: Separate CategoryGroupCode
khyeonm Jul 9, 2024
8d65dd3
Docs: Update step2 README.md
khyeonm Jul 11, 2024
9e07bf4
Feat: complete initial project setup
khyeonm Jul 11, 2024
8702f3b
Feat: Add mapview and map function
khyeonm Jul 11, 2024
b3231a9
Fix: resolve errors
khyeonm Jul 11, 2024
113daff
Chore: Update network security configuration
khyeonm Jul 11, 2024
b954413
Fix: Resolve windows emulator issue
khyeonm Jul 11, 2024
0f3c880
Style: Update mapview design
khyeonm Jul 11, 2024
9652c65
부산대 Android_김현민 3주차 과제 Step0 (#19)
khyeonm Jul 14, 2024
9238189
Fix: Reflect feedback
khyeonm Jul 15, 2024
918d3fd
Fix: Resolve error
khyeonm Jul 15, 2024
f87982e
Merge branch 'khyeonm' into step2-1
khyeonm Jul 15, 2024
ce0ab32
Merge branch 'step2-1-from-search' into step0
khyeonm Jul 15, 2024
f6cb344
부산대 Android_김현민 4주차 과제 Step0 (#16)
khyeonm Jul 15, 2024
767bc4a
Docs: Update README.md
khyeonm Jul 16, 2024
dac7bca
Feat: Add location marker
khyeonm Jul 16, 2024
afa34b0
Feat: Add camera movement function
khyeonm Jul 16, 2024
d88c1a5
Feat: Add bottom sheet dialog
khyeonm Jul 16, 2024
13d7133
Feat: Add initial camera location function
khyeonm Jul 16, 2024
97ee6d1
Refactor: Resolve initial camera issue and search issue
khyeonm Jul 16, 2024
dd9b3a1
Feat: Add map error event
khyeonm Jul 16, 2024
b44783b
Design: Modify UI design
khyeonm Jul 16, 2024
f14be70
Refactor: Separate function and write annotations
khyeonm Jul 16, 2024
1d481b2
Docs: Update README.md
khyeonm Jul 16, 2024
cec88cf
Feat: Add save item click function
khyeonm Jul 16, 2024
02b9df4
Feat: Add keyword search function
khyeonm Jul 16, 2024
08879d8
Refactor: Reflect step1 feedback
khyeonm Jul 17, 2024
53769af
Feat: Add dependencies
khyeonm Jul 19, 2024
bf7f411
Test: Add map activity ui test
khyeonm Jul 19, 2024
4aceb24
Test: Add main activity ui test
khyeonm Jul 19, 2024
634700d
Test: Add main activity unit test
khyeonm Jul 19, 2024
eea98eb
Test: Add map activity unit test
khyeonm Jul 19, 2024
202da6c
부산대 Android_김현민 4주차 과제 Step1 (#33)
khyeonm Jul 21, 2024
ec78710
Fix: Fix conflict error
khyeonm Jul 22, 2024
cac1aaa
Merge branch 'khyeonm' into step2-1
khyeonm Jul 22, 2024
3b8c2ca
Merge branch 'step2-from-location' into step0
khyeonm Jul 22, 2024
3ca355a
Chore: Add dependency and grouping
khyeonm Jul 22, 2024
bd0c9ba
Chore: Edit grouping
khyeonm Jul 22, 2024
fff84fb
Refactor: Change database to Room
khyeonm Jul 22, 2024
ba997ca
Fix: Resolve data integrity error
khyeonm Jul 22, 2024
55d7ed5
Refactor: Apply dependency injection
khyeonm Jul 22, 2024
9cf280f
Refactor: Apply dependency injection
khyeonm Jul 22, 2024
5b541c7
Refactor: Apply dependency injection
khyeonm Jul 23, 2024
712d413
Chore: Edit grouping
khyeonm Jul 23, 2024
8e28f65
Refactor: Apply dependency injection
khyeonm Jul 23, 2024
f79cab4
Refactor: Apply dependency injection
khyeonm Jul 23, 2024
59c928d
Fix: Remove test code error
khyeonm Jul 23, 2024
5aaa878
Refactor: Reflect step1 feedback
khyeonm Jul 23, 2024
348dcb9
Chore: Add initial settings
khyeonm Jul 23, 2024
dc1329a
Refactor: Apply databinding in MainActivity
khyeonm Jul 24, 2024
da573e2
Refactor: Apply MVVM in error activity
khyeonm Jul 24, 2024
9bdaa2f
Refactor: Change asynchronous to coroutine
khyeonm Jul 24, 2024
6ce455d
Refactor: Apply MVVM in map activity
khyeonm Jul 25, 2024
592cdc5
Chore: Modify error activity code
khyeonm Jul 25, 2024
9141ee4
Refactor: Apply MVVM in main activity
khyeonm Jul 26, 2024
261f6a3
Merge branch 'khyeonm' into step2
khyeonm Jul 26, 2024
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
5 changes: 5 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ android {
namespace = "campus.tech.kakao.map"
compileSdk = 34

dataBinding {
enable = true
}

defaultConfig {
applicationId = "campus.tech.kakao.map"
minSdk = 26
Expand Down Expand Up @@ -70,6 +74,7 @@ android {

dependencies {
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.3")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.3")
implementation("androidx.room:room-runtime:2.6.1")
implementation("androidx.activity:activity-ktx:1.9.0")
implementation("androidx.room:room-ktx:2.6.1")
Expand Down
27 changes: 9 additions & 18 deletions app/src/main/java/campus/tech/kakao/map/adapter/Adapter.kt
Original file line number Diff line number Diff line change
@@ -1,31 +1,24 @@
package campus.tech.kakao.map.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import campus.tech.kakao.map.R
import campus.tech.kakao.map.data.Profile
import campus.tech.kakao.map.databinding.ActivityItemViewBinding

class Adapter(private val profiles: MutableList<Profile>) : RecyclerView.Adapter<Adapter.ProfileViewHolder>() {


interface OnItemClickListener {
fun onItemClick(name: String, address: String, latitude: String, longitude: String)
}

var listener: OnItemClickListener? = null

fun setOnItemClickListener(listener: OnItemClickListener) {
this.listener = listener
}

inner class ProfileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvName: TextView = itemView.findViewById(R.id.tvName)
val tvAddress: TextView = itemView.findViewById(R.id.tvAddress)
val tvType: TextView = itemView.findViewById(R.id.tvType)


inner class ProfileViewHolder(val binding: ActivityItemViewBinding) : RecyclerView.ViewHolder(binding.root) {
init {
itemView.setOnClickListener {
bindingAdapterPosition.takeIf { it != RecyclerView.NO_POSITION }?.let { position ->
Expand All @@ -37,20 +30,18 @@ class Adapter(private val profiles: MutableList<Profile>) : RecyclerView.Adapter
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProfileViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.activity_item_view, parent, false)
return ProfileViewHolder(view)
val inflater = LayoutInflater.from(parent.context)
val binding = ActivityItemViewBinding.inflate(inflater, parent, false)
return ProfileViewHolder(binding)
}

override fun onBindViewHolder(holder: ProfileViewHolder, position: Int) {
val profile = profiles[position]
holder.tvName.text = profile.name
holder.tvAddress.text = profile.address
holder.tvType.text = profile.type
holder.binding.profile = profile
holder.binding.executePendingBindings()
}

override fun getItemCount(): Int {
return profiles.size
}
override fun getItemCount(): Int = profiles.size

fun updateProfiles(newProfiles: List<Profile>) {
profiles.clear()
Expand Down
15 changes: 0 additions & 15 deletions app/src/main/java/campus/tech/kakao/map/data/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,5 @@ import androidx.sqlite.db.SupportSQLiteDatabase
@Database(entities = [Profile::class], version = 2)
abstract class AppDatabase : RoomDatabase() {
abstract fun profileDao(): ProfileDao

companion object {
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("DROP TABLE IF EXISTS Profiles")
database.execSQL(
"CREATE TABLE IF NOT EXISTS Profiles (" +
"uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
"name TEXT NOT NULL, address TEXT NOT NULL, " +
"type TEXT NOT NULL, latitude TEXT NOT NULL, " +
"longitude TEXT NOT NULL)"
)
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.ActivityScoped

@Module
@InstallIn(ActivityComponent::class)
object BottomSheetModule {
@Provides
@ActivityScoped
fun singletonBottomSheet(@ActivityContext context: Context): BottomSheetHelper {
return BottomSheetHelper(context)
}
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/di/DatabaseModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package campus.tech.kakao.map.di

import android.content.Context
import androidx.room.Room
import campus.tech.kakao.map.data.AppDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {

@Provides
@Singleton
fun provideDatabase(@ApplicationContext appContext: Context): AppDatabase {
return Room.databaseBuilder(
appContext,
AppDatabase::class.java,
"profiles"
).fallbackToDestructiveMigration().build()
}
}
18 changes: 14 additions & 4 deletions app/src/main/java/campus/tech/kakao/map/network/Network.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ import javax.inject.Inject
class Network @Inject constructor(private val retrofitService: RetrofitService) {
val API_KEY = "KakaoAK ${BuildConfig.KAKAO_REST_API_KEY}"

fun searchCategory(categoryGroupCode: String, callback: Callback<KakaoResponse>) {
retrofitService.getSearchCategory(API_KEY, categoryGroupCode).enqueue(callback)
suspend fun searchCategory(categoryGroupCode: String): KakaoResponse? {
val response = retrofitService.getSearchCategory(API_KEY, categoryGroupCode)
if (response.isSuccessful) {
return response.body()
} else {
throw Exception("응답 실패: ${response.errorBody()?.string()}")
}
}

fun searchKeyword(query: String, callback: Callback<KakaoResponse>) {
retrofitService.getSearchKeyword(API_KEY, query).enqueue(callback)
suspend fun searchKeyword(query: String): KakaoResponse? {
val response = retrofitService.getSearchKeyword(API_KEY, query)
if (response.isSuccessful) {
return response.body()
} else {
throw Exception("응답 실패: ${response.errorBody()?.string()}")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package campus.tech.kakao.map.network

import retrofit2.Call
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query

interface RetrofitService {
@GET("/v2/local/search/category.json")
fun getSearchCategory(
suspend fun getSearchCategory(
@Header("Authorization") apiKey: String,
@Query("category_group_code") categoryGroupCode: String,
// @Query("x") x: String,
Expand All @@ -16,14 +17,14 @@ interface RetrofitService {
@Query("page") page: Int = 1,
@Query("size") size: Int = 15,
@Query("sort") sort: String = "accuracy"
): Call<KakaoResponse>
): Response<KakaoResponse>

@GET("/v2/local/search/keyword.json")
fun getSearchKeyword(
suspend fun getSearchKeyword(
@Header("Authorization") apiKey: String,
@Query("query") query: String,
@Query("page") page: Int = 1,
@Query("size") size: Int = 15,
@Query("sort") sort: String = "accuracy"
): Call<KakaoResponse>
): Response<KakaoResponse>
}
53 changes: 15 additions & 38 deletions app/src/main/java/campus/tech/kakao/map/network/SearchService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,23 @@ import retrofit2.Response
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class SearchService @Inject constructor(private val network: Network, private val context: Context) {

fun searchKeyword(query: String, callback: (KakaoResponse?) -> Unit) {
network.searchKeyword(query, object : Callback<KakaoResponse> {
override fun onResponse(call: Call<KakaoResponse>, response: Response<KakaoResponse>) {
if (response.isSuccessful) {
callback(response.body())
} else {
Toast.makeText(context, "응답 실패", Toast.LENGTH_SHORT).show()
Log.e("SearchService", "응답 실패")
callback(null)
}
}

override fun onFailure(call: Call<KakaoResponse>, t: Throwable) {
Toast.makeText(context, "요청 실패: ${t.message}", Toast.LENGTH_SHORT).show()
Log.e("SearchService", "요청 실패", t)
callback(null)
}
})
suspend fun searchKeyword(query: String): KakaoResponse? {
return try {
network.searchKeyword(query)
} catch (error: Throwable) {
Log.e("SearchService", "요청 실패", error)
throw error
}
}

fun searchCategory(categoryGroupCode: String, callback: (KakaoResponse?) -> Unit) {
network.searchCategory(categoryGroupCode, object : Callback<KakaoResponse> {
override fun onResponse(call: Call<KakaoResponse>, response: Response<KakaoResponse>) {
if (response.isSuccessful) {
callback(response.body())
} else {
Toast.makeText(context, "응답 실패", Toast.LENGTH_SHORT).show()
Log.e("SearchService", "응답 실패")
callback(null)
}
}

override fun onFailure(call: Call<KakaoResponse>, t: Throwable) {
Toast.makeText(context, "요청 실패: ${t.message}", Toast.LENGTH_SHORT).show()
Log.e("SearchService", "요청 실패", t)
callback(null)
}
})
suspend fun searchCategory(categoryGroupCode: String): KakaoResponse? {
return try {
network.searchCategory(categoryGroupCode)
} catch (error: Throwable) {
Log.e("SearchService", "요청 실패", error)
throw error
}
}
}
}
12 changes: 9 additions & 3 deletions app/src/main/java/campus/tech/kakao/map/ui/ErrorActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ package campus.tech.kakao.map.ui

import android.os.Bundle
import android.widget.TextView
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import campus.tech.kakao.map.R
import campus.tech.kakao.map.databinding.ActivityErrorBinding

class ErrorActivity : AppCompatActivity() {
val errorViewModel: ErrorViewModel by viewModels()
lateinit var errorBinding: ActivityErrorBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_error)
errorBinding = DataBindingUtil.setContentView(this, R.layout.activity_error)
errorBinding.lifecycleOwner = this
errorBinding.error = errorViewModel

val errorMessage = intent.getStringExtra("errorMessage")
val tvError = findViewById<TextView>(R.id.tvError)
tvError.text = errorMessage
errorViewModel.setErrorMessage(errorMessage?:"Unknown")

}
}
13 changes: 13 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/ui/ErrorViewModel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package campus.tech.kakao.map.ui

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class ErrorViewModel: ViewModel() {
val _errorMessage = MutableLiveData<String>()
val errorMessage: LiveData<String> get() = _errorMessage
fun setErrorMessage(message: String) {
_errorMessage.value = message
}
}
Loading