-
Notifications
You must be signed in to change notification settings - Fork 29
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
[강원대 안드로이드 주민철] 6주차 스텝2 #78
Open
joominchul
wants to merge
20
commits into
kakao-tech-campus-2nd-step2:joominchul
Choose a base branch
from
joominchul:feat-joominchul-step2
base: joominchul
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
8714679
step0 푸시
joominchul 956d358
Docs[README.md]: 추가 스텝1 요구 사항
joominchul 4a34359
Rename[]: 추가 view 패키지
joominchul bf50f3c
Rename[]: 추가 view 패키지
joominchul 277a972
Feat[]: 생성 스플래시 화면
joominchul 206edf7
Rename[]: 생성 뷰모델 패키지
joominchul ba533c7
Refactor[SplashScreen]: 제거 안 쓰는 import
joominchul 3cf0717
Docs[README.md]: 추가 2단계
joominchul e8d98f9
Feat[SplashScreen]: 추가 알림 권한 허용
joominchul fcc7266
Feat[]: 추가 푸시 알림 수신
joominchul ed5d202
Refactor[SplashScreen]: 삭제 안 쓰는 import
joominchul ddd1c0f
Merge branch 'joominchul' into feat-joominchul-step2
joominchul e504a5e
Refactor[]: 분리 notification
joominchul a2710e6
Merge remote-tracking branch 'origin/feat-joominchul-step2' into feat…
joominchul da80c8a
Merge branch 'joominchul' of https://github.com/kakao-tech-campus-2nd…
joominchul f184036
Refactor[NotificationManager]: 변경 NotificationManager 이름 변경 및 object
joominchul 5ed597c
Create 1
joominchul eaab998
실행 이미지 업로드
joominchul d08057f
Delete 실행 화면/1
joominchul 476e78a
Update README.md
joominchul File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,24 @@ | ||
# android-map-notification | ||
|
||
## 1단계 - Splash Screen | ||
### 기능 요구 사항 | ||
- 초기 진입 화면을 추가한다. | ||
- Firebase의 Remote Config를 설정한다. | ||
- 서비스 상태를 나타내는 매개변수를 아래와 같이 각각 등록한다. | ||
- 매개변수 이름:serviceState, serviceMessage | ||
- 매개변수 serviceState 값이 ON_SERVICE일 때만 초기 진입 화면이 지도 화면으로 넘어간다. | ||
- 매개변수 serviceState 값이 ON_SERVICE이 아닌 경우에는 serviceMessage 값을 초기 진입 화면 하단에 표시하고 지도 화면으로 진입하지 않는다. | ||
### 프로그래밍 요구 사항 | ||
- 서버 상태, UI 로딩 등에 대한 상태 관리를 한다. | ||
- 새로 추가되는 부분에도 MVVM 아키텍처 패턴을 적용한다. | ||
- 코드 컨벤션을 준수하며 프로그래밍한다. | ||
|
||
## 2단계 - 푸시 알림 | ||
### 기능 요구 사항 | ||
- Firebase Cloud Message를 설정한다. | ||
- 테스트 메시지를 보낸다. | ||
- 앱이 백그라운드 상태일 경우 FCM 기본 값을 사용하여 Notification을 발생한다. | ||
- 앱이 포그라운드 상태일 경우 커스텀 Notification을 발생한다. | ||
- Notification 창을 터치하면 초기 진입 화면이 호출된다. | ||
### 프로그래밍 요구 사항 | ||
- 코드 컨벤션을 준수하며 프로그래밍한다. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
app/src/main/java/campus/tech/kakao/map/MapFirebaseMessagingService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package campus.tech.kakao.map | ||
|
||
|
||
import com.google.firebase.messaging.FirebaseMessagingService | ||
import com.google.firebase.messaging.RemoteMessage | ||
|
||
class MapFirebaseMessagingService: FirebaseMessagingService() { | ||
private val notification = Notification() | ||
override fun onMessageReceived(remoteMessage: RemoteMessage) { | ||
remoteMessage.notification?.let {remoteMessageContent-> | ||
notification.createNotification(remoteMessageContent.title, remoteMessageContent.body, this) | ||
} | ||
} | ||
|
||
override fun onNewToken(token: String) { | ||
super.onNewToken(token) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package campus.tech.kakao.map | ||
|
||
import android.app.NotificationChannel | ||
import android.app.NotificationManager | ||
import android.app.PendingIntent | ||
import android.content.Context | ||
import android.content.Intent | ||
import androidx.core.app.NotificationCompat | ||
import campus.tech.kakao.map.view.SplashScreen | ||
|
||
class Notification { | ||
private lateinit var notificationManager: NotificationManager | ||
private fun createNotificationChannel(context: Context) { | ||
val channel = NotificationChannel( | ||
CHANNEL_ID, | ||
CHANNEL_NAME, | ||
NotificationManager.IMPORTANCE_DEFAULT | ||
).apply { | ||
description = CHANNEL_DESCRIPTION | ||
} | ||
notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager | ||
notificationManager.createNotificationChannel(channel) | ||
} | ||
|
||
|
||
fun createNotification(title: String?, body: String?, context: Context){ | ||
|
||
|
||
createNotificationChannel(context) | ||
val intent = Intent(context, SplashScreen::class.java).apply { | ||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK | ||
} | ||
val pendingIntent = PendingIntent.getActivity( | ||
context, | ||
0, | ||
intent, | ||
PendingIntent.FLAG_IMMUTABLE | ||
) | ||
val builder = NotificationCompat.Builder( | ||
context, | ||
CHANNEL_ID | ||
) | ||
.setSmallIcon(R.drawable.ic_launcher_foreground) | ||
.setContentTitle("[포그라운드] $title") | ||
.setContentText("$body") | ||
.setPriority(NotificationCompat.PRIORITY_DEFAULT) | ||
.setContentIntent(pendingIntent) | ||
.setStyle( | ||
NotificationCompat.BigTextStyle() | ||
.bigText("앱이 실행 중일 때는 포그라운드 알림이 발생합니다.") | ||
) | ||
.setAutoCancel(true) | ||
|
||
notificationManager.notify(NOTIFICATION_ID, builder.build()) | ||
} | ||
|
||
|
||
|
||
companion object { | ||
private const val NOTIFICATION_ID = 222222 | ||
private const val CHANNEL_ID = "main_default_channel" | ||
private const val CHANNEL_NAME = "main channelName" | ||
private const val CHANNEL_DESCRIPTION = "main channelDescription" | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
app/src/main/java/campus/tech/kakao/map/module/NotificationModule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package campus.tech.kakao.map.module | ||
|
||
import campus.tech.kakao.map.Notification | ||
import dagger.Module | ||
import dagger.Provides | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
import javax.inject.Singleton | ||
|
||
@Module | ||
@InstallIn(SingletonComponent::class) | ||
object NotificationModule { | ||
@Provides | ||
@Singleton | ||
fun provideNotification(): Notification { | ||
return Notification() | ||
} | ||
} | ||
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. 의존성 주입까지 잘 하셨는데 사실 구현하신 Notification은 Service가 동작할 시에만 필요한 것이기에 굳이 의존성 주입 할 필요가 있나라는 생각도 드네요. 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. 말씀하신 대로 굳이 필요한 것 같지 않아 삭제했습니다. |
179 changes: 179 additions & 0 deletions
179
app/src/main/java/campus/tech/kakao/map/view/MapActivity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
package campus.tech.kakao.map.view | ||
|
||
import android.graphics.Bitmap | ||
import android.graphics.BitmapFactory | ||
import android.graphics.Color | ||
import android.os.Bundle | ||
import android.util.Log | ||
import android.view.KeyEvent | ||
import android.view.View | ||
import android.widget.LinearLayout | ||
import androidx.appcompat.app.AppCompatActivity | ||
import androidx.lifecycle.ViewModelProvider | ||
import campus.tech.kakao.map.viewModel.MainViewModel | ||
import campus.tech.kakao.map.R | ||
import campus.tech.kakao.map.databinding.ActivityMapBinding | ||
import campus.tech.kakao.map.databinding.BottomSheetBinding | ||
import campus.tech.kakao.map.databinding.MapErrorBinding | ||
import com.google.android.material.bottomsheet.BottomSheetBehavior | ||
import com.kakao.vectormap.KakaoMap | ||
import com.kakao.vectormap.KakaoMapReadyCallback | ||
import com.kakao.vectormap.LatLng | ||
import com.kakao.vectormap.MapLifeCycleCallback | ||
import com.kakao.vectormap.camera.CameraUpdate | ||
import com.kakao.vectormap.camera.CameraUpdateFactory | ||
import com.kakao.vectormap.label.LabelOptions | ||
import com.kakao.vectormap.label.LabelStyle | ||
import com.kakao.vectormap.label.LabelStyles | ||
import dagger.hilt.android.AndroidEntryPoint | ||
import java.lang.Exception | ||
|
||
@AndroidEntryPoint | ||
class MapActivity : AppCompatActivity() { | ||
private var map: KakaoMap? = null | ||
private lateinit var model: MainViewModel | ||
lateinit var placeName:String | ||
lateinit var addressName:String | ||
private lateinit var bottomSheetBehavior: BottomSheetBehavior<LinearLayout> | ||
private var longitude:Double = 0.0 | ||
private var latitude:Double = 0.0 | ||
private lateinit var binding: ActivityMapBinding | ||
private lateinit var bottomBinding: BottomSheetBinding | ||
companion object{ | ||
const val MARKER_WIDTH = 100 | ||
const val MARKER_HEIGHT = 100 | ||
const val MARKER_TEXT_SIZE = 40 | ||
const val ZOOM_LEVEL = 17 | ||
} | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
model = ViewModelProvider(this)[MainViewModel::class.java] | ||
getMapInfo() | ||
binding = ActivityMapBinding.inflate(layoutInflater) | ||
binding.map = this | ||
val view = binding.root | ||
setContentView(view) | ||
bottomBinding = BottomSheetBinding.inflate(layoutInflater) | ||
model.documentClickedDone() | ||
binding.mapView.start(object : MapLifeCycleCallback() { | ||
override fun onMapDestroy() { | ||
|
||
} | ||
|
||
override fun onMapError(p0: Exception?) { | ||
val errorBinding = MapErrorBinding.inflate(layoutInflater) | ||
setContentView(errorBinding.root) | ||
errorBinding.mapErrorText.text = p0?.message | ||
} | ||
|
||
}, object: KakaoMapReadyCallback() { | ||
override fun onMapReady(kakaoMap: KakaoMap) { | ||
map = kakaoMap | ||
} | ||
|
||
override fun getPosition(): LatLng { | ||
return LatLng.from(latitude, longitude) | ||
} | ||
|
||
override fun getZoomLevel(): Int { | ||
return ZOOM_LEVEL | ||
} | ||
}) | ||
binding.searchBar.setOnClickListener { | ||
onSearchBarClicked() | ||
} | ||
initBottomSheet() | ||
documentClickedObserve() | ||
} | ||
private fun onSearchBarClicked(){ | ||
val fragmentManager = supportFragmentManager | ||
val searchFragment = SearchFragment() | ||
val transaction = fragmentManager.beginTransaction() | ||
transaction.replace(binding.activityMap.id, searchFragment) | ||
transaction.addToBackStack(null) | ||
binding.activityMapFrameLayout.setOnTouchListener(View.OnTouchListener { v, event -> true }) | ||
transaction.commit() | ||
} | ||
|
||
override fun onResume() { | ||
super.onResume() | ||
binding.mapView.resume() | ||
} | ||
private fun documentClickedObserve(){ | ||
model.documentClicked.observe(this){documentClicked-> | ||
if(documentClicked){ | ||
makeMarker() | ||
setBottomSheet() | ||
val cameraUpdate: CameraUpdate = CameraUpdateFactory.newCenterPosition(LatLng.from(latitude, longitude)) | ||
map?.moveCamera(cameraUpdate) | ||
} | ||
else{ | ||
map?.labelManager?.layer?.removeAll() | ||
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN | ||
} | ||
} | ||
} | ||
|
||
override fun onPause() { | ||
super.onPause() | ||
binding.mapView.pause() | ||
} | ||
|
||
private fun getMapInfo(){ | ||
model.getMapInfo() | ||
model.mapInfo.observe(this) { mapInfo -> | ||
if (!mapInfo.isNullOrEmpty()) { | ||
latitude = mapInfo[0].toDouble() | ||
longitude = mapInfo[1].toDouble() | ||
placeName = mapInfo[2] | ||
addressName = mapInfo[3] | ||
} | ||
else{ | ||
Log.e("testt", "getMapInfo: mapInfo is null") | ||
} | ||
} | ||
} | ||
|
||
private fun makeMarker(){ | ||
val bitmapImage = BitmapFactory.decodeResource(resources, R.drawable.marker) | ||
val markerImage = Bitmap.createScaledBitmap(bitmapImage, MARKER_WIDTH, MARKER_HEIGHT, true) | ||
val styles = map?.labelManager?.addLabelStyles(LabelStyles.from(LabelStyle.from(markerImage).setTextStyles( | ||
MARKER_TEXT_SIZE, Color.BLACK))) | ||
if(styles != null){ | ||
val options = LabelOptions.from(LatLng.from(latitude, longitude)).setStyles(styles).setTexts(placeName) | ||
map?.labelManager?.layer?.removeAll() | ||
map?.labelManager?.layer?.addLabel(options) | ||
} | ||
else{ | ||
Log.e("MapActivity", "makeMarker: styles is null") | ||
} | ||
} | ||
|
||
private fun initBottomSheet(){ | ||
bottomSheetBehavior = BottomSheetBehavior.from(binding.bottomSheetInclude.bottomSheet) | ||
bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback(){ | ||
override fun onStateChanged(bottomSheet: View, newState: Int) { | ||
} | ||
|
||
override fun onSlide(bottomSheet: View, slideOffset: Float) { | ||
} | ||
|
||
}) | ||
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN | ||
} | ||
|
||
private fun setBottomSheet(){ | ||
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED | ||
binding.invalidateAll() | ||
} | ||
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { | ||
if (keyCode == KeyEvent.KEYCODE_BACK && supportFragmentManager.backStackEntryCount > 0) { | ||
model.documentClickedDone() | ||
supportFragmentManager.popBackStack() | ||
return true | ||
} | ||
|
||
return super.onKeyDown(keyCode, event) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
네이밍을 좀 달리하면 좋겠네요. Notification을 띄우고 Notification Channel을 생성하는 거니 Notification ~~ (Manager 등) 으로 변경하심 좋겠습니다. 그리고 단순히 기능만 제공하니 object 클래스로 구현하셔도 괜찮을 것 같네요
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.
변경했습니다.