본문 바로가기
개발/Android

[Kotlin] Android Push 알림(Notification) 바로 답장하기 with Remote Input

by jeomn 2022. 3. 2.

0. 알림을 보내는 App에서 작성

  • 알림을 받아 저장하는 별개의 App에서도 Remote Input을 받아서...저장할 수 있을까?
  • 그렇게 해보려다가 너무 모르겠어서...일단 알림을 보내는 App에서 받는 걸 우선적으로 해보기로 함
  • 별개의 App에서도 알림의 remote input을 받아올 수 있는 지 더 공부해볼 것..!
  • 현재 알고 있는 지식으로는 안될 것같음

 

1. MainActivity

  • 답장을 받을 intent를 생성
  • PendingIntent로 답장 받을 intent를 감싼다
    • Intent를 감싸고 있는 객체
    • 외부의 다른 어플리케이션에서 해당 Intent를 실행할 수 있도록 전달해주는 것
      • Broadcast로 받아서 startActivity를 하려다 실패했는데...다시 해볼 것.
    • options
      • FLAG_UPDATE_CURRENT: 이미 생성된 PendingIntent가 있으면, 그 안의 내용을 update해준다.
  • RemoteInput 생성해서 Notification 생성자 안에 Action으로 넣어준다!
    • androidx.core.app의 NotificationCompat을 사용했기 때문에...
    • android.app의 RemoteInput이 아니라 androidx.core.app.RemoteInput!
class MainActivity : AppCompatActivity() {

    val KEY_QUICK_REPLY_TEXT: String = "quick_reply"	//remoteInput의 답장 키 값

    override fun onCreate(savedInstanceState: Bundle?) {

        val subIntent = Intent(this, SubActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val pIntent = PendingIntent.getActivity(this, 1, subIntent, PendingIntent.FLAG_UPDATE_CURRENT)

        ...

        btn_noti.setOnClickListener{
            createNotification(pIntent, 1, "DEFAULT", "My notification", "Much longer text that can fit one line...")
        }

    }
    
    ...

    private fun createNotification(intent: PendingIntent, id:Int, channelId: String, title: String, text : String){
        var remoteInputAction = createNotificationActionRemoteInput(intent)

        var builder = NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.drawable.ic_launcher_foreground)    //필수
            .setContentTitle(title)
            .setContentText(text)
            .addAction(remoteInputAction)	//action으로 remoteInput 추가
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setCategory(Notification.CATEGORY_MESSAGE)
        ...
    }

    private fun createNotificationActionRemoteInput(intent: PendingIntent):NotificationCompat.Action{
        var action = NotificationCompat.Action.Builder(
            R.drawable.ic_launcher_background, "Reply", intent)
            .addRemoteInput(
                RemoteInput.Builder(KEY_QUICK_REPLY_TEXT)
                    .setLabel("Quick reply").build())
            .build();
        return action
    }
}

 

2. SubActivity

  • 답장 결과를 받을 activity 생성
  • RemoteInput으로 결과를 받아서 activity의 text view로 보여주게끔
  • 결과를 받은 이후에는 사용자에게 알려주고, spinner를 그만 돌게 하기 위해서? 다시 noti를 보내줘야 한다고 하는데.....?
    • 안보내주면...그냥 하단에 알림 답장이 쌓이고, spinner는 알아서 안돌길래 주석처리해서 테스트했음
    • 실제 서비스 개발할 때는 주석 풀기!

답장 내용을 보여줄 TextView와 다시 MainActivity로 돌아가기 위한 Back 버튼

class SubActivity : AppCompatActivity() {

    val KEY_QUICK_REPLY_TEXT: String = "quick_reply"	//내가 설정한 Key

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sub)

        getDirectReply()	//답장 받는 함수

        btn_back.setOnClickListener{	//Main으로 돌아가기 위한 버튼
            finish()
        }
    }

    private fun getDirectReply(){
        val remoteInput = RemoteInput.getResultsFromIntent(intent)
        remoteInput?.let{
            val message = it.getCharSequence(KEY_QUICK_REPLY_TEXT).toString()
            reply.setText(message)
            //receiveReplySuccess()	//답장 받고, 다시 Noti에 알려주는 함수...
        }
    }

    private fun receiveReplySuccess(){
        val channelId = "DEFAULT"	//내가 설정한 채널ID
        val notiId = 1		//내가 설정한 알림ID

        val repliedNotification = NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setContentText("successful received message")
            .build()
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.notify(notiId, repliedNotification)
    }
}

 

3. 결과

Notification Remote Input으로 받은 데이터를 새 activity에 띄워준 모습

 

4. Broadcast로...하기

  • 처음에 intent로 보내주는 게 잘 안됐어서...
  • Broadcast로 보내고 toast로 띄워주는 걸 했었다
  • AndroidManifest.xml
    • manifest에 receiver 등록
<manifest
    ....
    <application
        ...>
        <receiver android:name=".MyBroadcastReceiver"/>
    </application>
</manifest>
  • MainActivity.kt
class MainActivity : AppCompatActivity() {

    val KEY_QUICK_REPLY_TEXT: String = "quick_reply"

    override fun onCreate(savedInstanceState: Bundle?) {
        ...

        val subIntent = Intent(this, MyBroadcastReceiver::class.java)
        subIntent.action = "REPLY_ACTION"
        subIntent.putExtra("KEY_NOTIFICATION_ID", 1)
        subIntent.putExtra("KEY_CHANNEL_ID", "DEFAULT")

        val pIntent = PendingIntent.getBroadcast(this, 1, subIntent, PendingIntent.FLAG_UPDATE_CURRENT)
        
        ...

    }
    ...
}
  • MyBroadcastReceiver.kt
class MyBroadcastReceiver: BroadcastReceiver() {

    val KEY_QUICK_REPLY_TEXT: String = "quick_reply"

    override fun onReceive(context: Context?, intent: Intent?) {
        intent?.apply {
            if("REPLY_ACTION".equals(action)){
                val message = getDirectReply(this)
                Toast.makeText(context, message, Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun getDirectReply(intent : Intent) : CharSequence? {
        val remoteInput = RemoteInput.getResultsFromIntent(intent)
        return remoteInput?.getCharSequence(KEY_QUICK_REPLY_TEXT)
    }
}
  • 결과

Broadcast로 답장 내용 Toast로 띄워준 모습

 

 

5. 참조

댓글