-
Notifications
You must be signed in to change notification settings - Fork 33
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_이지은 4주차 1단계 #60
base: jieunyume
Are you sure you want to change the base?
Changes from all commits
a749e88
80c47d6
3abbc9b
b0527b5
adca161
6d7449b
e533b25
2eb7b23
0b3db81
193fa3c
681b945
88faf63
66c2ece
4f44f65
97a4556
e1786ed
c3d8a4a
038d548
116e601
8b2cd64
b99401c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,10 @@ | ||
# android-map-location | ||
# android-map-location | ||
## step1 기능 목록 | ||
1. 저장된 검색어 목록에 기능 추가하기 | ||
- 저장된 검색어 중 하나를 선택하면 해당 검색어의 검색 결과 목록이 표시된다. | ||
2. 검색 결과 목록에 기능 추가하기 | ||
- 검색 결과 목록 중 하나의 항목을 선택하면 해당 항목의 위치를 지도에 표시한다. | ||
3. 마지막 위치 저장하기 | ||
- 앱 종료 시 마지막 위치를 SharedPreference 저장하여 다시 앱 실행 시 해당 위치로 포커스 한다. | ||
4. 에러 처리하기 | ||
- 카카오지도 onMapError() 호출 시 에러 화면을 보여준다. "지도 인증을 실패했습니다. 다시 시도해주세요. '에러이름(에러코드): 에러메세지' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package campus.tech.kakao.map.model.datasource | ||
|
||
import android.content.ContentValues | ||
import android.database.Cursor | ||
import android.util.Log | ||
import campus.tech.kakao.map.model.Contract.LocationEntry | ||
import campus.tech.kakao.map.model.Contract.SavedLocationEntry | ||
|
@@ -46,16 +47,21 @@ class LocationLocalDataSource(private val dbHelper : LocationDbHelper) { | |
val results = mutableListOf<Location>() | ||
with(cursor) { | ||
while (moveToNext()) { | ||
val title = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_TITLE)) | ||
val address = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_ADDRESS)) | ||
val category = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_CATEGORY)) | ||
results.add(Location(title, address, category)) | ||
val location = getLocation() | ||
results.add(location) | ||
} | ||
} | ||
cursor.close() | ||
return results | ||
} | ||
|
||
private fun Cursor.getLocation(): Location { | ||
val title = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_TITLE)) | ||
val address = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_ADDRESS)) | ||
val category = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_CATEGORY)) | ||
return Location(title, address, category, "", "") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. latitude longitude 는 없어도 될까요?! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2주차 과제에서 쓰인 코드를 그대로 뒀었는데, 삭제하도록 하겠습니다! |
||
} | ||
|
||
fun addSavedLocation(title: String): Long { | ||
val db = dbHelper.writableDatabase | ||
val values = ContentValues().apply { | ||
|
@@ -129,10 +135,8 @@ class LocationLocalDataSource(private val dbHelper : LocationDbHelper) { | |
val results = mutableListOf<Location>() | ||
with(cursor) { | ||
while (moveToNext()) { | ||
val title = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_TITLE)) | ||
val address = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_ADDRESS)) | ||
val category = getString(getColumnIndexOrThrow(LocationEntry.COLUMN_NAME_CATEGORY)) | ||
results.add(Location(title, address, category)) | ||
val location = getLocation() | ||
results.add(location) | ||
} | ||
} | ||
cursor.close() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package campus.tech.kakao.map.view.map | ||
|
||
data class Coordinates(val title: String, val longitude: Double, val latitude: Double, val address: String) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,61 @@ | ||
package campus.tech.kakao.map.view.map | ||
|
||
import android.app.Activity | ||
import android.content.Intent | ||
import android.content.SharedPreferences | ||
import android.graphics.Color | ||
import android.os.Bundle | ||
import android.util.Log | ||
import android.view.View | ||
import android.widget.EditText | ||
import android.widget.TextView | ||
import androidx.appcompat.app.AppCompatActivity | ||
import androidx.constraintlayout.widget.ConstraintLayout | ||
import campus.tech.kakao.map.BuildConfig | ||
import campus.tech.kakao.map.R | ||
import campus.tech.kakao.map.view.search.MainActivity | ||
import com.google.android.material.bottomsheet.BottomSheetBehavior | ||
import com.kakao.vectormap.KakaoMap | ||
import com.kakao.vectormap.KakaoMapReadyCallback | ||
import com.kakao.vectormap.KakaoMapSdk | ||
import com.kakao.vectormap.LatLng | ||
import com.kakao.vectormap.MapLifeCycleCallback | ||
import com.kakao.vectormap.MapView | ||
import com.kakao.vectormap.label.LabelOptions | ||
import com.kakao.vectormap.label.LabelStyle | ||
import com.kakao.vectormap.label.LabelStyles | ||
|
||
|
||
class MapActivity : AppCompatActivity() { | ||
private lateinit var searchEditText: EditText | ||
private lateinit var mapView: MapView | ||
private val searchEditText by lazy { findViewById<EditText>(R.id.SearchEditTextInMap) } | ||
private val mapView by lazy { findViewById<MapView>(R.id.map_view) } | ||
private val bottomSheetLayout by lazy { findViewById<ConstraintLayout>(R.id.bottom_sheet_layout) } | ||
private val bottom_sheet_title by lazy { findViewById<TextView>(R.id.bottom_sheet_title) } | ||
private val bottom_sheet_address by lazy { findViewById<TextView>(R.id.bottom_sheet_address) } | ||
private val errorMessageTextView by lazy { findViewById<TextView>(R.id.errorMessageTextView) } | ||
private val bottomSheetBehavior: BottomSheetBehavior<ConstraintLayout> by lazy { BottomSheetBehavior.from(bottomSheetLayout) } | ||
|
||
companion object{ | ||
private val DEFAULT_LONGITUDE = 127.115587 | ||
private val DEFAULT_LATITUDE = 37.406960 | ||
} | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.activity_map) | ||
|
||
initViews() | ||
setupEditText() | ||
setupMapView() | ||
} | ||
|
||
private fun initViews() { | ||
searchEditText = findViewById(R.id.SearchEditTextInMap) | ||
mapView = findViewById(R.id.map_view) | ||
override fun onResume() { | ||
super.onResume() | ||
mapView.resume() // MapView 의 resume 호출 | ||
} | ||
|
||
override fun onPause() { | ||
super.onPause() | ||
mapView.pause() // MapView 의 pause 호출 | ||
} | ||
|
||
private fun setupEditText() { | ||
|
@@ -43,19 +69,122 @@ class MapActivity : AppCompatActivity() { | |
KakaoMapSdk.init(this, BuildConfig.KAKAO_API_KEY); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저번에 코멘트를 드리지 못한 부분이긴한데, sdk 의 initialize 는 activity 에서 하기보다 Application 에서 처리하기를 권장하고 있습니다! (kakao map 도 마찬가지네요!) |
||
mapView.start(object : MapLifeCycleCallback() { | ||
override fun onMapDestroy() { | ||
// 지도 API 가 정상적으로 종료될 때 호출됨 | ||
Log.d("jieun", "onMapDestroy") | ||
} | ||
|
||
override fun onMapError(error: Exception) { | ||
// 인증 실패 및 지도 사용 중 에러가 발생할 때 호출됨 | ||
override fun onMapError(error: Exception) { // 인증 실패 및 지도 사용 중 에러가 발생할 때 호출됨 | ||
Log.d("jieun", "onMapError" + error) | ||
showErrorMessage(error) | ||
} | ||
}, object : KakaoMapReadyCallback() { | ||
override fun onMapReady(kakaoMap: KakaoMap) { | ||
// 인증 후 API 가 정상적으로 실행될 때 호출됨 | ||
Log.d("jieun", "onMapReady") | ||
val coordinates = getCoordinates() | ||
override fun onMapReady(kakaoMap: KakaoMap) { // 인증 후 API 가 정상적으로 실행될 때 호출됨 | ||
Log.d("jieun", "onMapReady coordinates: " + coordinates.toString()) | ||
if (coordinates != null) { | ||
showLabel(coordinates, kakaoMap) | ||
showBottomSheet(coordinates) | ||
setSharedData("pref", coordinates) | ||
// Log.d("jieun", "onMapReady setSharedData: " + getSharedData("pref")) | ||
} else{ | ||
hideBottomSheet() | ||
} | ||
} | ||
|
||
override fun getPosition(): LatLng { | ||
// Log.d("jieun", "getPosition coordinates: " + coordinates.toString()) | ||
if (coordinates != null) { | ||
return LatLng.from(coordinates.latitude, coordinates.longitude) | ||
} else{ | ||
return LatLng.from(DEFAULT_LATITUDE, DEFAULT_LONGITUDE) | ||
} | ||
|
||
} | ||
|
||
}) | ||
} | ||
|
||
private fun showErrorMessage(error: Exception) { | ||
runOnUiThread { | ||
setContentView(R.layout.error_map) | ||
errorMessageTextView.text = "지도 인증을 실패했습니다.\n다시 시도해주세요.\n\n" + error.message | ||
} | ||
} | ||
|
||
private fun showLabel( | ||
coordinates: Coordinates, | ||
kakaoMap: KakaoMap | ||
) { | ||
val labelStyles: LabelStyles = LabelStyles.from( | ||
LabelStyle.from(R.drawable.location_red_icon_resized).setZoomLevel(8), | ||
LabelStyle.from(R.drawable.location_red_icon_resized) | ||
.setTextStyles(32, Color.BLACK, 1, Color.GRAY).setZoomLevel(15) | ||
) | ||
val position = LatLng.from(coordinates.latitude, coordinates.longitude) | ||
kakaoMap.labelManager?.getLayer()?.addLabel( | ||
LabelOptions.from(position) | ||
.setStyles(labelStyles) | ||
.setTexts(coordinates.title) | ||
) | ||
} | ||
|
||
private fun hideBottomSheet() { | ||
runOnUiThread { bottomSheetLayout.visibility = View.GONE } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. onMapReady 가 혹시 ui thread 가 아닌 다른 스레드에서 처리하고 있나요? runOnUiThread 는 꼭 필요한 경우에만 처리해주시는 것이 좋습니다! |
||
} | ||
|
||
private fun showBottomSheet(coordinates: Coordinates) { | ||
runOnUiThread { | ||
bottomSheetLayout.visibility = View.VISIBLE | ||
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED | ||
bottom_sheet_title.text = coordinates.title | ||
bottom_sheet_address.text = coordinates.address | ||
} | ||
} | ||
|
||
private fun getCoordinates(): Coordinates? { | ||
var coordinates = getCoordinatesByIntent() | ||
if(coordinates == null) { | ||
coordinates = getCoordinatedBySharedPreference("pref") | ||
} | ||
return coordinates | ||
|
||
} | ||
|
||
private fun getCoordinatesByIntent(): Coordinates? { | ||
if (intent.hasExtra("title") && intent.hasExtra("longitude") | ||
&& intent.hasExtra("latitude") && intent.hasExtra("address")) { | ||
val title = intent.getStringExtra("title").toString() | ||
val longitudeString = intent.getStringExtra("longitude") | ||
val latitudeString = intent.getStringExtra("latitude") | ||
val address = intent.getStringExtra("address").toString() | ||
if (longitudeString != null && latitudeString != null) { | ||
val longitude = longitudeString.toDouble() | ||
val latitude = latitudeString.toDouble() | ||
return Coordinates(title, longitude, latitude, address) | ||
} else return null | ||
} else return null | ||
} | ||
|
||
fun setSharedData(name: String, coordinates: Coordinates?) { | ||
if (coordinates != null) { | ||
var pref: SharedPreferences = getSharedPreferences(name, Activity.MODE_PRIVATE) | ||
var editor: SharedPreferences.Editor = pref.edit() | ||
editor.putString("longitude", coordinates.longitude.toString()) | ||
editor.putString("latitude", coordinates.latitude.toString()) | ||
editor.putString("title", coordinates.title.toString()) | ||
editor.putString("address", coordinates.address.toString()) | ||
editor.apply() | ||
Comment on lines
+169
to
+175
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이렇게 정보를 가지고 오는 것은 data layer 에서 로직이 있는 것이 좋습니다. Repository 로 로직을 옮기고, ViewModel 을 통해서 데이터를 가져오는 것을 추천드립니다! |
||
} | ||
} | ||
|
||
fun getCoordinatedBySharedPreference(name: String): Coordinates? { | ||
var pref: SharedPreferences = getSharedPreferences(name, Activity.MODE_PRIVATE) | ||
if(pref.getString("title", "") == ""){ | ||
return null | ||
} | ||
val title = pref.getString("title", "").toString() | ||
val longitude = pref.getString("longitude", "").toString().toDouble() | ||
val latitude = pref.getString("latitude", "").toString().toDouble() | ||
val address = pref.getString("address", "").toString() | ||
return Coordinates(title, longitude, latitude, address) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lat lng 는 double 이어도 되지 않을까요!?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드에서 위치 정보를 미리 변환하지 않고 실제로 사용할 때마다 변환하려고 했습니다! 근데 생각해보니까 그러면 여러 번 변환하는 경우가 생길 수 있으니까 더 비효율적일 수 있겠네요! 감사합니다~!