[트러블슈팅] Braze Android UI 중첩 이슈

김하연·2024년 3월 5일
0

우당탕탕

목록 보기
8/11

안드로이드 기기 Braze top slideup 형태 인앱메시지 위치가 노티바와 중첩되는 이슈

Braze 노티 수신 시, android 에서만 인앱메세지의 ui가 OS 상태바와 중첩되는 이슈가 있어 이슈 추적 및 해소한 과정을 기록해보았다.


이슈 추적 과정

1. Braze가 수신되는 푸시 메세지를 감지하는 방법과 해당 코드 위치 확인

Braze.Events.PUSH_NOTIFICATION_EVENT
🔗 (참고문서) Listen for push notifications (optional)

위 문서를 참고한 결과, 문서에 안내된 대로 App.tsx 파일에 아래와같이
브레이즈 노티 알림을 감지하는 코드가 추가되어 있음

const brazePushNotificationSubscription = Braze.addListener(
  Braze.Events.PUSH_NOTIFICATION_EVENT,
  (data: { push_event_type: any; title: any; deeplink: any }) => {
  ... // 생략
});

그러나 이곳에서는 인앱메세지 구현체를 찾을 수 없었기 때문에 인앱메세지를 구현하고 스타일링하는 부분을 찾아야 했음.


2. 코드상으로는 구현체를 찾을 수 없었기에 Braze 설정 코드에서 제어하는 부분이라고 판단. 메세지 커스터마이징 관련 가이드 문서 검색

인앱메세지의 display와 행동을 커스터마이징하는 이벤트 핸들러로 추정되는 리스너 확인
🔗 (참고문서) Custom Listeners
🔗 (참고문서) IInAppMessageManagerListener
🔗 (참고문서) Custom manage in-app message display and behavior

위 문서에 의하면, IInAppMessageManagerListener 를 구현하는 클래스를 생성하면, IInAppMessageManagerListener 내부의 콜백들이 인앱메세지의 라이프사이클 여러 지점에 거쳐 호출될 수 있음을 파악

위 코드가 구현되어있는지 검색해보니 InAppMessageManagerListener.kt 파일 내부에 실제로 구현되어 있음

...
import android.util.Log
import com.braze.models.inappmessage.IInAppMessage
import com.braze.ui.inappmessage.InAppMessageOperation
import com.braze.ui.inappmessage.listeners.IInAppMessageManagerListener
...

class InAppMessageManagerListener(private val reactNativeHost: ReactNativeHost): IInAppMessageManagerListener {
  override fun beforeInAppMessageDisplayed(inAppMessage: IInAppMessage): InAppMessageOperation {
    val parameters = WritableNativeMap();
    parameters.putString("inAppMessageJsonString", inAppMessage.forJsonPut().toString())
    reactNativeHost
      .reactInstanceManager
      .currentReactContext
      ?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
	  ?.emit("inAppMessageReceived", parameters)

    return when (inAppMessage.extras["display"]) {
      "discard" -> InAppMessageOperation.DISCARD
      else -> InAppMessageOperation.DISPLAY_NOW
    }
  }
}
  • beforeInAppMessageDisplayed 메서드가 브레이즈로부터 인앱메세지를 수신했을 때 실행되는 메서드임을 파악
  • 내부에 메세지의 위치를 수정할 수 있는 코드를 GPT에게 요청하여 아래 코드를 받았고 beforeInAppMessageDisplayed 메서드 내부에 추가하였으나 안드로이드 빌드 실패
// 추가한 코드
inAppMessage.setExtras("position", "top")
inAppMessage.setExtras("offset", 100)
...
import android.util.Log
import com.braze.models.inappmessage.IInAppMessage
import com.braze.ui.inappmessage.InAppMessageOperation
import com.braze.ui.inappmessage.listeners.IInAppMessageManagerListener
...

class InAppMessageManagerListener(private val reactNativeHost: ReactNativeHost): IInAppMessageManagerListener {
  override fun beforeInAppMessageDisplayed(inAppMessage: IInAppMessage): InAppMessageOperation {
    
    // 코드 추가된 위치
    inAppMessage.setExtras("position", "top")
	inAppMessage.setExtras("offset", 100)
    
    val parameters = WritableNativeMap();
    parameters.putString("inAppMessageJsonString", inAppMessage.forJsonPut().toString())
    reactNativeHost
      .reactInstanceManager
      .currentReactContext
      ?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
	  ?.emit("inAppMessageReceived", parameters)

    return when (inAppMessage.extras["display"]) {
      "discard" -> InAppMessageOperation.DISCARD
      else -> InAppMessageOperation.DISPLAY_NOW
    }
  }
}

3. Custom styling 문서 확인

🔗 (참고문서) Custom Styling

styles.xml 파일에서 Braze SDK의 디폴트 스타일을 확인할 수 있다하여 해당 파일 확인해보니 브레이즈 스타일 관련된 코드는 없었으나 styles.xml 파일 자체는 아래와 같이 존재했음

<resources>
  <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
    <item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
            
    <item name="colorPrimary">#...</item>
    <item name="colorPrimaryDark">#...</item>
    <item name="colorAccent">#...</item>
  </style>
            
  <style name="AppTheme.Splash" parent="AppTheme">
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowBackground">@color/splash</item>
    <item name="android:statusBarColor">@android:color/transparent</item>
	...
  </style>
</resources>

그리고 문서에서 보여주는 디폴트 스타일의 예시

<style name="Braze"/>
<style name="Braze.InAppMessage"/>
<style name="Braze.InAppMessage.Header">
  <item name="android:layout_height">wrap_content</item>
  <item name="android:layout_width">match_parent</item>
  <item name="android:padding">0.0dp</item>
  <item name="android:background">@android:color/transparent</item>
  <item name="android:textColor">@color/com_braze_inappmessage_header_text</item>
  <item name="android:textSize">20.0sp</item>
  <item name="android:lineSpacingMultiplier">1.3</item>
  <item name="android:gravity">center</item>
  <item name="android:textStyle">bold</item>
  <item name="android:layout_centerHorizontal">true</item>
</style>

위 코드를 참고하여 브레이즈 인앱메세지에 margin을 아래처럼 추가하여 최종적으로 이슈를 해소하였다.

<style name="Braze.InAppMessage">
  <item name="android:layout_marginTop">30.0dp</item>
</style>

트러블슈팅 in 트러블슈팅

안드로이드 스타일은 브라우저 CSS와 또 달라서 margin의 경우 marginTop이 아닌 layout_marginTop 으로 지정해야 한다. 처음에 <item name="android:marginTop"> 으로 지정했다가 빌드 에러가 발생해서 또 실패했나보다 하고 좌절했는데, 다시 검색해보니 표현방법이 달랐던 것! 간단히 해결할 수 있는 문제였다.

🔗 참고한 블로그 [Android UI - padding, layout_margin 사용하기]


이번 이슈 해결하면서 느낀 점

사실 작업하기 전부터 Native 코드를 만져야 할 것만 같아서 불안하긴 했다. 하지만 Braze 자체에서 설정하는 세팅도 아니고, 노티피케이션 쪽 코드는 이런저런 작업을 위해 여러번 보고 손도 댔던 부분이기에 면밀히 살펴보면 찾을 수 있을거란 생각은 들었다.
그리고 결국엔 해결하면서 느낀점 두가지가 있다.

  • 공식문서는 답이다.
    이거는 모든 이슈와 마주하고 그 이슈를 해결할때마다 반복해서 느끼고 있는 부분이다. 모르겠으면 공식문서부터 참고하자. 그곳에는 내가 겪은 모든 이슈를 나보다 먼저 마주한 사람들의 흔적이 있고 답이 아니더라도 결정적인 힌트는 얻을 수 있다.
  • Native라고 쫄지말자!
    네이티브 관련 영역을 작업할때마다 미지의 세계를 탐구하는 것 같아 막연함에 의한 심리적 위축이 됐던 것 같다. 하지만 이번 이슈는 생각보다 쉽게 해결되었고 어려운 내용도 아니었다. 그러니까 뭘 하든 미리 쫄지말자!

0개의 댓글