Skip to content

Commit

Permalink
Merge pull request #219 from TeamDMU/feature/fcm-push
Browse files Browse the repository at this point in the history
Feat : FCM 푸쉬 알림 구현
  • Loading branch information
m6z1 authored Apr 2, 2024
2 parents ac8f962 + f120350 commit 39e9b0b
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,29 @@ package com.dongyang.android.youdongknowme.service
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.TaskStackBuilder
import android.content.Context
import android.content.Intent
import android.media.RingtoneManager
import android.os.Build
import androidx.core.app.NotificationCompat
import com.dongyang.android.youdongknowme.data.local.SharedPreference
import com.dongyang.android.youdongknowme.ui.view.detail.DetailActivity
import com.dongyang.android.youdongknowme.ui.view.main.MainActivity
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class FCMService : FirebaseMessagingService() {

override fun onMessageReceived(remoteMessage: RemoteMessage) {
val title = remoteMessage.notification?.title ?: "기본 제목"
val message = remoteMessage.notification?.body ?: "기본 메시지"
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)

val title = message.notification?.title ?: "기본 제목"
val messageBody = message.notification?.body ?: "기본 메시지"
val url = message.data["url"] ?: ""

// 알림 채널 ID
val channelId = "your_channel_id"
val channelId = "DMforU"

// NotificationManager 인스턴스 생성
val notificationManager =
Expand All @@ -36,22 +41,39 @@ class FCMService : FirebaseMessagingService() {
notificationManager.createNotificationChannel(channel)
}

// Intent 및 PendingIntent 생성
val intent = Intent(this, MainActivity::class.java).apply {
// MainActivity를 시작하는 Intent 생성
val mainIntent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
}
val pendingIntent = PendingIntent.getActivity(
this,
0,
intent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

// DetailActivity를 열기 위한 Intent 생성
val detailIntent = if (!url.isNullOrEmpty()) {
DetailActivity.newIntent(this, url)
} else {
null // URL이 없는 경우에는 null 할당
}

// PendingIntent 생성
val pendingIntent = if (detailIntent != null) {
TaskStackBuilder.create(this).run {
addNextIntent(mainIntent)
addNextIntentWithParentStack(detailIntent) // DetailActivity를 부모 스택으로 추가
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
} else {
PendingIntent.getActivity(
this,
0,
mainIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
}

// 알림 생성
val builder = NotificationCompat.Builder(this, channelId)
.setSmallIcon(com.dongyang.android.youdongknowme.R.mipmap.ic_logo) // 알림 아이콘 설정
.setContentTitle(title) // 알림 제목
.setContentText(message) // 알림 내용
.setContentText(messageBody) // 알림 내용
.setAutoCancel(true) // 터치 시 자동으로 삭제되도록 설정
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) // 알림 소리 설정
.setVibrate(longArrayOf(0, 1000, 500, 1000)) // 진동 패턴 설정
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,25 @@ package com.dongyang.android.youdongknowme.standard.util
fun mapKeywordEnglishToKorean(english: String): String {
return when (english) {
"exam" -> "시험"
"course" -> "수강"
"lecture" -> "특강"
"season" -> "계절학기"
"signup" -> "수강"
"speciallecture" -> "특강"
"seasonalsemester" -> "계절학기"
"leaveofabsence" -> "휴학"
"returntoschool" -> "복학"
"graduate" -> "졸업"
"switchmajors" -> "전과"
"givingupthesemester" -> "학기포기"
"scholarship" -> "장학"
"tuition" -> "등록"
"leave" -> "휴학"
"return" -> "복학"
"graduation" -> "졸업"
"transfer" -> "전과"
"drop" -> "학기포기"
"recruitment" -> "채용"
"nationalscholarship" -> "국가장학"
"registration" -> "등록"
"employment" -> "채용"
"contest" -> "공모전"
"field" -> "현장실습"
"competition" -> "대회"
"service" -> "봉사"
"fieldtraining" -> "현장실습"
"volunteer" -> "봉사"
"dormitory" -> "기숙사"
"corona" -> "코로나19"
"club" -> "동아리"
else -> throw IllegalArgumentException("올바른 타입이 아닙니다.")
}
}

fun mapDepartmentCodeToKorean(code: Int): String {
return when (code) {
CODE.SCHOOL_CODE -> "학교"
CODE.MECHANICAL_ENGINE_CODE -> "기계공학과"
CODE.MECHANICAL_DESIGN_CODE -> "기계설계공학과"
CODE.AUTOMATION_ENGINE_CODE -> "자동화공학과"
CODE.ROBOT_ENGINE_CODE -> "로봇공학과"
CODE.COMPUTER_SOFTWARE_ENGINE_CODE -> "컴퓨터소프트웨어공학과"
CODE.COMPUTER_INFO_ENGINE_CODE -> "컴퓨터정보공학과"
CODE.ARTIFICIAL_ENGINE_CODE -> "인공지능소프트웨어공학과"
CODE.ELECTRICAL_ENGINE_CODE -> "전기공학과"
CODE.INFO_ELECTRONIC_ENGINE_CODE -> "정보전자공학과"
CODE.SEMICONDUCTOR_ENGINE_CODE -> "반도체전자공학과"
CODE.INFO_COMMUNICATION_ENGINE_CODE -> "정보통신공학과"
CODE.BIOCHEMICAL_ENGINE_CODE -> "생명화학공학과"
CODE.BIO_CONVERGENCE_ENGINE_CODE -> "바이오융합공학과"
CODE.ARCHITECTURE_CODE -> "건축과"
CODE.INTERIOR_DESIGN_CODE -> "실내건축디자인과"
CODE.VISUAL_DESIGN_CODE -> "시각디자인과"
CODE.BUSINESS_ADMINISTRATION_CODE -> "경영학과"
CODE.TAX_ACCOUNTING_CODE -> "세무회계학과"
CODE.DISTRIBUTION_MARKETING_CODE -> "유통마케팅학과"
CODE.HOTEL_TOURISM_CODE -> "호텔관광학과"
CODE.MANAGEMENT_INFORMATION_CODE -> "경영정보학과"
CODE.BIG_DATA_MANAGEMENT_CODE -> "빅데이터경영과"
"group" -> "동아리"
"studentcouncil" -> "학생회"
else -> throw IllegalArgumentException("올바른 타입이 아닙니다.")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.dongyang.android.youdongknowme.standard.base.BaseActivity
import com.dongyang.android.youdongknowme.ui.adapter.DepartAdapter
import com.dongyang.android.youdongknowme.ui.view.main.MainActivity
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber


class DepartActivity : BaseActivity<ActivityDepartBinding, DepartViewModel>(), DepartClickListener {
Expand Down Expand Up @@ -64,6 +65,7 @@ class DepartActivity : BaseActivity<ActivityDepartBinding, DepartViewModel>(), D
private fun getDepart(items: ArrayList<String>) {
return binding.btnDepartComplete.setOnClickListener {
viewModel.setDepartment(items[viewModel.selectDepartPosition.value ?: 0])
setResult(RESULT_OK)
finish()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class KeywordActivity : BaseActivity<ActivityKeywordBinding, KeywordViewModel>()
viewModel.getLocalKeywordList()

binding.btnKeywordComplete.setOnClickListener {
viewModel.subscribeCheckedKeyword()
setResult(RESULT_OK)
finish()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import com.dongyang.android.youdongknowme.data.local.SharedPreference
import com.dongyang.android.youdongknowme.databinding.ActivityMainBinding
import com.dongyang.android.youdongknowme.standard.base.BaseActivity
import com.dongyang.android.youdongknowme.ui.view.util.KeepStateNavigator
import com.google.android.gms.tasks.OnCompleteListener
import com.google.firebase.messaging.FirebaseMessaging
import org.koin.androidx.viewmodel.ext.android.viewModel
import timber.log.Timber

/* 메인 액티비티 */
class MainActivity : BaseActivity<ActivityMainBinding, MainViewModel>() {
Expand All @@ -36,23 +36,28 @@ class MainActivity : BaseActivity<ActivityMainBinding, MainViewModel>() {
binding.mainNvBottom.setupWithNavController(navController)

viewModel.checkFirstLaunch()
}

if (viewModel.isFirstLaunch.value == true) {
getFcmToken()
override fun initDataBinding() {
viewModel.isFirstLaunch.observe(this) { boolean ->
if (boolean) getFcmToken()
}
}

override fun initDataBinding() = Unit
override fun initAfterBinding() = Unit

private fun getFcmToken() {
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isSuccessful) {
viewModel.setFCMToken(task.result)
viewModel.setInitToken()
viewModel.setFCMToken(task.result).run { viewModel.setInitToken() }
Timber.d("first ${task.result}")
} else {
return@addOnCompleteListener
}
val token = task.result
SharedPreference.setFcmToken(token)

Timber.d("token : ${token}")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.dongyang.android.youdongknowme.standard.base.BaseViewModel
import com.dongyang.android.youdongknowme.standard.network.NetworkResult
import com.dongyang.android.youdongknowme.ui.view.util.Event
import kotlinx.coroutines.launch
import timber.log.Timber

class MainViewModel(private val mainRepository: MainRepository) : BaseViewModel() {
private val _errorState: MutableLiveData<Event<Int>> = MutableLiveData()
Expand Down Expand Up @@ -45,7 +46,7 @@ class MainViewModel(private val mainRepository: MainRepository) : BaseViewModel(

fun setFCMToken(token: String){
mainRepository.setFCMToken(token)
_FCMToken.postValue(token)
_FCMToken.value = token
}

private fun getUserDepart(){
Expand All @@ -69,6 +70,7 @@ class MainViewModel(private val mainRepository: MainRepository) : BaseViewModel(
)
)) {
is NetworkResult.Success -> {
Timber.d("first ${FCMToken.value.toString()}")
mainRepository.setIsFirstLaunch(false)
_isFirstLaunch.postValue(false)
_isLoading.postValue(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,29 @@ class SettingFragment : BaseFragment<FragmentSettingBinding, SettingViewModel>()
override val layoutResourceId: Int = R.layout.fragment_setting
override val viewModel: SettingViewModel by viewModel()

private lateinit var resultLauncher: ActivityResultLauncher<Intent>
private lateinit var resultLauncherKeyword: ActivityResultLauncher<Intent>
private lateinit var resultResultDepartment: ActivityResultLauncher<Intent>

private var topics: List<String> = emptyList()
private var department: String = ""

override fun initStartView() {
binding.tvSettingAppVersion.text = getAppVersion()
setResultKeyword()
setResultDepartment()
}

override fun initDataBinding() {

viewModel.myDepartment.observe(viewLifecycleOwner) { myDepartment ->
binding.tvSettingDepartment.text = myDepartment
department = myDepartment
viewModel.updateUserDepartment(department)
}

viewModel.myTopics.observe(viewLifecycleOwner) { myTopics ->
topics = topics
topics = myTopics
viewModel.updateUserTopic(topics)
}

viewModel.isAccessUniversityAlarm.observe(viewLifecycleOwner) { isChecked ->
Expand All @@ -54,36 +61,39 @@ class SettingFragment : BaseFragment<FragmentSettingBinding, SettingViewModel>()

binding.switchSettingUniversityAlarm.setOnCheckedChangeListener { compoundButton, _ ->
if (compoundButton.isChecked) {
viewModel.updateUserTopic(topics)
if (topics.isNotEmpty()) {
viewModel.updateUserTopic(topics)
}
} else {
viewModel.removeUserTopic()
}
}

binding.switchSettingDepartmentAlarm.setOnCheckedChangeListener { compoundButton, _ ->
if (compoundButton.isChecked) {
viewModel.updateUserDepartment()
if (department.isNotEmpty()) {
viewModel.updateUserDepartment(department)
}
} else {
viewModel.removeUserDepartment()
}
}

binding.btnSettingEditKeyword.setOnClickListener {
val intent = Intent(requireActivity(), KeywordActivity::class.java)
resultLauncher.launch(intent)
resultLauncherKeyword.launch(intent)
}

binding.btnSettingEditDepartment.setOnClickListener {
val intent = Intent(requireActivity(), DepartActivity::class.java)
startActivity(intent)
resultResultDepartment.launch(intent)
}

binding.btnSettingAppHelp.setOnClickListener {
val intent =
Intent(
Intent.ACTION_VIEW,
Uri.parse("https://docs.google.com/forms/d/e/1FAIpQLSeRTKalenelmffTbCZeK4mqmQg0palobghkXSoie1FlmV22ZQ/viewform")
)
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://docs.google.com/forms/d/e/1FAIpQLSeRTKalenelmffTbCZeK4mqmQg0palobghkXSoie1FlmV22ZQ/viewform")
)
startActivity(intent)
}

Expand All @@ -108,11 +118,21 @@ class SettingFragment : BaseFragment<FragmentSettingBinding, SettingViewModel>()
}

private fun setResultKeyword() {
resultLauncher =
resultLauncherKeyword =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
viewModel.getUserTopic()
viewModel.updateUserTopic(topics)
viewModel.getUserTopic().run { viewModel.updateUserTopic(topics) }
binding.switchSettingUniversityAlarm.isChecked = true
}
}
}

private fun setResultDepartment() {
resultResultDepartment =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK) {
viewModel.getUserDepartment()
binding.switchSettingDepartmentAlarm.isChecked = true
}
}
}
Expand Down
Loading

0 comments on commit 39e9b0b

Please sign in to comment.