본문 바로가기

Android

Android 앱에 디버깅 플랫폼 Flipper 적용

반응형

Flipper는 iOS, Android 및 React Native 앱을 디버깅하기 위한 플랫폼입니다. 데스크탑 인터페이스로 간단하게 앱을 시각화, 검사하고 제어할 수 있습니다. Flipper를 그대로 사용해도 좋지만, 필요에 따라 플러그인 API를 사용하여 확장할 수도 있습니다. 오늘은 Android 앱에 Flipper를 적용하는 법에 대해 알아보겠습니다. 실행 환경은 macOS입니다.

먼저 아래 링크에서 자신의데스크탑 OS에 맞는 프로그램을 다운로드 받습니다.

https://fbflipper.com/

Flipper 실행 화면은 다음과 같습니다. 왼쪽 아래 Setup Doctor를 눌러 봅니다.

데스크탑 프로그램에서는 다음과 같은 설정을 해야 합니다:

OpenSSL과 Watchman 설치는 다음 명령어로 가능합니다. (먼저 brew 설치가 필요합니다.)

brew install openssl watchman

Android SDK는 Android Studio 설치 시 함께 설치됩니다. 해당 SDK의 경로를 확인하는 법은 다음과 같습니다. Android Studio를 켜고 Project Structure에 진입합니다. (단축키 cmd + ;) SDK Location에 존재하는 경로를 복사합니다.

이제 경로를 설정해봅시다. 왼쪽 아래 톱니바퀴 버튼을 눌러 Settings 메뉴를 눌러봅니다.

Android Developer 항목의 Android SDK location에 해당 경로를 입력합니다.

제대로 입력하면 글자가 검정색이 됩니다. iOS Developer가 아니라면 메뉴를 꺼도 좋습니다.

이 단계까지 마쳤다면 Flipper 기본 기능인 Crash Reporter와 Logs를 사용할 수 있습니다. 앱이 강제 종료 될 경우 알림이 표시되며, Crash Reporter에서 스택 트레이스를 확인할 수 있고, Logs에서는 Logcat과 같이 로그를 확인할 수 있습니다.

Flipper Logs 메뉴에서는 설정한 Log Levels 이상의 로그만이 표시됩니다.

이제 나머지 플러그인을 적용해봅시다. 아래 링크를 참고하여 Gradle에 Flipper를 추가합니다.

https://fbflipper.com/docs/getting-started/android-native/

Jetpack Startup Initializer를 사용하고, debug 모드에서만 추가되도록 debug/AndroidManifest.xml을 추가하였습니다.

// build.gradle (:app)
dependencies {
    // ...
    debugImplementation 'com.facebook.flipper:flipper:0.154.0'
    debugImplementation 'com.facebook.soloader:soloader:0.10.4'
    releaseImplementation 'com.facebook.flipper:flipper-noop:0.154.0'
    releaseImplementation 'com.github.theGlenn:flipper-android-no-op:0.9.0'
}

// settings.gradle
dependencyResolutionManagement {
    // ...
    repositories {
        // ...
        maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application tools:ignore="MissingApplicationIcon">

        <activity
            android:name="com.facebook.flipper.android.diagnostics.FlipperDiagnosticActivity"
            android:exported="true"
            android:permission="android.permission.INTERNET, android.permission.ACCESS_WIFI_STATE" />

        <provider
            android:name="androidx.startup.InitializationProvider"
            android:authorities="${applicationId}.androidx-startup"
            android:exported="false"
            tools:node="merge">
            <meta-data
                android:name="com.example.sample.app.FlipperInitializer"
                android:value="androidx.startup" />
        </provider>
    </application>
</manifest>
package com.example.sample.app

import androidx.startup.Initializer
import com.facebook.flipper.android.AndroidFlipperClient
import com.facebook.flipper.android.utils.FlipperUtils
import com.facebook.flipper.core.FlipperClient
import com.facebook.flipper.core.FlipperPlugin
import com.facebook.flipper.plugins.inspector.DescriptorMapping
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin
import com.facebook.soloader.SoLoader

class FlipperInitializer : Initializer<Unit> {

    override fun create(context: android.content.Context) {
        if (!FlipperUtils.shouldEnableFlipper(context)) {
            return
        }
        SoLoader.init(context, false)
        AndroidFlipperClient.getInstance(context).addPlugins(
            InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()),
        ).start()
    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }

    private fun FlipperClient.addPlugins(vararg flipperPlugins: FlipperPlugin): FlipperClient {
        flipperPlugins.forEach {
            addPlugin(it)
        }
        return this
    }
}

 

반응형