inflearn logo
강의

Course

Instructor

[Beginner-Intermediate] Creating an Android Dating App (Android Kotlin)

Display notification when matching occurs

Notification 구현시 컴파일에러

355

khs50851

14 asked

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

Answer 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

bokchi

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

0

communityai8509

안녕하세요, 인프런 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

198

3

최신화 된 강의 요청합니다

0

159

2

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

0

193

1

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

0

240

1

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

0

261

2

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

0

183

1

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

0

185

1

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

0

157

1

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

0

206

1

FCM 토큰 문의

0

214

1

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

0

231

1

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

0

396

3

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

0

221

1

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

0

272

2

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

0

294

3

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

0

227

1

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

0

464

3

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

0

234

2

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

0

275

1

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

0

355

3

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

0

143

1

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

0

457

11