inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[초중급편] 안드로이드 데이팅 앱 만들기(Android Kotlin)

매칭이 되면 Notification 띄우기

Notification 구현시 컴파일에러

355

khs50851

작성한 질문수 14

0

class MainActivity : AppCompatActivity() {

    lateinit var cardStackAdapter: CardStackAdapter
    lateinit var manager : CardStackLayoutManager
    private val TAG = "MainActivity"
    private val usersDataList = mutableListOf<UserDataModel>()
    private var userCount = 0
    private val uid =FireBaseAuthUtils.getUid()
    private lateinit var currentUserGender : String
    private val REQUEST_CODE = 123

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val isTiramisuOrHigher = Build.VERSION.SDK_INT>= Build.VERSION_CODES.TIRAMISU
        val notificationPermission = Manifest.permission.POST_NOTIFICATIONS

        var hasNotificationPermission =
            if (isTiramisuOrHigher)
                ContextCompat.checkSelfPermission(this,notificationPermission) == PackageManager.PERMISSION_GRANTED
            else true

        val launcher = registerForActivityResult(ActivityResultContracts.RequestPermission()){
            hasNotificationPermission = it
        }

        if(!hasNotificationPermission) {
            launcher.launch(notificationPermission)
        }

        val setting = findViewById<ImageView>(R.id.settingIcon)
        setting.setOnClickListener{
//            val auth = Firebase.auth
//            auth.signOut()
//
            val intent = Intent(this,SettingActivity::class.java)
            startActivity(intent)
        }

        val cardStackView = findViewById<CardStackView>(R.id.cardStackView)

        manager = CardStackLayoutManager(baseContext,object : CardStackListener{
            override fun onCardDragging(direction: Direction?, ratio: Float) {

            }

            override fun onCardSwiped(direction: Direction?) {
                if(direction == Direction.Right){
                    userLikeOtherUser(uid,usersDataList[userCount].uid.toString())
                }

                if(direction == Direction.Left){

                }

                userCount = userCount + 1

                if(userCount == usersDataList.count()){
                    getUserDataList(currentUserGender)
                    Toast.makeText(this@MainActivity,"유저 리스트를 새롭게 받아옵니다.",Toast.LENGTH_SHORT).show()
                }

            }

            override fun onCardRewound() {

            }

            override fun onCardCanceled() {

            }

            override fun onCardAppeared(view: View?, position: Int) {

            }

            override fun onCardDisappeared(view: View?, position: Int) {

            }

        })

        cardStackAdapter = CardStackAdapter(baseContext,usersDataList)
        cardStackView.layoutManager = manager
        cardStackView.adapter = cardStackAdapter

//        getUserDataList()
        getMyUserData()
    }

    private fun getMyUserData(){
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {

                val data = dataSnapshot.getValue(UserDataModel::class.java)
                Log.d(TAG,data.toString())

                currentUserGender = data?.gender.toString()

                getUserDataList(currentUserGender)

            }

            override fun onCancelled(databaseError: DatabaseError) {
                // Getting Post failed, log a message
                Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
            }
        }
        FireBaseRef.userInfoRef.child(uid).addValueEventListener(postListener)
    }

    private fun getUserDataList(currentUserGender : String){
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {

//                val post = dataSnapshot.getValue<Post>()

                for(dataModel in dataSnapshot.children){
                    val user = dataModel.getValue(UserDataModel::class.java)
                    if(!user!!.gender.toString().equals(currentUserGender)){
                        usersDataList.add(user!!)
                    }

                }
                cardStackAdapter.notifyDataSetChanged()
            }

            override fun onCancelled(databaseError: DatabaseError) {
                // Getting Post failed, log a message
                Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
            }
        }
        FireBaseRef.userInfoRef.addValueEventListener(postListener)
    }

    private fun userLikeOtherUser(myUid : String, otherUid : String) {
        FireBaseRef.userLikeRef.child(myUid).child(otherUid).setValue("true")
        getOtherUserLikeList(otherUid)
    }

    private fun getOtherUserLikeList(otherUid : String){
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {

                // 여기 리스트에서 나의 UID가 있나 확인 필요
                for(dataModel in dataSnapshot.children){

                    val likeUserKey = dataModel.key.toString()

                    if(likeUserKey.equals(uid)){
                        Toast.makeText(this@MainActivity,"매칭완료",Toast.LENGTH_SHORT).show()
                        createNotificationChannel()
                        sendNotification()

                    }

                }

            }

            override fun onCancelled(databaseError: DatabaseError) {
                // Getting Post failed, log a message
                Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
            }
        }
        FireBaseRef.userLikeRef.child(otherUid).addValueEventListener(postListener)
    }

    // 알림

    private fun createNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is not in the Support Library.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 채널 이름
            val name = "name"
            val descriptionText = "description"
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel("TestChannel", name, importance).apply {
                description = descriptionText
            }
            // Register the channel with the system.
            val notificationManager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }

    private fun sendNotification(){

        var builder = NotificationCompat.Builder(this, "TestChannel")
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setContentTitle("My notification")
            .setContentText("Hello World!")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setCategory(NotificationCompat.CATEGORY_MESSAGE)
        with(NotificationManagerCompat.from(this)){
            notify(123,builder.build())
        }

    }

}

안녕하세요. 알림기능 구현하는데

notify(123,builder.build())

위 부분에서 Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException 이런 에러가 아직도 발생하고있는데 어떻게 해결할수 있을지 자세한 답변을 부탁드려도될까요? 구글링 해봤는데 명확히 어떤코드 입력해서 컴파일에러를 지울 수 있을지 모르겠습니다. 빠른답변 부탁드리겠습니다.

android kotlin firebase

답변 2

0

khs50851

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.POST_NOTIFICATIONS
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        var builder = NotificationCompat.Builder(this, "TestChannel")
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setContentTitle("매칭완료")
            .setContentText("매칭이 성사되었습니다. 메세지를 확인하세요!")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setCategory(NotificationCompat.CATEGORY_MESSAGE)
        with(NotificationManagerCompat.from(this)) {
            notify(123, builder.build())
        }
    } else {
        // 권한 요청
        requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), REQUEST_CODE)
    }
}

위와 같이 코드를 작성하라는 말씀이신가요? 이렇게하면 컴파일 에러는 사라지는데 서로 좋아요시 알림이 오지 않네요..

AndroidManifest.xml파일엔

<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

위 코드가 추가되어있습니다.

조금 더 검색해봤는데 아래 with~ 코드를 지우고

with(NotificationManagerCompat.from(this)){
    notify(123,builder.build())
}
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(REQUEST_CODE, builder.build())

이렇게 코드를 넣으니 컴파일 에러 없이 실행 되네요 REQUEST_CODE엔 대충 정수 123을 넣었습니다.

0

개복치개발자

전체 코드를 압축해서 구글 드라이브에 업로드 후 링크를 공유해주시겠어요?
한번 살펴보겠습니다!

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. khs50851님의 질문에 대해 관련 자료를 찾았습니다.

질문하신 내용에서 Android Tiramisu 버전(API level 33 이상)에서는 Notification을 사용하기 위해 사용자의 명시적인 권한 요청이 필요합니다. 이를 위해 Manifest.permission.POST_NOTIFICATIONS 권한이 필수적인데, 질문하신 부분을 해결하기 위해서는 사전에 이 권한을 확인하고 요청하는 과정이 필요합니다.

“Notification 띄우기를 하는 중에 났던 에러들 입니다!” 이 게시물은 Notification 관련 이슈들에 대해서 정리하고 있으며, 질문자님의 문제와 관련된 내용도 포함되어 있습니다. 특히, 해당 게시물에서는 API level 33 이상에서의 Notification 사용 방법 및 권한 요청 과정에 대하여 설명하고 있습니다.

이 게시글에서는 아래처럼 권한을 요청하는 코드 예시를 제공하고 있습니다:

// API level 33 이상일 경우
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    if (ContextCompat.checkSelfPermission(
            this,
            Manifest.permission.POST_NOTIFICATIONS
        ) == PackageManager.PERMISSION_GRANTED
    ) {
        // 권한이 있을 때의 알림 전송 로직
    } else {
        // 권한 요청
        requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), REQUEST_CODE)
    }
} else {
    // API level 33 미만일 경우, 권한 없이 알림 전송 로직
}

위 예시와 같이, 알림을 보내기 전에 사용자로부터 필요한 권한을 명시적으로 요청하는 로직이 필요합니다. 이 과정을 거친 후에 notify 메서드를 호출하면, 권한 관련 에러 없이 알림을 전송할 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

CardStackView 라이브러리 추가에 실패합니다.

0

98

1

CardStackView

0

125

2

CardStackView 오류 정상적으로 구현이 되지 않습니다.

0

199

3

최신화 된 강의 요청합니다

0

160

2

auth.currentUser?.uid.toString() 가 null 이 나와요

0

194

1

혹시.. 지금 최신 환경 상, 강의 내용대로 진행이 안 되는 걸까요?

0

240

1

현시점에서 알려주신 방법대로 서버키를 받는것이 안되는것같습니다

0

261

2

3강 firebase 쓰기가 동작하질않아요

0

185

1

강사님 실시간으로 혹시 문의하는 방법은 없을까요??

0

185

1

해당 강의 들으시는 분들 중에 교육관련해서 서로 얘기 나누실 분 있으신가요??

0

158

1

강사님 FCM 단계 진행하면서 오류들이 너무 많이 발생합니다...

0

207

1

FCM 토큰 문의

0

214

1

강사님 FCM 단계에서 전체적으로 앱 문제가 발생해서 혹시 원격으로 조치 해주실 수 있나요?

0

232

1

토큰 정보 유저정보에 저장하기 강의 4분 12초 코드를 동일하게 입력했는데 적용이 잘 안되는 것 같아요.

0

397

3

토큰 받아와서 메세지 보내기 강의 2분 20초 로그캣 확인 하는 창이 다르고 토큰 값이 안떠요.

0

221

1

FCM 강의, firebaseservice 클래스 내 오류코드 해결방안이 궁금합니다.

0

274

2

FCM 강의 중간부터 코드 오류가 발생했는지 앱에서 회원가입을 해도 파이어베이스 Authentication에는 회원등록이 해도 화면이 넘어가지 않고 데이터도 저장이 안 되네요.

0

294

3

섹션 1 CardStackView의 Implement members 질문있습니다.

0

228

1

수업자료 다운로드 후 알집풀기에서 오류가 발생합니다.

0

465

3

Retrofit 사용해보기 강의 2:20 쯤에 작성된 복사된 코드는 어디서 받나요?

0

234

2

강의 FCM 소개 1:56에 디펜던시 추가하는게 최신버전으로 바뀐 듯합니다.

0

277

1

매칭이 되면 알람 띄우기 강의에서 오류문구 해결방안이 궁금합니다.

0

356

3

소스코드 다운이 불가능합니다..

0

145

1

나와 다른 성별의 유저 불러오기 강의에서 에뮬레이터에서 앱이 켜졌다가 바로 꺼져요.

0

459

11