Skip to main content

Integration Example

This page describes a short example of integrating an Android DXcharts library into an application. For the full algorithm for connecting the DXcharts library, please check Quick Start page

Add dependencies​

First step is to add dependencies into your build.gradle file

plugins {
//...
id 'org.jetbrains.kotlin.android' version '2.2.10' apply false
id 'org.jetbrains.kotlin.plugin.compose' version '2.2.10' apply false
}

android {
//...
buildFeatures {
compose true
}
//...
}

dependencies {
//Compose dependencies
def composeBom = platform('androidx.compose:compose-bom:$COMPOSE_BOM_VERSION')
implementation composeBom
androidTestImplementation composeBom
implementation 'androidx.compose.foundation:foundation'
implementation 'androidx.compose.ui:ui'
implementation 'androidx.activity:activity-compose:$ACTIVITY_COMPOSE_VERSION'
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0'
implementation 'androidx.constraintlayout:constraintlayout-compose:1.1.0'
implementation 'androidx.compose.material3:material3'

//Additional dependencies that used in the library
implementation 'com.google.code.gson:gson:2.10.1' // For JSON parsing
implementation 'com.jakewharton.threetenabp:threetenabp:1.4.7' // For date and time API

//Required DxCharts dependencies
implementation 'com.devexperts.dxcharts.lib:dxcharts_lib:$MAIN_LIB_VERSION'
implementation 'com.devexperts.dxcharts.provider:dxcharts_data_providers:$'DATA_PROVIDER_VERSION'

//Not necessary dependencies. Default implementations of data providers with DxFeed API
implementation 'com.devexperts.dxcharts.provider.candles:dxcharts_dxfeed_candles_provider:$CANDLES_PROVIDER_VERSION'
implementation 'com.devexperts.dxcharts.provider.events:dxcharts_dxfeed_events_provider:$EVENTS_PROVIDER_VERSION'
implementation 'com.devexperts.dxcharts.provider.ipf:dxcharts_dxfeed_ipf_provider:$IPF_PROVIDER_VERSION'
implementation 'com.devexperts.dxcharts.provider.news:dxcharts_dxfeed_news_provider:$NEWS_PROVIDER_VERSION'
implementation 'com.devexperts.dxcharts.provider.studies:dxcharts_studies_provider:$STUDIES_PROVIDER_VERSION'
}

DxCharts configuration​

Next step will be creating DxCharts view.

class DXChartsActivity : AppCompatActivity() {
/**
* Creating providers objects.
* In this example we use our default providers implementations, but you can create your own.
* Notice that default implementations based on the DxFeed API and require endpointAddress, url and token.
*/
private val quotesProvider = DxFeedQuotesProvider(
endpointAddress = "ENDPOINT_ADDRESS"
)
private val candlesProvider = DxFeedCandlesProvider(
endpointAddress = "ENDPOINT_ADDRESS"
)
private val newsProvider = DxFeedNewsProvider(
url = "NEWS_URL",
token = "Basic " + String(Base64.encode("NEWS_TOKEN".encodeToByteArray(),Base64.NO_WRAP))
)
private val dxFeedIpfProvider = DxFeedHttpIpfProvider(
url = "IPF_URL",
token = "Basic " + String(Base64.encode("IPF_TOKEN".encodeToByteArray(),Base64.NO_WRAP))
)
private val eventsProvider = DxFeedEventsProvider(
url = "EVENTS_URL",
token = "Basic " + String(Base64.encode("EVENTS_TOKEN".encodeToByteArray(), Base64.NO_WRAP))
)
private val studiesProvider = DxStudiesDataProviderImplementation()
private val studiesPreviewProvider = DxStudiesPreviewDataProviderImplementation()
private val scheduleProvider = DxFeedHttpScheduleProvider(
token = "Basic " + String(
Base64.encode(
BuildConfig.IPF_TOKEN.encodeToByteArray(),
Base64.NO_WRAP
)
)
)
/**
* Creating repositories objects.
* Library provides 2 default variants of implementations of repositories.
* 1. SerializableStorage repositories. They implement saving their inner state into shared preferences. To restore their state you need to use deserialize() method.
* 2. LocalStorage repositories. They don't save any state across instances of chart and don't need context as a parameter.
* Also you can create your own implementations of repositories.
*/
private val studiesRepository by lazy {
/**
* StudiesRepository needs indicator items to be passed. Default studies list can be obtained by using StudiesLoader().load(assets).
*/
SerializableStorageDefaultStudiesRepository(application, StudiesLoader().load(assets))
}
private val aggregationsRepository by lazy {
SerializableStorageDefaultAggregationsRepository(application)
}
private val colorsRepository by lazy {
SerializableStorageDefaultColorsRepository(application)
}
private val drawingsLineWidthRepo by lazy {
SerializableStorageDefaultDrawingsLineWidthRepo(application)
}
private val drawingsSnapshotsRepo by lazy {
SerializableStorageDefaultDrawingsSnapshotsRepo(application)
}
private val drawingsFirstClickRepo by lazy {
SerializableStorageDefaultFirstClickRepo(application)
}
private val drawingsTypesRepo by lazy {
SerializableStorageDefaultDrawingsTypesRepo(application)
}
private val highlighterColorsRepository by lazy {
SerializableStorageDefaultHighlighterColorsRepository(application)
}
private val instrumentRepository by lazy {
SerializableStorageDefaultInstrumentRepository(application)
}
private val timeframePresetsRepository by lazy {
SerializableStorageDefaultTimeframePresetsRepository(application)
}
private val ordersRepository by lazy {
SerializableStorageDefaultOrdersRepository(application)
}
private val settingsRepository by lazy {
SerializableStorageDefaultSettingsRepository(application)
}
private val studiesTemplatesRepository by lazy {
SerializableStorageDefaultStudiesTemplatesRepository(application)
}
private var isSystemInDarkTheme: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
/**
* Method that restore state into SerializableStorage repositories.
*/
deserializeRepositories()
/**
* Enables or disables the trading buttons feature. By default it's true.
*/
settingsRepository.setTradingButtonsFeatureEnabled(isEnabled = false)
isSystemInDarkTheme =
resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
/**
* Initializing providers.
*/
quotesProvider.connect()
candlesProvider.connect()
dxFeedIpfProvider.connect()
studiesProvider.connect()
studiesPreviewProvider.connect()
/**
* Handling errors in default repositories.
* Default providers have errorFlow that let you set your own way of handling errors.
* It's optional and can be customized depending on your needs.
*/
lifecycleScope.launch {
merge(
candlesProvider.errorFlow,
quotesProvider.errorFlow,
dxFeedIpfProvider.errorFlow,
eventsProvider.errorFlow,
newsProvider.errorFlow,
studiesProvider.errorFlow,
studiesPreviewProvider.errorFlow
).collect { error ->
// Custom error handling logic
val errorClassName = error?.javaClass?.simpleName
val parentClassName = error?.javaClass?.superclass?.simpleName
Log.e("DxChartsProviderError", "$errorClassName from $parentClassName : $error?.message")
if(error?.error != null){
throw error.error!!
}
}
}
setContent {
/**
* Get initial theme and from settings repository and set according color palette for DxCharts
*/
val initialTheme = getPalette(settingsRepository.getCurrentTheme())
var theme by remember { mutableStateOf(initialTheme) }
/**
* Get initial instrument from settings repository
*/
val initialInstrument = instrumentRepository.getSelectedInstrument()
// Set mainToolbarConfig with necessary buttons in order how it should be shown
val mainToolbarConfig = listOf(
MainToolbarButtonType.InstrumentSearch(),
MainToolbarButtonType.Aggregation(),
MainToolbarButtonType.Studies(),
MainToolbarButtonType.Drawings(),
MainToolbarButtonType.Settings()
)
/**
* Initializing DxChart
*/
DxChartsTheme(
colors = theme
) {
Surface(
modifier = Modifier.fillMaxSize(),
color = DxChartsTheme.colors.mainChartBg
) {
DxChartsScreen(
DxChartsConfig(
/**
* Passing repositories to the DxChartConfig.
* By default all repositories are LocalStorage and don't save their state across instances.
*/
repositories = DxChartsConfig.Repositories(
studiesRepository = studiesRepository,
aggregationsRepository = aggregationsRepository,
colorsRepository = colorsRepository,
drawingsLineWidthRepo = drawingsLineWidthRepo,
drawingsSnapshotsRepo = drawingsSnapshotsRepo,
drawingsFirstClickRepo = drawingsFirstClickRepo,
drawingsTypesRepo = drawingsTypesRepo,
highlighterColorsRepository = highlighterColorsRepository,
instrumentRepository = instrumentRepository,
ordersRepository = ordersRepository,
timeframePresetsRepository = timeframePresetsRepository,
settingsRepository = settingsRepository,
studiesTemplatesRepository = studiesTemplatesRepository
),
/**
* Passing providers to the DxChartConfig.
* By default all providers are null
*/
providers = DxChartsDataProviders(
candlesProvider = candlesProvider,
ipfProvider = dxFeedIpfProvider,
scheduleProvider = scheduleProvider,
quotesProvider = quotesProvider,
eventsProvider = eventsProvider,
newsProvider = newsProvider,
studiesDataProvider = studiesProvider,
studiesDataPreviewProvider = studiesPreviewProvider
),
/**
* Set initial instrument that will be used if there are no saved instruments in the instrument repository.
*/
initialInstrument = instrument
),
/**
* Callback for click on Buy button.
*/
buyClicked = {},
/**
* Callback for click on Sell button.
*/
sellClicked = {},
/**
* Callback for changing theme in the DxCharts settings.
*/
themeChanged = { theme = getPalette(it) },
/**
* Setting your logo.
* By default it's null.
*/
logo = Logo(
image = R.drawable.devexperts_logo,
position = Logo.LogoPosition.BOTTOM_LEFT,
),
/**
* Whether to show toolbar or not.
*/
mainToolbarConfig = mainToolbarConfig
)
}
}
}
}
/**
* Disconnecting default providers.
*/
override fun onDestroy() {
if (!isChangingConfigurations) {
newsProvider.disconnect()
dxFeedIpfProvider.disconnect()
quotesProvider.disconnect()
candlesProvider.disconnect()
eventsProvider.disconnect()
studiesProvider.disconnect()
studiesPreviewProvider.disconnect()
}
}
/**
* Function that checks what color palette to use.
*/
private fun getPalette(theme: Theme): DxChartsColors {
return when (theme) {
Theme.AUTO -> {
if (isSystemInDarkTheme) darkPalette() else lightPalette()
}
Theme.LIGHT -> {
lightPalette()
}
Theme.DARK -> {
darkPalette()
}
}
}
/**
* Function that responsible for restoring state of SerializableStorage repositories.
*/
private fun deserializeRepositories() {
val prefs = application.getSharedPreferences("dxcharts_demo_app", MODE_PRIVATE)
val aggregations = prefs.getString("aggregations_repo", null)
val colors = prefs.getString("colors_repo", null)
val drawingsLine = prefs.getString("drawings_line_repo", null)
val drawingsSnapshots = prefs.getString("drawings_snapshots_repo", null)
val drawingsTypes = prefs.getString("drawings_types_repo", null)
val drawingsFirstClick = prefs.getString("drawings_first_click_repo", null)
val highlighter = prefs.getString("highlighter_repo", null)
val instrument = prefs.getString("instrument_repo", null)
val orders = prefs.getString("orders_repo", null)
val settings = prefs.getString("settings_repo", null)
val studies = prefs.getString("studies_repo", null)
val studiesTemplates = prefs.getString("studies_templates_repo", null)
val timeframePresets = prefs.getString("timeframe_presets_repo", null)
aggregations?.let {
aggregationsRepository.deserialize(it)
}
colors?.let {
colorsRepository.deserialize(it)
}
drawingsLine?.let {
drawingsLineWidthRepo.deserialize(it)
}
drawingsSnapshots?.let {
drawingsSnapshotsRepo.deserialize(it)
}
drawingsTypes?.let {
drawingsTypesRepo.deserialize(it)
}
drawingsFirstClick?.let {
drawingsFirstClickRepo.deserialize(it)
}
highlighter?.let {
highlighterColorsRepository.deserialize(it)
}
instrument?.let {
instrumentRepository.deserialize(it)
}
orders?.let {
ordersRepository.deserialize(it)
}
settings?.let {
settingsRepository.deserialize(it)
}
studies?.let {
studiesRepository.deserialize(it)
}
studiesTemplates?.let {
studiesTemplatesRepository.deserialize(it)
}
timeframePresets?.let {
timeframePresetsRepository.deserialize(it)
}
}
}