Бибилиотека для отладки приложений.
Warning
Библиотека находится в стадии разработки.
Changelog | Документация по разработке плагинов | Миграция на новые версии
Тебе надоело каждый раз вручную вбивать логин и пароль тестового пользователя или пересобирать приложение для того чтобы поменять сервер в настройках? Эта библиотека разрабатывается с идеей решить эти и другие проблемы, и сделать процесс отладки приложения более удобным.
В данный момент библиотека предоставляет следующий функционал:
- Добавление, редактирование и выбор юзера.
- Добавление, редактирование и выбор сервера.
- Просмотр и редактирование SharedPreferences.
- Управление Feature toggle на основе Flipper.
- Управление remote config на основе Konfeature.
Библиотека разрабатывается используя подход работы с плагинами, когда каждый функционал подключается отдельным модулем в зависимостях.
Для работы с библиотекой необходимо:
- Подключить Coreмодуль для работы самой панели:
dependencies {
    //core модуль панели
   debugImplementation 'com.redmadrobot.debug:panel-core:${debug_panel_version}'
}- Подключить необходимые плагины
dependencies {
    //Плагин для работы с аккаунтами
    debugImplementation 'com.redmadrobot.debug:plugin-accounts:${debug_panel_version}'
    //Плагин для работы с серверами
    debugImplementation 'com.redmadrobot.debug:plugin-servers:${debug_panel_version}'
    //Плагин для работы с SharedPreferences
    debugImplementation 'com.redmadrobot.debug:plugin-app-settings:${debug_panel_version}'
    //Плагин для работы с Feature Toggle на основе Flipper
    debugImplementation 'com.redmadrobot.debug:plugin-flipper:${debug_panel_version}'
    //Так же необходимо подключить саму библеотеку flipper
    debugImplementation "com.redmadrobot:flipper:${flipper_version}"
    //Плагин для работы с remote config на основе Konfeature
    debugImplementation 'com.redmadrobot.debug:plugin-konfeature:${debug_panel_version}'
    //Так же необходимо подключить саму библиотеку konfeature
    debugImplementation "com.redmadrobot.konfeature:konfeature:${konfeature_version}"
}
- Для того чтобы библиотека не попала в релизную сборку необходимо подключить no-opверсию библиотеки
   releaseImplementation 'com.redmadrobot.debug:panel-no-op:${debug_panel_version}'Общий принцип подключения библиотеки в коде выглядит так:
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        
      DebugPanel.initialize(
            application = this,
            config = DebugPanelConfig(shakerMode = false),
            plugins = listOf(
                AccountsPlugin(/*arguments*/),
                ServersPlugin(/*arguments*/),
                AppSettingsPlugin(/*arguments*/),
                FlipperPlugin(/*arguments*/),
                KonfeaturePlugin(/*arguments*/),
            )
        )
    }
}Для того чтобы открыть DebugPanel, нужно вызвать в коде:
fun openDebugPanel() {
    DebugPanel.showPanel(supportFragmentManager)
}Так же в панель можно войти через уведомление которое появляется при запуске приложения использующее библиотеку. Через это же уведомление можно перейти в ручную настройку панели. Для этого нужно нажать кнопку SETTINGS в раскрытом уведомлении.
Для дополнительной конфигурации DebugPanel, нужно добавить свою версию DebugPanelConfig класса при инициализации панели.
   DebugPanel.initialize(
            application = this,
            config = DebugPanelConfig(),
            plugins = listOf(/*plugins*/)
)shakerMode: Boolean - Открытие DebugPanel при встряхивании устройства.
Используется для работы тестовыми аккаунтами.
Можно задать список предустановленных аккаунтов
AccountsPlugin(
    preInstalledAccounts = listOf(
        DebugAccount(
            login = "user_login",
            password = "user_password",
            pin = "pin" //необязательное поле
        )
    )
)Чтобы реагировать на смену пользователя вы можете подписаться на события DebugPanel внутри любого LifecycleOwner
DebugPanel.subscribeToEvents(lifecycleOwner = this) { event ->
    when (event) {
        is AccountSelectedEvent -> {
            val account = event.debugAccount
          //Реализация перелогина
        }
    }
}Так же вы можете использовать интерфейс DebugAuthenticator чтобы реализовать логику перелогина в отдельном классе который можно передать в плагин.
class UserAuthenticator : DebugAuthenticator {
    override fun onAccountSelected(account: DebugAccount) {
         //Реализация перелогина
    }
}AccountsPlugin(
    preInstalledAccounts = listOf(),
    debugAuthenticator = UserAuthenticator()
)Метод onAccountSelected будет вызываться при каждом выборе аккаунта
Используется для работы с тестовыми серверами
Можно задать список предустановленных серверов
ServersPlugin(
    preInstalledServers = listOf(
        DebugServer(
            name = "server_name",
            url = "https://debug_server.com",
            isDefault = true /*!!!Обязательно должен быть указан хотя бы один сервер по умолчанию*/
        )
    )
)И подписаться на событие смены сервера
DebugPanel.subscribeToEvents(lifecycleOwner = this) { event ->
    when (event) {
        is ServerSelectedEvent -> {
            val debugServer = event.debugServer
            // логика переключения сервера
        }
    }
}Для получения выбранного сервера или default сервера из кода:
   val selectedServer = ServersPlugin.getSelectedServer()
   val defaultServer = ServersPlugin.getDefaultServer()Так же если вы используете OkHttp в своем сетевом стеке то можете использовать DebugServerInterceptor который будет автоматически подменять хост в запросах на выбранный вами.
OkHttpClient.Builder()
    .addInterceptor(DebugServerInterceptor())
    .build()Если запросы должны еще как то модифицироваться, например добавляться Header'ы то это можно сделать используя метод modifyRequest
OkHttpClient.Builder()
   .addInterceptor(
       DebugServerInterceptor().modifyRequest { request, server ->
           if (server.name == "Test") {
               request.newBuilder()
                   .addHeader("Authorization", "testToken")
                   .build()
           } else {
               request
           }
       }
   )
   .build()Текущий выбранный сервер можно получить следующим образом
val selectedServer = getPlugin<ServersPlugin>().getSelectedServer()Используется для просмотра и редактирования SharedPreferences в проекте
Для подключения плагина, необходимо передать в него список SharedPreferences с которыми хотите работать:
 AppSettingsPlugin(
     sharedPreferences = listOf(
         primarySharedPreferences,
         secondarySharedPreferences
     )
 )Используется для просмотра и редактирования Flipper feature toggle'ов в проекте
Для подключения плагина, необходимо передать в него map id поддерживаемых фичей и их значений
FlipperPlugin(
   featureStateMap = mapOf(
      "Toggle Id" to FlipperValue()
   )
)Для изменения значений в рамках проекта необходимо использовать метод FlipperPlugin.observeChangedToggles():
FlipperPlugin
   .observeChangedToggles()         // Пришлёт map размером = [0, yourFeatures.size]
   .onEach { changedToggles ->      // Первый раз пришлёт сохранённые значения
      this.yourDebugPanelChangedToggles = changedToggles
   }
   .flowOn(Dispatchers.Main)
   .launchIn(debugScope)В FlipperConfig должно быть что-то наподобие
override fun getValue(feature: Feature): FlipperValue {
   return yourDebugPanelChangedToggles[feature.id]
      ?: localConfig[feature.id]
      ?: FlipperValue.BooleanValue(false)
}В основе плагина лежит библиотека Konfeature, которая позволяет:
- отображать конфигурации feature, которые используются в konfeature
- видеть источник каждого элемента конфигурации (Default, Firebase, AppGallery и т.д.)
- переопределять значение элементов конфигурации с типом Boolean, String, Long, Double
Для подключения плагина, необходимо передать в него объект класса KonfeatureDebugPanelInterceptor и Konfeature
val debugPanelInterceptor = KonfeatureDebugPanelInterceptor(context)
val konfeatureInstance = konfeature {
    if (isDebug) {
        addIntercepot(debugPanelInterceptor)
    }
}
KonfeaturePlugin(
    debugPanelInterceptor = debugPanelInterceptor,
    konfeature = konfeatureInstance,
)В builder konfeture можно настроить следующее:
- добавить config конкретной фичи - register(FeatureConfigN())
- настроить работу с remote config через реализацию интерфейса FeatureSource-addSource(featureSource)
- настроить логирование - setLogger(logger)
Для того чтобы тестовые данные не попали в релизные сборки рекомендуется не задавать их явно в Application классе, а использовать реализации DebugDataProvider, которые можно разнести по разным buildType. Для release версии следует сделать пустую реализацию.
buildType  debug
class DebugServersProvider : DebugDataProvider<List<DebugServer>> {
   
    override fun provideData(): List<DebugServer> {
        return listOf(
            DebugServer(name = "debug 1", url = "https://testserver1.com")
        )
    }
}buildType  release
class DebugServersProvider : DebugDataProvider<List<DebugServer>> {
    override fun provideData(): List<DebugServer> {
        return emptyList()
    }
}Добавление в плагин
ServersPlugin(
    preInstalledServers = DebugServersProvider()
)