시배's Android

Hi Jack Mocker | Android 오픈 소스 배포기 (4) 본문

Android/Hi Jack Mocker

Hi Jack Mocker | Android 오픈 소스 배포기 (4)

si8ae 2024. 7. 11. 17:15

Hi Jack Mocker란?

 

GitHub - koreatlwls/Hi-Jack-Mocker: Hi-Jack-Mocker is a project that leverages OkHttp3's interceptor to intercept and modify net

Hi-Jack-Mocker is a project that leverages OkHttp3's interceptor to intercept and modify network requests and responses, allowing you to verify the UI easily. - koreatlwls/Hi-Jack-Mocker

github.com

Hi Jack Mocker는 비개발자도 UI 엣지 케이스를 쉽게 테스트할 수 있도록 돕는 라이브러리입니다. 이 프로젝트는 OkHttp3 인터셉터를 활용하여 네트워크 요청과 응답을 가로채고 수정할 수 있게 합니다. 이를 통해 개발자뿐만 아니라 다양한 사용자들이 다양한 시나리오를 테스트할 수 있게 합니다.

 

HiJackMocker

HiJackMocker의 구성 및 초기화

HiJackMocker는 object 키워드를 통해 싱글톤 클래스로 구현되었습니다. 이는 Hilt와 같은 의존성 주입 라이브러리를 사용하지 않는 프로젝트에서도 쉽게 사용할 수 있도록 하기 위함입니다.

싱글톤 클래스 정의 및 초기화

 object HiJackMocker {
    internal lateinit var interceptorManager: InterceptorManager
    private lateinit var hjmDataStore: HjmDataStore
    private lateinit var hjmInterceptor: HjmInterceptor

    fun initialize(context: Context) {
        require(context is Application) {
            "Context must be an instance of Application"
        }

        hjmDataStore = HjmDataStore(context = context.applicationContext)
        interceptorManager = InterceptorManager()
        hjmInterceptor =
            HjmInterceptor(
                context = context.applicationContext,
                interceptorManager = interceptorManager,
                hjmDataStore = hjmDataStore
            )

        context.addLifecycleCallbacks()
    }
}

initialize 함수를 통해 HiJackMocker를 초기화합니다. 이 함수는 Application 컨텍스트를 받아 HjmDataStore, InterceptorManager, HjmInterceptor를 초기화합니다. 또한, Application의 생명주기 콜백을 등록하여 HJM 모드 버튼을 관리합니다.

OkHttpClient 빌더 확장 함수

fun OkHttpClient.Builder.addHiJackMocker(): OkHttpClient.Builder =
    this.addInterceptor(hjmInterceptor)

이 확장 함수를 통해 OkHttpClient 빌더에 우리가 작성한 HjmInterceptor를 추가할 수 있습니다. 이 함수는 OkHttpClient 빌더에 HjmInterceptor를 쉽게 추가할 수 있도록 도와줍니다.

HJM 모드 버튼 추가

HJM 모드를 활성화하거나 비활성화할 수 있는 버튼을 추가하기 위해 Application의 액티비티 생명주기 콜백을 활용합니다.

액티비티 생명주기 콜백 등록

private fun Application.addLifecycleCallbacks() {
    registerActivityLifecycleCallbacks(
        object : Application.ActivityLifecycleCallbacks {
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
            override fun onActivityStarted(activity: Activity) {}

            override fun onActivityResumed(activity: Activity) {
                if (activity !is HjmActivity) {
                    addHjmModeButton(activity)
                }
            }

            override fun onActivityPaused(activity: Activity) {}
            override fun onActivityStopped(activity: Activity) {}
            override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
            override fun onActivityDestroyed(activity: Activity) {
                if (activity is HjmActivity) {
                    interceptorManager.isHjmActivityRunning.set(false)
                }
            }
        }
    )
}

액티비티가 재개될 때마다 HjmActivity가 아닌 경우 HJM 모드 버튼을 추가합니다.

private fun addHjmModeButton(activity: Activity) {
    val composeView = ComposeView(activity).apply {
        setContent {
            HjmModeButton()
        }
    }

    val params = FrameLayout.LayoutParams(
        FrameLayout.LayoutParams.WRAP_CONTENT,
        FrameLayout.LayoutParams.WRAP_CONTENT
    ).apply {
        gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
        topMargin = 150
    }

    activity.addContentView(composeView, params)
}

@Composable
private fun HjmModeButton() {
    val checked by hjmDataStore.getHjmModeFlow().collectAsState(initial = false)
    val scope = rememberCoroutineScope()

    IconButton(
        onClick = {
            scope.launch {
                hjmDataStore.setHjmMode(!checked)
            }
        }
    ) {
        Image(
            modifier = Modifier.size(36.dp),
            painter = painterResource(
                id = if (checked) R.drawable.hjm_mode_on
                else R.drawable.hjm_mode_off
            ),
            contentDescription = null,
        )
    }
}

addHjmModeButton 함수는 액티비티 상단에 HJM 모드를 켜고 끌 수 있는 버튼을 추가합니다. 이 버튼은 Compose로 구현되어 있으며, 클릭 시 HJM 모드를 토글합니다.

 

앞으로

앞으로는 HiJackMocker를 실제 프로젝트에 적용하면서 겪은 문제와 해결 방안을 공유하겠습니다.