MessageStyle
이번 글에서는 Android Notification Style 중 MessageStyle의 이미지 표시하는 방법에 대해서 알아보려고 합니다. MessageStyle은 Android에서 제공하는 알림 스타일 중 채팅처럼 대화형 데이터를 표시하는 목적으로 사용하는 스타일입니다.
최근 회사에서 앱의 알림 스타일을 MessageStyle로 변경하는 작업을 진행했는데요.이미지를 표시하는 부분에서 어려움을 느껴서 이번 글에서 정리해보려고 합니다.
기본 사용법
val person = Person.Builder() --- (1)
.setName("자비스")
.setIcon(IconCompat.createWithBitmap(bitmap))
...
.build()
val style = NotificationCompat.MessagingStyle(person) --- (2)
.addMessage(
NotificationCompat.MessagingStyle.Message("안녕하세요", Date().time, person)
)
val builder = NotificationCompat.Builder(this, channelId) --- (3)
...
.setStyle(style)
.setCategory(Notification.CATEGORY_MESSAGE)
...
우선 MessageStyle의 사용법을 아주 간단히 알아보면
(1) - Person 객체 생성
Person 클래스는 생성자로 직접 객체를 생성할 수 없고 Builder 객체로 생성 가능합니다. 프로필 이미지, 사용자 이름 등 정보를 저장하는 Immutable 객체입니다.
(2) - MessageStyle 객체 생성
MessageStyle 객체는 메시지 응답을 보내는 유저의 이름으로 사용될 문자열, 또는 (1)에서 만든 Person 객체를 통해 생성 가능합니다. addMessage 함수로 알림에 표시할 메시지 정보를 저장합니다.
(3) - 적용
Notification Builder 객체에서 (2)에서 만든 Style을 적용합니다
MessageStyle 이미지 표시
(2) 코드 부분에서 메시지를 추가하는 addMessage 함수를 확인할 수 있었습니다.
addMessage 함수는 Message 객체 인자로 받고 있는데요. 이 Message 객체에 이미지를 추가하는 setData 함수가 있습니다.
친절한 주석으로 설명되어 있지만 정리해 보자면 이미지의 mimeType, 이미지의 uri 2개의 인자가 필요합니다.
이미지의 mimeType은 image/png
등이 해당되며 타입을 굳이 명시하지 않고 image/
로도 충분합니다.
중요한 부분은 2번째 인자인 이미지의 uri입니다. 단순 바이너리로는 넘길 수 없고, 저장소에 저장하고 해당 파일의 위치를 의미하는 Uri를 넘겨야 합니다. System UI에서 접근이 가능한 Uri를 넘겨야 하는 것이 매우 중요합니다.
이미지를 Uri 가져오기
private fun getFileUri(file: File): Uri {
return FileProvider.getUriForFile(this, "$packageName.fileprovider", file)
}
위 함수는 이미지가 저장되어 있는 파일의 uri를 FileProvider를 이용해 가져오는 코드입니다.
그런데 Fileprovider는 그냥 사용할 수 없고 몇 가지 설정이 필요합니다.
- AndroidManifest.xml
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
- values/xml/filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path path="/" name="cache" />
</paths>
setData로 이미지 데이터 적용하기
val style = NotificationCompat.MessagingStyle(person)
.addMessage(
NotificationCompat.MessagingStyle.Message("image", Date().time, person)
.also {
if (uri != null) {
it.setData("image/", uri)
}
}
)
주의할 점은 Message의 생성자에서 text 인자를 null로 설정하면 안 됩니다.
grantUriPermission로 퍼미션 직접 부여하기
Fileprovider 자체로도 타 앱에 이미지 파일 접근 권한을 부여하지만, 일부 기기에서는 이미지가 표시 안 되는 케이스가 발생할 수 있습니다. 필자도 이 이슈로 오랜 시간 삽질했습니다.. ㅜㅜ
val uri = file?.let { getFileUri(it) }
uri?.grantReadPermissionToSystem()
private fun Uri.grantReadPermissionToSystem() {
applicationContext.grantUriPermission("com.android.systemui", this,
Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
grantUriPermission 함수는 다른 패키지에게 권한을 부여하는 함수입니다. 이를 알림을 관리하는 것으로 추측되는 com.android.systemui
패키지에 이미지 uri의 권한을 강제적으로 부여합니다.
이번 글에서 사용한 전체 코드는 아래 링크에서 확인 가능합니다.
MessageStyle 적용 by jaeryo2357 · Pull Request #8 · jaeryo2357/posting_android_sample_code
github.com
'Android > Common' 카테고리의 다른 글
[Android] touchDelegate로 뷰 계층 제약 없이 터치 영역 확장하기 (1) | 2023.11.30 |
---|---|
[Android] InAppUpdate 기능 알아보기 (1) | 2023.11.09 |
[Android] 앱 성능 개선 - 앱 시작 시간 (1) | 2023.10.10 |
[Android] minSdk, compileSdk, targetSdk (0) | 2023.09.25 |
[Android] Radius 올바르게 적용하기 (0) | 2023.05.24 |