• 카테고리

    질문 & 답변
  • 세부 분야

    모바일 앱 개발

  • 해결 여부

    미해결

Notification 구현시 컴파일에러

24.03.25 17:21 작성 조회수 96

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 이런 에러가 아직도 발생하고있는데 어떻게 해결할수 있을지 자세한 답변을 부탁드려도될까요? 구글링 해봤는데 명확히 어떤코드 입력해서 컴파일에러를 지울 수 있을지 모르겠습니다. 빠른답변 부탁드리겠습니다.

답변 2

·

답변을 작성해보세요.

0

khs50851님의 프로필

khs50851

질문자

2024.03.25

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

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.03.25

안녕하세요, 인프런 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 메서드를 호출하면, 권한 관련 에러 없이 알림을 전송할 수 있습니다.

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