[{"data":1,"prerenderedAt":7501},["ShallowReactive",2],{"navigation_docs":3,"-sdks-mobile-android":244,"-sdks-mobile-android-surround":7496},[4,51,78,229],{"title":5,"icon":6,"modifiedAt":7,"path":8,"stem":9,"children":10,"page":6},"Getting Started",false,"2026-04-30T19:15:33.000Z","\u002Fgetting-started","1.getting-started",[11,16,21,26,31,36,41,46],{"title":12,"path":13,"stem":14,"icon":15},"Quickstart","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F1.quickstart","i-lucide-fast-forward",{"title":17,"path":18,"stem":19,"icon":20},"Core Concepts","\u002Fgetting-started\u002Fcore-concepts","1.getting-started\u002F2.core-concepts","i-lucide-workflow",{"title":22,"path":23,"stem":24,"icon":25},"Configs Anatomy","\u002Fgetting-started\u002Fconfigs","1.getting-started\u002F3.configs","i-lucide-file-cog",{"title":27,"path":28,"stem":29,"icon":30},"Architecture","\u002Fgetting-started\u002Farchitecture","1.getting-started\u002F4.architecture","i-lucide-layers",{"title":32,"path":33,"stem":34,"icon":35},"JSON Schema Validation","\u002Fgetting-started\u002Fjson-schema-validation","1.getting-started\u002F5.json-schema-validation","i-lucide-braces",{"title":37,"path":38,"stem":39,"icon":40},"Testing Rules","\u002Fgetting-started\u002Ftesting-targeting-rules","1.getting-started\u002F6.testing-targeting-rules","i-lucide-flask-conical",{"title":42,"path":43,"stem":44,"icon":45},"Segments","\u002Fgetting-started\u002Fsegments","1.getting-started\u002F7.segments","i-lucide-squares-intersect",{"title":47,"path":48,"stem":49,"icon":50},"Pricing & Billing","\u002Fgetting-started\u002Fpricing-and-billing","1.getting-started\u002F8.pricing-and-billing","i-lucide-credit-card",{"title":52,"modifiedAt":53,"defaultOpen":54,"path":55,"stem":56,"children":57,"page":6},"Monitoring","2026-09-24T23:33:20.000Z",true,"\u002Fmonitoring","2.monitoring",[58,63,68,73],{"title":59,"path":60,"stem":61,"icon":62},"Activity","\u002Fmonitoring\u002Factivity","2.monitoring\u002F1.activity","i-lucide-activity",{"title":64,"path":65,"stem":66,"icon":67},"Lifecycle","\u002Fmonitoring\u002Flifecycle","2.monitoring\u002F2.lifecycle","i-lucide-recycle",{"title":69,"path":70,"stem":71,"icon":72},"Alerts","\u002Fmonitoring\u002Falerts","2.monitoring\u002F3.alerts","i-lucide-bell",{"title":74,"path":75,"stem":76,"icon":77},"Dynamic Detection","\u002Fmonitoring\u002Fdynamic-detection","2.monitoring\u002F4.dynamic-detection","i-lucide-hat-glasses",{"title":79,"modifiedAt":53,"defaultOpen":54,"path":80,"stem":81,"children":82,"page":6},"SDKs","\u002Fsdks","3.sdks",[83,88,109,134,150,181,224],{"title":84,"path":85,"stem":86,"icon":87},"Available SDKs","\u002Fsdks\u002Favailable-sdks","3.sdks\u002F1.available-sdks","i-lucide-list",{"title":89,"modifiedAt":53,"icon":90,"defaultOpen":6,"path":91,"stem":92,"children":93,"page":6},"Browser SDKs","i-lucide-monitor","\u002Fsdks\u002Fbrowser","3.sdks\u002F2.browser",[94,99,104],{"title":95,"path":96,"stem":97,"icon":98},"Javascript","\u002Fsdks\u002Fbrowser\u002Fjavascript","3.sdks\u002F2.browser\u002F1.javascript","cd-logos-javascript",{"title":100,"path":101,"stem":102,"icon":103},"React","\u002Fsdks\u002Fbrowser\u002Freact","3.sdks\u002F2.browser\u002F2.react","cd-logos-react-light",{"title":105,"path":106,"stem":107,"icon":108},"Vue","\u002Fsdks\u002Fbrowser\u002Fvue","3.sdks\u002F2.browser\u002F3.vue","cd-logos-vue",{"title":110,"modifiedAt":53,"icon":111,"defaultOpen":6,"path":112,"stem":113,"children":114,"page":6},"Mobile SDKs","i-lucide-smartphone","\u002Fsdks\u002Fmobile","3.sdks\u002F3.mobile",[115,119,124,129],{"title":116,"path":117,"stem":118,"icon":103},"React Native","\u002Fsdks\u002Fmobile\u002Freact-native","3.sdks\u002F3.mobile\u002F1.react-native",{"title":120,"path":121,"stem":122,"icon":123},"Flutter","\u002Fsdks\u002Fmobile\u002Fflutter","3.sdks\u002F3.mobile\u002F2.flutter","cd-logos-flutter",{"title":125,"path":126,"stem":127,"icon":128},"Swift","\u002Fsdks\u002Fmobile\u002Fswift","3.sdks\u002F3.mobile\u002F3.swift","cd-logos-swift",{"title":130,"path":131,"stem":132,"icon":133},"Android","\u002Fsdks\u002Fmobile\u002Fandroid","3.sdks\u002F3.mobile\u002F4.android","cd-logos-android",{"title":135,"modifiedAt":53,"icon":136,"defaultOpen":6,"path":137,"stem":138,"children":139,"page":6},"Meta-framework SDKs","i-lucide-monitor-smartphone","\u002Fsdks\u002Fmeta","3.sdks\u002F4.meta",[140,145],{"title":141,"path":142,"stem":143,"icon":144},"Next.js","\u002Fsdks\u002Fmeta\u002Fnextjs","3.sdks\u002F4.meta\u002F1.nextjs","cd-logos-nextjs",{"title":146,"path":147,"stem":148,"icon":149},"Nuxt","\u002Fsdks\u002Fmeta\u002Fnuxt","3.sdks\u002F4.meta\u002F2.nuxt","cd-logos-nuxt",{"title":151,"modifiedAt":53,"icon":152,"defaultOpen":6,"path":153,"stem":154,"children":155,"page":6},"Server SDKs","i-lucide-server","\u002Fsdks\u002Fserver","3.sdks\u002F5.server",[156,161,166,171,176],{"title":157,"path":158,"stem":159,"icon":160},"Node.js","\u002Fsdks\u002Fserver\u002Fnode-js","3.sdks\u002F5.server\u002F1.node-js","cd-logos-nodejs",{"title":162,"path":163,"stem":164,"icon":165},"Python","\u002Fsdks\u002Fserver\u002Fpython","3.sdks\u002F5.server\u002F2.python","cd-logos-python",{"title":167,"path":168,"stem":169,"icon":170},"Java","\u002Fsdks\u002Fserver\u002Fjava","3.sdks\u002F5.server\u002F3.java","cd-logos-java",{"title":172,"path":173,"stem":174,"icon":175},".NET","\u002Fsdks\u002Fserver\u002Fdotnet","3.sdks\u002F5.server\u002F4.dotnet","cd-logos-dotnet",{"title":177,"path":178,"stem":179,"icon":180},"Go","\u002Fsdks\u002Fserver\u002Fgo","3.sdks\u002F5.server\u002F5.go","cd-logos-go",{"title":182,"modifiedAt":53,"icon":183,"defaultOpen":6,"path":184,"stem":185,"children":186,"page":6},"OpenFeature Providers","cd-logos-openfeature","\u002Fsdks\u002Fopenfeature","3.sdks\u002F6.openfeature",[187,192,196,200,204,208,212,216,220],{"title":188,"path":189,"stem":190,"icon":183,"icons":191},"Web","\u002Fsdks\u002Fopenfeature\u002Fweb","3.sdks\u002F6.openfeature\u002F1.web",[183,98],{"title":125,"path":193,"stem":194,"icon":183,"icons":195},"\u002Fsdks\u002Fopenfeature\u002Fswift","3.sdks\u002F6.openfeature\u002F2.swift",[183,128],{"title":130,"path":197,"stem":198,"icon":183,"icons":199},"\u002Fsdks\u002Fopenfeature\u002Fandroid","3.sdks\u002F6.openfeature\u002F3.android",[183,133],{"title":120,"path":201,"stem":202,"icon":183,"icons":203},"\u002Fsdks\u002Fopenfeature\u002Fflutter","3.sdks\u002F6.openfeature\u002F4.flutter",[183,123],{"title":157,"path":205,"stem":206,"icon":183,"icons":207},"\u002Fsdks\u002Fopenfeature\u002Fnode-js","3.sdks\u002F6.openfeature\u002F5.node-js",[183,160],{"title":162,"path":209,"stem":210,"icon":183,"icons":211},"\u002Fsdks\u002Fopenfeature\u002Fpython","3.sdks\u002F6.openfeature\u002F6.python",[183,165],{"title":167,"path":213,"stem":214,"icon":183,"icons":215},"\u002Fsdks\u002Fopenfeature\u002Fjava","3.sdks\u002F6.openfeature\u002F7.java",[183,170],{"title":172,"path":217,"stem":218,"icon":183,"icons":219},"\u002Fsdks\u002Fopenfeature\u002Fdotnet","3.sdks\u002F6.openfeature\u002F8.dotnet",[183,175],{"title":177,"path":221,"stem":222,"icon":183,"icons":223},"\u002Fsdks\u002Fopenfeature\u002Fgo","3.sdks\u002F6.openfeature\u002F9.go",[183,180],{"title":225,"path":226,"stem":227,"icon":228},"Maven Repository","\u002Fsdks\u002Fmaven-repository","3.sdks\u002F7.maven-repository","i-lucide-package",{"title":230,"modifiedAt":53,"defaultOpen":54,"path":231,"stem":232,"children":233,"page":6},"Integrations","\u002Fintegrations","4.integrations",[234,239],{"title":235,"path":236,"stem":237,"icon":238},"Terraform","\u002Fintegrations\u002Fterraform","4.integrations\u002F1.terraform","cd-logos-terraform",{"title":240,"path":241,"stem":242,"icon":243},"MCP","\u002Fintegrations\u002Fmcp","4.integrations\u002F2.mcp","cd-logos-mcp",{"id":245,"title":246,"body":247,"description":7488,"extension":7489,"links":7490,"meta":7491,"navigation":7493,"path":131,"seo":7494,"stem":132,"__hash__":7495},"docs\u002F3.sdks\u002F3.mobile\u002F4.android.md","Android SDK",{"type":248,"value":249,"toc":7458},"minimark",[250,254,259,264,268,280,351,358,361,365,389,669,672,908,915,919,933,1159,1162,1174,1178,1191,1198,1690,1705,1715,1720,1735,1741,1747,1758,1918,1923,1940,1943,2064,2081,2084,2406,2411,2417,2552,2764,2770,2774,2796,3214,3217,3304,3314,3422,3508,3516,3520,3546,3578,3972,3975,4063,4072,4076,4098,4355,4359,4365,4372,4498,4504,4670,4679,4686,4690,4693,4879,4883,4886,5219,5225,5558,5568,5585,5715,5729,5733,5736,5740,5755,5760,5787,5793,5822,5829,5847,5855,5868,5872,5875,5878,5882,5897,5907,5992,6180,6194,6201,6486,6490,6509,6586,6611,6615,6628,6937,6940,7003,7066,7070,7232,7247,7364,7368,7395,7399,7454],[251,252],"div",{"hidden":54,"dataTitleIcon":253},"android",[255,256],"external-badges",{"package-url":226,"registry":257,"repo":258},"maven","android-sdk",[260,261,263],"h2",{"id":262},"introduction","Introduction",[265,266,267],"p",{},"The Android SDK is intended to be used by Android applications. It evaluates your configs against a user context, keeps them current as they change in the dashboard, and hands your UI values it can re-render from.",[265,269,270,271,275,276,279],{},"It is written in Kotlin and is meant to be used from Kotlin and Java alike. Every API has a form that works without coroutines, and the Kotlin conveniences — ",[272,273,274],"code",{},"suspend"," functions, ",[272,277,278],{},"Flow",", and typed extensions — sit on top of it. It ships as three artifacts:",[281,282,283,302],"table",{},[284,285,286],"thead",{},[287,288,289,293,296,299],"tr",{},[290,291,292],"th",{},"Artifact",[290,294,295],{},"Contents",[290,297,298],{},"Minimum SDK",[290,300,301],{},"Java bytecode",[303,304,305,322,337],"tbody",{},[287,306,307,313,316,319],{},[308,309,310],"td",{},[272,311,312],{},"com.configdirector:android-sdk",[308,314,315],{},"The SDK",[308,317,318],{},"21",[308,320,321],{},"8",[287,323,324,329,332,334],{},[308,325,326],{},[272,327,328],{},"com.configdirector:android-sdk-compose",[308,330,331],{},"Optional Jetpack Compose bindings",[308,333,318],{},[308,335,336],{},"11",[287,338,339,344,347,349],{},[308,340,341],{},[272,342,343],{},"com.configdirector:android-sdk-testing",[308,345,346],{},"Tools for testing the code that reads your configs",[308,348,318],{},[308,350,321],{},[265,352,353,354,357],{},"The Compose artifact depends only on the Compose runtime, so it does not pull ",[272,355,356],{},"compose-ui"," or Material into an application that does not already have them.",[265,359,360],{},"Config evaluation is synchronous and reads config state the client already holds in memory, which is what makes it safe to call from a composable or from a view binding. Telemetry about those evaluations is aggregated and reported on its own coroutine, so evaluating a config never waits on the network.",[260,362,364],{"id":363},"installation","Installation",[265,366,367,368,372,373,376,377,380,381,384,385,388],{},"The SDK is published to the ",[369,370,371],"a",{"href":226},"ConfigDirector Maven repository",". Add the repository to ",[272,374,375],{},"settings.gradle.kts"," or ",[272,378,379],{},"settings.gradle",", next to ",[272,382,383],{},"google()"," and ",[272,386,387],{},"mavenCentral()",":",[390,391,392,553],"code-group",{},[393,394,399],"pre",{"className":395,"code":396,"filename":375,"language":397,"meta":398,"style":398},"language-kotlin shiki shiki-themes material-theme-lighter github-light github-dark","dependencyResolutionManagement {\n    repositories {\n        google()\n        mavenCentral()\n        exclusiveContent {\n            forRepository {\n                maven {\n                    name = \"ConfigDirector\"\n                    url = uri(\"https:\u002F\u002Fmaven.configdirector.com\")\n                }\n            }\n            filter {\n                includeGroup(\"com.configdirector\")\n            }\n        }\n    }\n}\n","kotlin","",[272,400,401,414,422,431,439,447,455,463,477,497,503,509,517,530,535,541,547],{"__ignoreMap":398},[402,403,406,410],"span",{"class":404,"line":405},"line",1,[402,407,409],{"class":408},"sGLFI","dependencyResolutionManagement",[402,411,413],{"class":412},"su5hD"," {\n",[402,415,417,420],{"class":404,"line":416},2,[402,418,419],{"class":408},"    repositories",[402,421,413],{"class":412},[402,423,425,428],{"class":404,"line":424},3,[402,426,427],{"class":408},"        google",[402,429,430],{"class":412},"()\n",[402,432,434,437],{"class":404,"line":433},4,[402,435,436],{"class":408},"        mavenCentral",[402,438,430],{"class":412},[402,440,442,445],{"class":404,"line":441},5,[402,443,444],{"class":408},"        exclusiveContent",[402,446,413],{"class":412},[402,448,450,453],{"class":404,"line":449},6,[402,451,452],{"class":408},"            forRepository",[402,454,413],{"class":412},[402,456,458,461],{"class":404,"line":457},7,[402,459,460],{"class":408},"                maven",[402,462,413],{"class":412},[402,464,466,469,473],{"class":404,"line":465},8,[402,467,468],{"class":412},"                    name ",[402,470,472],{"class":471},"smGrS","=",[402,474,476],{"class":475},"s_sjI"," \"ConfigDirector\"\n",[402,478,480,483,485,488,491,494],{"class":404,"line":479},9,[402,481,482],{"class":412},"                    url ",[402,484,472],{"class":471},[402,486,487],{"class":408}," uri",[402,489,490],{"class":412},"(",[402,492,493],{"class":475},"\"https:\u002F\u002Fmaven.configdirector.com\"",[402,495,496],{"class":412},")\n",[402,498,500],{"class":404,"line":499},10,[402,501,502],{"class":412},"                }\n",[402,504,506],{"class":404,"line":505},11,[402,507,508],{"class":412},"            }\n",[402,510,512,515],{"class":404,"line":511},12,[402,513,514],{"class":408},"            filter",[402,516,413],{"class":412},[402,518,520,523,525,528],{"class":404,"line":519},13,[402,521,522],{"class":408},"                includeGroup",[402,524,490],{"class":412},[402,526,527],{"class":475},"\"com.configdirector\"",[402,529,496],{"class":412},[402,531,533],{"class":404,"line":532},14,[402,534,508],{"class":412},[402,536,538],{"class":404,"line":537},15,[402,539,540],{"class":412},"        }\n",[402,542,544],{"class":404,"line":543},16,[402,545,546],{"class":412},"    }\n",[402,548,550],{"class":404,"line":549},17,[402,551,552],{"class":412},"}\n",[393,554,558],{"className":555,"code":556,"filename":379,"language":557,"meta":398,"style":398},"language-groovy shiki shiki-themes material-theme-lighter github-light github-dark","dependencyResolutionManagement {\n    repositories {\n        google()\n        mavenCentral()\n        exclusiveContent {\n            forRepository {\n                maven {\n                    name = 'ConfigDirector'\n                    url = 'https:\u002F\u002Fmaven.configdirector.com'\n                }\n            }\n            filter {\n                includeGroup 'com.configdirector'\n            }\n        }\n    }\n}\n","groovy",[272,559,560,565,570,577,583,588,593,598,614,627,631,635,640,653,657,661,665],{"__ignoreMap":398},[402,561,562],{"class":404,"line":405},[402,563,564],{"class":412},"dependencyResolutionManagement {\n",[402,566,567],{"class":404,"line":416},[402,568,569],{"class":412},"    repositories {\n",[402,571,572,574],{"class":404,"line":424},[402,573,427],{"class":412},[402,575,430],{"class":576},"sP7_E",[402,578,579,581],{"class":404,"line":433},[402,580,436],{"class":412},[402,582,430],{"class":576},[402,584,585],{"class":404,"line":441},[402,586,587],{"class":412},"        exclusiveContent {\n",[402,589,590],{"class":404,"line":449},[402,591,592],{"class":412},"            forRepository {\n",[402,594,595],{"class":404,"line":457},[402,596,597],{"class":412},"                maven {\n",[402,599,600,602,604,608,611],{"class":404,"line":465},[402,601,468],{"class":412},[402,603,472],{"class":471},[402,605,607],{"class":606},"sjJ54"," '",[402,609,610],{"class":475},"ConfigDirector",[402,612,613],{"class":606},"'\n",[402,615,616,618,620,622,625],{"class":404,"line":479},[402,617,482],{"class":412},[402,619,472],{"class":471},[402,621,607],{"class":606},[402,623,624],{"class":475},"https:\u002F\u002Fmaven.configdirector.com",[402,626,613],{"class":606},[402,628,629],{"class":404,"line":499},[402,630,502],{"class":412},[402,632,633],{"class":404,"line":505},[402,634,508],{"class":412},[402,636,637],{"class":404,"line":511},[402,638,639],{"class":412},"            filter {\n",[402,641,642,645,648,651],{"class":404,"line":519},[402,643,644],{"class":412},"                includeGroup ",[402,646,647],{"class":606},"'",[402,649,650],{"class":475},"com.configdirector",[402,652,613],{"class":606},[402,654,655],{"class":404,"line":532},[402,656,508],{"class":412},[402,658,659],{"class":404,"line":537},[402,660,540],{"class":412},[402,662,663],{"class":404,"line":543},[402,664,546],{"class":412},[402,666,667],{"class":404,"line":549},[402,668,552],{"class":412},[265,670,671],{},"Then add the dependencies to your app module:",[390,673,674,725,771],{},[393,675,678],{"className":395,"code":676,"filename":677,"language":397,"meta":398,"style":398},"dependencies {\n    implementation(\"com.configdirector:android-sdk:1.7.1\")\n\n    \u002F\u002F Optional, for Jetpack Compose applications\n    implementation(\"com.configdirector:android-sdk-compose:1.7.1\")\n}\n","build.gradle.kts",[272,679,680,687,699,704,710,721],{"__ignoreMap":398},[402,681,682,685],{"class":404,"line":405},[402,683,684],{"class":408},"dependencies",[402,686,413],{"class":412},[402,688,689,692,694,697],{"class":404,"line":416},[402,690,691],{"class":408},"    implementation",[402,693,490],{"class":412},[402,695,696],{"class":475},"\"com.configdirector:android-sdk:1.7.1\"",[402,698,496],{"class":412},[402,700,701],{"class":404,"line":424},[402,702,703],{"emptyLinePlaceholder":54},"\n",[402,705,706],{"class":404,"line":433},[402,707,709],{"class":708},"sutJx","    \u002F\u002F Optional, for Jetpack Compose applications\n",[402,711,712,714,716,719],{"class":404,"line":441},[402,713,691],{"class":408},[402,715,490],{"class":412},[402,717,718],{"class":475},"\"com.configdirector:android-sdk-compose:1.7.1\"",[402,720,496],{"class":412},[402,722,723],{"class":404,"line":449},[402,724,552],{"class":412},[393,726,729],{"className":555,"code":727,"filename":728,"language":557,"meta":398,"style":398},"dependencies {\n    implementation 'com.configdirector:android-sdk:1.7.1'\n\n    \u002F\u002F Optional, for Jetpack Compose applications\n    implementation 'com.configdirector:android-sdk-compose:1.7.1'\n}\n","build.gradle",[272,730,731,736,748,752,756,767],{"__ignoreMap":398},[402,732,733],{"class":404,"line":405},[402,734,735],{"class":412},"dependencies {\n",[402,737,738,741,743,746],{"class":404,"line":416},[402,739,740],{"class":412},"    implementation ",[402,742,647],{"class":606},[402,744,745],{"class":475},"com.configdirector:android-sdk:1.7.1",[402,747,613],{"class":606},[402,749,750],{"class":404,"line":424},[402,751,703],{"emptyLinePlaceholder":54},[402,753,754],{"class":404,"line":433},[402,755,709],{"class":708},[402,757,758,760,762,765],{"class":404,"line":441},[402,759,740],{"class":412},[402,761,647],{"class":606},[402,763,764],{"class":475},"com.configdirector:android-sdk-compose:1.7.1",[402,766,613],{"class":606},[402,768,769],{"class":404,"line":449},[402,770,552],{"class":412},[393,772,777],{"className":773,"code":774,"filename":775,"language":776,"meta":398,"style":398},"language-toml shiki shiki-themes material-theme-lighter github-light github-dark","[versions]\nconfigdirector = \"1.7.1\"\n\n[libraries]\nconfigdirector-android-sdk = { module = \"com.configdirector:android-sdk\", version.ref = \"configdirector\" }\n# Optional, for Jetpack Compose applications\nconfigdirector-android-sdk-compose = { module = \"com.configdirector:android-sdk-compose\", version.ref = \"configdirector\" }\n","libs.versions.toml","toml",[272,778,779,791,807,811,820,866,871],{"__ignoreMap":398},[402,780,781,784,788],{"class":404,"line":405},[402,782,783],{"class":576},"[",[402,785,787],{"class":786},"sbgvK","versions",[402,789,790],{"class":576},"]\n",[402,792,793,796,798,801,804],{"class":404,"line":416},[402,794,795],{"class":412},"configdirector ",[402,797,472],{"class":576},[402,799,800],{"class":606}," \"",[402,802,803],{"class":475},"1.7.1",[402,805,806],{"class":606},"\"\n",[402,808,809],{"class":404,"line":424},[402,810,703],{"emptyLinePlaceholder":54},[402,812,813,815,818],{"class":404,"line":433},[402,814,783],{"class":576},[402,816,817],{"class":786},"libraries",[402,819,790],{"class":576},[402,821,822,825,827,830,833,835,837,839,842,845,848,851,854,856,858,861,863],{"class":404,"line":441},[402,823,824],{"class":412},"configdirector-android-sdk ",[402,826,472],{"class":576},[402,828,829],{"class":576}," {",[402,831,832],{"class":412}," module ",[402,834,472],{"class":576},[402,836,800],{"class":606},[402,838,312],{"class":475},[402,840,841],{"class":606},"\"",[402,843,844],{"class":576},",",[402,846,847],{"class":412}," version",[402,849,850],{"class":576},".",[402,852,853],{"class":412},"ref ",[402,855,472],{"class":576},[402,857,800],{"class":606},[402,859,860],{"class":475},"configdirector",[402,862,841],{"class":606},[402,864,865],{"class":576}," }\n",[402,867,868],{"class":404,"line":449},[402,869,870],{"class":708},"# Optional, for Jetpack Compose applications\n",[402,872,873,876,878,880,882,884,886,888,890,892,894,896,898,900,902,904,906],{"class":404,"line":457},[402,874,875],{"class":412},"configdirector-android-sdk-compose ",[402,877,472],{"class":576},[402,879,829],{"class":576},[402,881,832],{"class":412},[402,883,472],{"class":576},[402,885,800],{"class":606},[402,887,328],{"class":475},[402,889,841],{"class":606},[402,891,844],{"class":576},[402,893,847],{"class":412},[402,895,850],{"class":576},[402,897,853],{"class":412},[402,899,472],{"class":576},[402,901,800],{"class":606},[402,903,860],{"class":475},[402,905,841],{"class":606},[402,907,865],{"class":576},[265,909,910,911,914],{},"The SDK declares the ",[272,912,913],{},"INTERNET"," permission, which is merged into your application's manifest, so there is nothing to add there.",[260,916,918],{"id":917},"configure-and-initialize-the-client","Configure and initialize the client",[920,921,922,930],"ol",{},[923,924,925,926,929],"li",{},"Create an instance of the client providing an Android context and your client SDK key. You can retrieve a client SDK key for each environment under ",[272,927,928],{},"SDK keys"," in the dashboard's navigation panel.",[923,931,932],{},"Initialize the client to initiate its connection lifecycle.",[390,934,935,1008],{},[393,936,939],{"className":395,"code":937,"filename":938,"language":397,"meta":398,"style":398},"import com.configdirector.ConfigDirectorClient\n\n\u002F\u002F Creating the client makes no network calls. It throws only when the SDK key is\n\u002F\u002F blank or an option holds an unusable value.\nval client = ConfigDirectorClient(applicationContext, \"YOUR-CLIENT-SDK-KEY\")\n\n\u002F\u002F Connects and waits until config values are received, or until it times out.\n\u002F\u002F After a timeout the client keeps trying to connect in the background.\nclient.initialize()\n","ConfigDirectorSetup.kt",[272,940,941,949,953,958,963,984,988,993,998],{"__ignoreMap":398},[402,942,943,946],{"class":404,"line":405},[402,944,945],{"class":471},"import",[402,947,948],{"class":786}," com.configdirector.ConfigDirectorClient\n",[402,950,951],{"class":404,"line":416},[402,952,703],{"emptyLinePlaceholder":54},[402,954,955],{"class":404,"line":424},[402,956,957],{"class":708},"\u002F\u002F Creating the client makes no network calls. It throws only when the SDK key is\n",[402,959,960],{"class":404,"line":433},[402,961,962],{"class":708},"\u002F\u002F blank or an option holds an unusable value.\n",[402,964,965,968,971,973,976,979,982],{"class":404,"line":441},[402,966,967],{"class":471},"val",[402,969,970],{"class":412}," client ",[402,972,472],{"class":471},[402,974,975],{"class":408}," ConfigDirectorClient",[402,977,978],{"class":412},"(applicationContext, ",[402,980,981],{"class":475},"\"YOUR-CLIENT-SDK-KEY\"",[402,983,496],{"class":412},[402,985,986],{"class":404,"line":449},[402,987,703],{"emptyLinePlaceholder":54},[402,989,990],{"class":404,"line":457},[402,991,992],{"class":708},"\u002F\u002F Connects and waits until config values are received, or until it times out.\n",[402,994,995],{"class":404,"line":465},[402,996,997],{"class":708},"\u002F\u002F After a timeout the client keeps trying to connect in the background.\n",[402,999,1000,1003,1006],{"class":404,"line":479},[402,1001,1002],{"class":412},"client.",[402,1004,1005],{"class":408},"initialize",[402,1007,430],{"class":412},[393,1009,1014],{"className":1010,"code":1011,"filename":1012,"language":1013,"meta":398,"style":398},"language-java shiki shiki-themes material-theme-lighter github-light github-dark","import com.configdirector.ConfigDirectorClient;\n\n\u002F\u002F Creating the client makes no network calls. It throws only when the SDK key is\n\u002F\u002F blank or an option holds an unusable value.\nConfigDirectorClient client = new ConfigDirectorClient(getApplicationContext(), \"YOUR-CLIENT-SDK-KEY\");\n\n\u002F\u002F Connects, and calls back on the main thread once config values are received or\n\u002F\u002F the attempt times out. After a timeout the client keeps trying in the background.\nclient.initialize(null, () -> Log.i(\"MyApp\", \"ConfigDirector ready: \" + client.isReady()));\n","ConfigDirectorSetup.java","java",[272,1015,1016,1037,1041,1045,1049,1081,1085,1090,1095],{"__ignoreMap":398},[402,1017,1018,1021,1025,1027,1029,1031,1034],{"class":404,"line":405},[402,1019,945],{"class":1020},"sw1J6",[402,1022,1024],{"class":1023},"s_bVq"," com",[402,1026,850],{"class":576},[402,1028,860],{"class":1023},[402,1030,850],{"class":576},[402,1032,1033],{"class":1023},"ConfigDirectorClient",[402,1035,1036],{"class":576},";\n",[402,1038,1039],{"class":404,"line":416},[402,1040,703],{"emptyLinePlaceholder":54},[402,1042,1043],{"class":404,"line":424},[402,1044,957],{"class":708},[402,1046,1047],{"class":404,"line":433},[402,1048,962],{"class":708},[402,1050,1051,1053,1055,1057,1061,1063,1065,1068,1071,1073,1076,1078],{"class":404,"line":441},[402,1052,1033],{"class":1023},[402,1054,970],{"class":412},[402,1056,472],{"class":471},[402,1058,1060],{"class":1059},"sVHd0"," new",[402,1062,975],{"class":408},[402,1064,490],{"class":576},[402,1066,1067],{"class":408},"getApplicationContext",[402,1069,1070],{"class":576},"(),",[402,1072,800],{"class":606},[402,1074,1075],{"class":475},"YOUR-CLIENT-SDK-KEY",[402,1077,841],{"class":606},[402,1079,1080],{"class":576},");\n",[402,1082,1083],{"class":404,"line":449},[402,1084,703],{"emptyLinePlaceholder":54},[402,1086,1087],{"class":404,"line":457},[402,1088,1089],{"class":708},"\u002F\u002F Connects, and calls back on the main thread once config values are received or\n",[402,1091,1092],{"class":404,"line":465},[402,1093,1094],{"class":708},"\u002F\u002F the attempt times out. After a timeout the client keeps trying in the background.\n",[402,1096,1097,1100,1102,1104,1106,1110,1112,1115,1119,1122,1124,1127,1129,1131,1134,1136,1138,1140,1143,1145,1148,1151,1153,1156],{"class":404,"line":479},[402,1098,1099],{"class":412},"client",[402,1101,850],{"class":576},[402,1103,1005],{"class":408},[402,1105,490],{"class":576},[402,1107,1109],{"class":1108},"s39Yj","null",[402,1111,844],{"class":576},[402,1113,1114],{"class":576}," ()",[402,1116,1118],{"class":1117},"sbsja"," ->",[402,1120,1121],{"class":412}," Log",[402,1123,850],{"class":576},[402,1125,1126],{"class":408},"i",[402,1128,490],{"class":576},[402,1130,841],{"class":606},[402,1132,1133],{"class":475},"MyApp",[402,1135,841],{"class":606},[402,1137,844],{"class":576},[402,1139,800],{"class":606},[402,1141,1142],{"class":475},"ConfigDirector ready: ",[402,1144,841],{"class":606},[402,1146,1147],{"class":471}," +",[402,1149,1150],{"class":412}," client",[402,1152,850],{"class":576},[402,1154,1155],{"class":408},"isReady",[402,1157,1158],{"class":576},"()));\n",[265,1160,1161],{},"The client is thread safe. Create one and share it for the lifetime of the app.",[265,1163,1164,1166,1167,1169,1170,1173],{},[272,1165,1005],{}," is a ",[272,1168,274],{}," function in Kotlin, so it is called from a coroutine. The overload taking a ",[272,1171,1172],{},"CompletionCallback"," is the one to use from Java, and from anywhere in Kotlin that has no coroutine to run in.",[1175,1176,1177],"note",{},"Before the client is initialized, config values will evaluate to the default value provided in code.",[265,1179,1180,1181,1184,1185,1187,1188,1190],{},"The constructor throws a ",[272,1182,1183],{},"ConfigDirectorValidationException"," in only two cases, both of which are programming errors rather than runtime conditions: a blank client SDK key, and an option that cannot be used, such as a negative timeout or a base URL that is not absolute. Connection failures are not thrown — ",[272,1186,1005],{}," returns normally whether or not config state arrived, and ",[272,1189,1155],{}," tells you which happened.",[265,1192,1193,1194,1197],{},"Most applications create a single client instance and initialize it during startup. That usually means owning it in the ",[272,1195,1196],{},"Application",", so every screen shares one client:",[390,1199,1200,1400],{},[393,1201,1204],{"className":395,"code":1202,"filename":1203,"language":397,"meta":398,"style":398},"import android.app.Application\nimport com.configdirector.ConfigDirectorClient\nimport com.configdirector.ConfigDirectorContext\nimport kotlinx.coroutines.MainScope\nimport kotlinx.coroutines.launch\n\nclass MyApplication : Application() {\n\n    lateinit var client: ConfigDirectorClient\n        private set\n\n    override fun onCreate() {\n        super.onCreate()\n\n        client = ConfigDirectorClient(this, \"YOUR-CLIENT-SDK-KEY\")\n\n        MainScope().launch {\n            client.initialize(ConfigDirectorContext.build { id(\"user-123\") })\n        }\n    }\n}\n","MyApplication.kt",[272,1205,1206,1213,1219,1226,1233,1240,1244,1260,1264,1278,1286,1290,1303,1315,1319,1340,1344,1357,1385,1390,1395],{"__ignoreMap":398},[402,1207,1208,1210],{"class":404,"line":405},[402,1209,945],{"class":471},[402,1211,1212],{"class":786}," android.app.Application\n",[402,1214,1215,1217],{"class":404,"line":416},[402,1216,945],{"class":471},[402,1218,948],{"class":786},[402,1220,1221,1223],{"class":404,"line":424},[402,1222,945],{"class":471},[402,1224,1225],{"class":786}," com.configdirector.ConfigDirectorContext\n",[402,1227,1228,1230],{"class":404,"line":433},[402,1229,945],{"class":471},[402,1231,1232],{"class":786}," kotlinx.coroutines.MainScope\n",[402,1234,1235,1237],{"class":404,"line":441},[402,1236,945],{"class":471},[402,1238,1239],{"class":786}," kotlinx.coroutines.launch\n",[402,1241,1242],{"class":404,"line":449},[402,1243,703],{"emptyLinePlaceholder":54},[402,1245,1246,1249,1252,1255,1257],{"class":404,"line":457},[402,1247,1248],{"class":471},"class",[402,1250,1251],{"class":786}," MyApplication",[402,1253,1254],{"class":412}," : ",[402,1256,1196],{"class":786},[402,1258,1259],{"class":412},"() {\n",[402,1261,1262],{"class":404,"line":465},[402,1263,703],{"emptyLinePlaceholder":54},[402,1265,1266,1269,1272,1275],{"class":404,"line":479},[402,1267,1268],{"class":1117},"    lateinit",[402,1270,1271],{"class":471}," var",[402,1273,1274],{"class":412}," client: ",[402,1276,1277],{"class":786},"ConfigDirectorClient\n",[402,1279,1280,1283],{"class":404,"line":499},[402,1281,1282],{"class":1117},"        private",[402,1284,1285],{"class":1117}," set\n",[402,1287,1288],{"class":404,"line":505},[402,1289,703],{"emptyLinePlaceholder":54},[402,1291,1292,1295,1298,1301],{"class":404,"line":511},[402,1293,1294],{"class":1117},"    override",[402,1296,1297],{"class":471}," fun",[402,1299,1300],{"class":408}," onCreate",[402,1302,1259],{"class":412},[402,1304,1305,1308,1310,1313],{"class":404,"line":519},[402,1306,1307],{"class":1108},"        super",[402,1309,850],{"class":412},[402,1311,1312],{"class":408},"onCreate",[402,1314,430],{"class":412},[402,1316,1317],{"class":404,"line":532},[402,1318,703],{"emptyLinePlaceholder":54},[402,1320,1321,1324,1326,1328,1330,1333,1336,1338],{"class":404,"line":537},[402,1322,1323],{"class":412},"        client ",[402,1325,472],{"class":471},[402,1327,975],{"class":408},[402,1329,490],{"class":412},[402,1331,1332],{"class":1108},"this",[402,1334,1335],{"class":412},", ",[402,1337,981],{"class":475},[402,1339,496],{"class":412},[402,1341,1342],{"class":404,"line":543},[402,1343,703],{"emptyLinePlaceholder":54},[402,1345,1346,1349,1352,1355],{"class":404,"line":549},[402,1347,1348],{"class":408},"        MainScope",[402,1350,1351],{"class":412},"().",[402,1353,1354],{"class":408},"launch",[402,1356,413],{"class":412},[402,1358,1360,1363,1365,1368,1371,1374,1377,1379,1382],{"class":404,"line":1359},18,[402,1361,1362],{"class":412},"            client.",[402,1364,1005],{"class":408},[402,1366,1367],{"class":412},"(ConfigDirectorContext.",[402,1369,1370],{"class":408},"build",[402,1372,1373],{"class":412}," { ",[402,1375,1376],{"class":408},"id",[402,1378,490],{"class":412},[402,1380,1381],{"class":475},"\"user-123\"",[402,1383,1384],{"class":412},") })\n",[402,1386,1388],{"class":404,"line":1387},19,[402,1389,540],{"class":412},[402,1391,1393],{"class":404,"line":1392},20,[402,1394,546],{"class":412},[402,1396,1398],{"class":404,"line":1397},21,[402,1399,552],{"class":412},[393,1401,1404],{"className":1010,"code":1402,"filename":1403,"language":1013,"meta":398,"style":398},"import android.app.Application;\nimport com.configdirector.ConfigDirectorClient;\nimport com.configdirector.ConfigDirectorContext;\n\npublic class MyApplication extends Application {\n\n  private ConfigDirectorClient client;\n\n  @Override\n  public void onCreate() {\n    super.onCreate();\n\n    client = new ConfigDirectorClient(this, \"YOUR-CLIENT-SDK-KEY\");\n\n    client.initialize(\n        ConfigDirectorContext.builder().id(\"user-123\").build(),\n        () -> Log.i(\"MyApp\", \"ConfigDirector ready: \" + client.isReady()));\n  }\n\n  public ConfigDirectorClient getClient() {\n    return client;\n  }\n}\n","MyApplication.java",[272,1405,1406,1424,1440,1457,1461,1479,1483,1494,1498,1506,1521,1534,1538,1563,1567,1579,1610,1649,1654,1658,1671,1680,1685],{"__ignoreMap":398},[402,1407,1408,1410,1413,1415,1418,1420,1422],{"class":404,"line":405},[402,1409,945],{"class":1020},[402,1411,1412],{"class":1023}," android",[402,1414,850],{"class":576},[402,1416,1417],{"class":1023},"app",[402,1419,850],{"class":576},[402,1421,1196],{"class":1023},[402,1423,1036],{"class":576},[402,1425,1426,1428,1430,1432,1434,1436,1438],{"class":404,"line":416},[402,1427,945],{"class":1020},[402,1429,1024],{"class":1023},[402,1431,850],{"class":576},[402,1433,860],{"class":1023},[402,1435,850],{"class":576},[402,1437,1033],{"class":1023},[402,1439,1036],{"class":576},[402,1441,1442,1444,1446,1448,1450,1452,1455],{"class":404,"line":424},[402,1443,945],{"class":1020},[402,1445,1024],{"class":1023},[402,1447,850],{"class":576},[402,1449,860],{"class":1023},[402,1451,850],{"class":576},[402,1453,1454],{"class":1023},"ConfigDirectorContext",[402,1456,1036],{"class":576},[402,1458,1459],{"class":404,"line":433},[402,1460,703],{"emptyLinePlaceholder":54},[402,1462,1463,1466,1469,1471,1474,1477],{"class":404,"line":441},[402,1464,1465],{"class":1117},"public",[402,1467,1468],{"class":1117}," class",[402,1470,1251],{"class":786},[402,1472,1473],{"class":1117}," extends",[402,1475,1476],{"class":786}," Application",[402,1478,413],{"class":576},[402,1480,1481],{"class":404,"line":449},[402,1482,703],{"emptyLinePlaceholder":54},[402,1484,1485,1488,1490,1492],{"class":404,"line":457},[402,1486,1487],{"class":1117},"  private",[402,1489,975],{"class":1023},[402,1491,1150],{"class":412},[402,1493,1036],{"class":576},[402,1495,1496],{"class":404,"line":465},[402,1497,703],{"emptyLinePlaceholder":54},[402,1499,1500,1503],{"class":404,"line":479},[402,1501,1502],{"class":576},"  @",[402,1504,1505],{"class":1117},"Override\n",[402,1507,1508,1511,1514,1516,1519],{"class":404,"line":499},[402,1509,1510],{"class":1117},"  public",[402,1512,1513],{"class":1117}," void",[402,1515,1300],{"class":408},[402,1517,1518],{"class":576},"()",[402,1520,413],{"class":576},[402,1522,1523,1527,1529,1531],{"class":404,"line":505},[402,1524,1526],{"class":1525},"s_hVV","    super",[402,1528,850],{"class":576},[402,1530,1312],{"class":408},[402,1532,1533],{"class":576},"();\n",[402,1535,1536],{"class":404,"line":511},[402,1537,703],{"emptyLinePlaceholder":54},[402,1539,1540,1543,1545,1547,1549,1551,1553,1555,1557,1559,1561],{"class":404,"line":519},[402,1541,1542],{"class":412},"    client ",[402,1544,472],{"class":471},[402,1546,1060],{"class":1059},[402,1548,975],{"class":408},[402,1550,490],{"class":576},[402,1552,1332],{"class":1108},[402,1554,844],{"class":576},[402,1556,800],{"class":606},[402,1558,1075],{"class":475},[402,1560,841],{"class":606},[402,1562,1080],{"class":576},[402,1564,1565],{"class":404,"line":532},[402,1566,703],{"emptyLinePlaceholder":54},[402,1568,1569,1572,1574,1576],{"class":404,"line":537},[402,1570,1571],{"class":412},"    client",[402,1573,850],{"class":576},[402,1575,1005],{"class":408},[402,1577,1578],{"class":576},"(\n",[402,1580,1581,1584,1586,1589,1591,1593,1595,1597,1600,1602,1605,1607],{"class":404,"line":543},[402,1582,1583],{"class":412},"        ConfigDirectorContext",[402,1585,850],{"class":576},[402,1587,1588],{"class":408},"builder",[402,1590,1351],{"class":576},[402,1592,1376],{"class":408},[402,1594,490],{"class":576},[402,1596,841],{"class":606},[402,1598,1599],{"class":475},"user-123",[402,1601,841],{"class":606},[402,1603,1604],{"class":576},").",[402,1606,1370],{"class":408},[402,1608,1609],{"class":576},"(),\n",[402,1611,1612,1615,1617,1619,1621,1623,1625,1627,1629,1631,1633,1635,1637,1639,1641,1643,1645,1647],{"class":404,"line":549},[402,1613,1614],{"class":576},"        ()",[402,1616,1118],{"class":1117},[402,1618,1121],{"class":412},[402,1620,850],{"class":576},[402,1622,1126],{"class":408},[402,1624,490],{"class":576},[402,1626,841],{"class":606},[402,1628,1133],{"class":475},[402,1630,841],{"class":606},[402,1632,844],{"class":576},[402,1634,800],{"class":606},[402,1636,1142],{"class":475},[402,1638,841],{"class":606},[402,1640,1147],{"class":471},[402,1642,1150],{"class":412},[402,1644,850],{"class":576},[402,1646,1155],{"class":408},[402,1648,1158],{"class":576},[402,1650,1651],{"class":404,"line":1359},[402,1652,1653],{"class":576},"  }\n",[402,1655,1656],{"class":404,"line":1387},[402,1657,703],{"emptyLinePlaceholder":54},[402,1659,1660,1662,1664,1667,1669],{"class":404,"line":1392},[402,1661,1510],{"class":1117},[402,1663,975],{"class":1023},[402,1665,1666],{"class":408}," getClient",[402,1668,1518],{"class":576},[402,1670,413],{"class":576},[402,1672,1673,1676,1678],{"class":404,"line":1397},[402,1674,1675],{"class":1059},"    return",[402,1677,1150],{"class":412},[402,1679,1036],{"class":576},[402,1681,1683],{"class":404,"line":1682},22,[402,1684,1653],{"class":576},[402,1686,1688],{"class":404,"line":1687},23,[402,1689,552],{"class":576},[1175,1691,1692,1693,1695,1696,850],{},"The client watches the application behind the context it was given so it can release its network connection while the app is backgrounded. Pass it any context — the application behind it is what matters. If the context does not belong to an ",[272,1694,1196],{},", the SDK logs a warning and leaves the connection running for you to manage with ",[369,1697,1699,384,1702],{"href":1698},"#pausenetwork-and-resumenetwork",[272,1700,1701],{},"pauseNetwork()",[272,1703,1704],{},"resumeNetwork()",[265,1706,1707,1708,1714],{},"Nothing needs to close the client: it lives as long as the process, and Android reclaims everything when the process ends. Call ",[369,1709,1711],{"href":1710},"#close",[272,1712,1713],{},"close()"," when an application wants the client gone before that, on sign-out for instance.",[1716,1717,1719],"h3",{"id":1718},"additional-configuration-options","Additional configuration options",[265,1721,1722,1723,1726,1727,1730,1731,1734],{},"These options can be passed in to ",[272,1724,1725],{},"ClientOptions",", which is built with ",[272,1728,1729],{},"ClientOptions.build { }"," from Kotlin and ",[272,1732,1733],{},"ClientOptions.builder()"," from Java. They are read once when the client is created; changing them afterwards has no effect.",[1736,1737,1739],"h4",{"id":1738},"metadata",[272,1740,1738],{},[265,1742,1743,1744,1746],{},"The ",[272,1745,1738],{}," option allows you to provide your application's name and version. These values can be used in targeting rules conditionals. For example, if a certain feature should only be enabled starting with a certain version of your application.",[265,1748,1749,1750,1753,1754,1757],{},"Whichever of the two you leave unset is read from the application when the client is created — the name from the application label and the version from ",[272,1751,1752],{},"versionName"," — so most applications do not need to set either one. When one cannot be read, the client says so at the ",[272,1755,1756],{},"INFO"," log level.",[390,1759,1760,1825],{},[393,1761,1763],{"className":395,"code":1762,"filename":938,"language":397,"meta":398,"style":398},"val client = ConfigDirectorClient(\n    applicationContext,\n    \"YOUR-CLIENT-SDK-KEY\",\n    ClientOptions.build {\n        metadata(\"YOUR-APP-NAME\", \"1.0.2\")\n    },\n)\n",[272,1764,1765,1777,1782,1790,1799,1816,1821],{"__ignoreMap":398},[402,1766,1767,1769,1771,1773,1775],{"class":404,"line":405},[402,1768,967],{"class":471},[402,1770,970],{"class":412},[402,1772,472],{"class":471},[402,1774,975],{"class":408},[402,1776,1578],{"class":412},[402,1778,1779],{"class":404,"line":416},[402,1780,1781],{"class":412},"    applicationContext,\n",[402,1783,1784,1787],{"class":404,"line":424},[402,1785,1786],{"class":475},"    \"YOUR-CLIENT-SDK-KEY\"",[402,1788,1789],{"class":412},",\n",[402,1791,1792,1795,1797],{"class":404,"line":433},[402,1793,1794],{"class":412},"    ClientOptions.",[402,1796,1370],{"class":408},[402,1798,413],{"class":412},[402,1800,1801,1804,1806,1809,1811,1814],{"class":404,"line":441},[402,1802,1803],{"class":408},"        metadata",[402,1805,490],{"class":412},[402,1807,1808],{"class":475},"\"YOUR-APP-NAME\"",[402,1810,1335],{"class":412},[402,1812,1813],{"class":475},"\"1.0.2\"",[402,1815,496],{"class":412},[402,1817,1818],{"class":404,"line":449},[402,1819,1820],{"class":412},"    },\n",[402,1822,1823],{"class":404,"line":457},[402,1824,496],{"class":412},[393,1826,1828],{"className":1010,"code":1827,"filename":1012,"language":1013,"meta":398,"style":398},"ConfigDirectorClient client = new ConfigDirectorClient(\n    getApplicationContext(),\n    \"YOUR-CLIENT-SDK-KEY\",\n    ClientOptions.builder()\n        .metadata(new Metadata(\"YOUR-APP-NAME\", \"1.0.2\"))\n        .build());\n",[272,1829,1830,1844,1851,1862,1873,1909],{"__ignoreMap":398},[402,1831,1832,1834,1836,1838,1840,1842],{"class":404,"line":405},[402,1833,1033],{"class":1023},[402,1835,970],{"class":412},[402,1837,472],{"class":471},[402,1839,1060],{"class":1059},[402,1841,975],{"class":408},[402,1843,1578],{"class":576},[402,1845,1846,1849],{"class":404,"line":416},[402,1847,1848],{"class":408},"    getApplicationContext",[402,1850,1609],{"class":576},[402,1852,1853,1856,1858,1860],{"class":404,"line":424},[402,1854,1855],{"class":606},"    \"",[402,1857,1075],{"class":475},[402,1859,841],{"class":606},[402,1861,1789],{"class":576},[402,1863,1864,1867,1869,1871],{"class":404,"line":433},[402,1865,1866],{"class":412},"    ClientOptions",[402,1868,850],{"class":576},[402,1870,1588],{"class":408},[402,1872,430],{"class":576},[402,1874,1875,1878,1880,1882,1885,1888,1890,1892,1895,1897,1899,1901,1904,1906],{"class":404,"line":441},[402,1876,1877],{"class":576},"        .",[402,1879,1738],{"class":408},[402,1881,490],{"class":576},[402,1883,1884],{"class":1059},"new",[402,1886,1887],{"class":408}," Metadata",[402,1889,490],{"class":576},[402,1891,841],{"class":606},[402,1893,1894],{"class":475},"YOUR-APP-NAME",[402,1896,841],{"class":606},[402,1898,844],{"class":576},[402,1900,800],{"class":606},[402,1902,1903],{"class":475},"1.0.2",[402,1905,841],{"class":606},[402,1907,1908],{"class":576},"))\n",[402,1910,1911,1913,1915],{"class":404,"line":449},[402,1912,1877],{"class":576},[402,1914,1370],{"class":408},[402,1916,1917],{"class":576},"());\n",[1736,1919,1921],{"id":1920},"logger",[272,1922,1920],{},[265,1924,1925,1926,1928,1929,1931,1932,1935,1936,1939],{},"By default, the SDK logs to logcat under the ",[272,1927,610],{}," tag, and it is set to log warnings and errors only. You can configure a ",[272,1930,1920],{}," by either creating an ",[272,1933,1934],{},"AndroidLogger"," with a different log level, or by implementing the ",[272,1937,1938],{},"ConfigDirectorLogger"," interface to provide your own logger. The interface can be used to create an adapter to another logging library.",[265,1941,1942],{},"Configure the default logger to a different level:",[390,1944,1945,1993],{},[393,1946,1948],{"className":395,"code":1947,"filename":938,"language":397,"meta":398,"style":398},"val client = ConfigDirectorClient(\n    applicationContext,\n    \"YOUR-CLIENT-SDK-KEY\",\n    ClientOptions.build { logger(AndroidLogger(LogLevel.DEBUG)) },\n)\n",[272,1949,1950,1962,1966,1972,1989],{"__ignoreMap":398},[402,1951,1952,1954,1956,1958,1960],{"class":404,"line":405},[402,1953,967],{"class":471},[402,1955,970],{"class":412},[402,1957,472],{"class":471},[402,1959,975],{"class":408},[402,1961,1578],{"class":412},[402,1963,1964],{"class":404,"line":416},[402,1965,1781],{"class":412},[402,1967,1968,1970],{"class":404,"line":424},[402,1969,1786],{"class":475},[402,1971,1789],{"class":412},[402,1973,1974,1976,1978,1980,1982,1984,1986],{"class":404,"line":433},[402,1975,1794],{"class":412},[402,1977,1370],{"class":408},[402,1979,1373],{"class":412},[402,1981,1920],{"class":408},[402,1983,490],{"class":412},[402,1985,1934],{"class":408},[402,1987,1988],{"class":412},"(LogLevel.DEBUG)) },\n",[402,1990,1991],{"class":404,"line":441},[402,1992,496],{"class":412},[393,1994,1996],{"className":1010,"code":1995,"filename":1012,"language":1013,"meta":398,"style":398},"ConfigDirectorClient client = new ConfigDirectorClient(\n    getApplicationContext(),\n    \"YOUR-CLIENT-SDK-KEY\",\n    ClientOptions.builder().logger(new AndroidLogger(LogLevel.DEBUG)).build());\n",[272,1997,1998,2012,2018,2028],{"__ignoreMap":398},[402,1999,2000,2002,2004,2006,2008,2010],{"class":404,"line":405},[402,2001,1033],{"class":1023},[402,2003,970],{"class":412},[402,2005,472],{"class":471},[402,2007,1060],{"class":1059},[402,2009,975],{"class":408},[402,2011,1578],{"class":576},[402,2013,2014,2016],{"class":404,"line":416},[402,2015,1848],{"class":408},[402,2017,1609],{"class":576},[402,2019,2020,2022,2024,2026],{"class":404,"line":424},[402,2021,1855],{"class":606},[402,2023,1075],{"class":475},[402,2025,841],{"class":606},[402,2027,1789],{"class":576},[402,2029,2030,2032,2034,2036,2038,2040,2042,2044,2047,2049,2052,2054,2057,2060,2062],{"class":404,"line":433},[402,2031,1866],{"class":412},[402,2033,850],{"class":576},[402,2035,1588],{"class":408},[402,2037,1351],{"class":576},[402,2039,1920],{"class":408},[402,2041,490],{"class":576},[402,2043,1884],{"class":1059},[402,2045,2046],{"class":408}," AndroidLogger",[402,2048,490],{"class":576},[402,2050,2051],{"class":412},"LogLevel",[402,2053,850],{"class":576},[402,2055,2056],{"class":412},"DEBUG",[402,2058,2059],{"class":576},")).",[402,2061,1370],{"class":408},[402,2063,1917],{"class":576},[265,2065,2066,2067,1335,2070,1335,2073,2076,2077,384,2079,850],{},"The available levels are ",[272,2068,2069],{},"OFF",[272,2071,2072],{},"ERROR",[272,2074,2075],{},"WARN"," (the default), ",[272,2078,1756],{},[272,2080,2056],{},[265,2082,2083],{},"Implement your own logger adapter:",[390,2085,2086,2240],{},[393,2087,2090],{"className":395,"code":2088,"filename":2089,"language":397,"meta":398,"style":398},"import com.configdirector.ConfigDirectorLogger\nimport com.configdirector.LogLevel\n\nclass MyLogger : ConfigDirectorLogger {\n    \u002F\u002F Messages more verbose than this level are never passed to `log`.\n    override val level: LogLevel = LogLevel.INFO\n\n    override fun log(level: LogLevel, message: String, error: Throwable?) {\n        \u002F\u002F your specific logging library implementation here\n    }\n}\n\nval client = ConfigDirectorClient(\n    applicationContext,\n    \"YOUR-CLIENT-SDK-KEY\",\n    ClientOptions.build { logger(MyLogger()) },\n)\n","MyLogger.kt",[272,2091,2092,2099,2106,2110,2123,2128,2146,2150,2179,2184,2188,2192,2196,2208,2212,2218,2236],{"__ignoreMap":398},[402,2093,2094,2096],{"class":404,"line":405},[402,2095,945],{"class":471},[402,2097,2098],{"class":786}," com.configdirector.ConfigDirectorLogger\n",[402,2100,2101,2103],{"class":404,"line":416},[402,2102,945],{"class":471},[402,2104,2105],{"class":786}," com.configdirector.LogLevel\n",[402,2107,2108],{"class":404,"line":424},[402,2109,703],{"emptyLinePlaceholder":54},[402,2111,2112,2114,2117,2119,2121],{"class":404,"line":433},[402,2113,1248],{"class":471},[402,2115,2116],{"class":786}," MyLogger",[402,2118,1254],{"class":412},[402,2120,1938],{"class":786},[402,2122,413],{"class":412},[402,2124,2125],{"class":404,"line":441},[402,2126,2127],{"class":708},"    \u002F\u002F Messages more verbose than this level are never passed to `log`.\n",[402,2129,2130,2132,2135,2138,2140,2143],{"class":404,"line":449},[402,2131,1294],{"class":1117},[402,2133,2134],{"class":471}," val",[402,2136,2137],{"class":412}," level: ",[402,2139,2051],{"class":786},[402,2141,2142],{"class":471}," =",[402,2144,2145],{"class":412}," LogLevel.INFO\n",[402,2147,2148],{"class":404,"line":457},[402,2149,703],{"emptyLinePlaceholder":54},[402,2151,2152,2154,2156,2159,2162,2164,2167,2170,2173,2176],{"class":404,"line":465},[402,2153,1294],{"class":1117},[402,2155,1297],{"class":471},[402,2157,2158],{"class":408}," log",[402,2160,2161],{"class":412},"(level: ",[402,2163,2051],{"class":786},[402,2165,2166],{"class":412},", message: ",[402,2168,2169],{"class":786},"String",[402,2171,2172],{"class":412},", error: ",[402,2174,2175],{"class":786},"Throwable",[402,2177,2178],{"class":412},"?) {\n",[402,2180,2181],{"class":404,"line":479},[402,2182,2183],{"class":708},"        \u002F\u002F your specific logging library implementation here\n",[402,2185,2186],{"class":404,"line":499},[402,2187,546],{"class":412},[402,2189,2190],{"class":404,"line":505},[402,2191,552],{"class":412},[402,2193,2194],{"class":404,"line":511},[402,2195,703],{"emptyLinePlaceholder":54},[402,2197,2198,2200,2202,2204,2206],{"class":404,"line":519},[402,2199,967],{"class":471},[402,2201,970],{"class":412},[402,2203,472],{"class":471},[402,2205,975],{"class":408},[402,2207,1578],{"class":412},[402,2209,2210],{"class":404,"line":532},[402,2211,1781],{"class":412},[402,2213,2214,2216],{"class":404,"line":537},[402,2215,1786],{"class":475},[402,2217,1789],{"class":412},[402,2219,2220,2222,2224,2226,2228,2230,2233],{"class":404,"line":543},[402,2221,1794],{"class":412},[402,2223,1370],{"class":408},[402,2225,1373],{"class":412},[402,2227,1920],{"class":408},[402,2229,490],{"class":412},[402,2231,2232],{"class":408},"MyLogger",[402,2234,2235],{"class":412},"()) },\n",[402,2237,2238],{"class":404,"line":549},[402,2239,496],{"class":412},[393,2241,2244],{"className":1010,"code":2242,"filename":2243,"language":1013,"meta":398,"style":398},"import com.configdirector.ConfigDirectorLogger;\nimport com.configdirector.LogLevel;\n\npublic final class MyLogger implements ConfigDirectorLogger {\n\n  \u002F\u002F Messages more verbose than this level are never passed to `log`.\n  @Override\n  public LogLevel getLevel() {\n    return LogLevel.INFO;\n  }\n\n  @Override\n  public void log(LogLevel level, String message, Throwable error) {\n    \u002F\u002F your specific logging library implementation here\n  }\n}\n","MyLogger.java",[272,2245,2246,2262,2278,2282,2301,2305,2310,2316,2330,2342,2346,2350,2356,2393,2398,2402],{"__ignoreMap":398},[402,2247,2248,2250,2252,2254,2256,2258,2260],{"class":404,"line":405},[402,2249,945],{"class":1020},[402,2251,1024],{"class":1023},[402,2253,850],{"class":576},[402,2255,860],{"class":1023},[402,2257,850],{"class":576},[402,2259,1938],{"class":1023},[402,2261,1036],{"class":576},[402,2263,2264,2266,2268,2270,2272,2274,2276],{"class":404,"line":416},[402,2265,945],{"class":1020},[402,2267,1024],{"class":1023},[402,2269,850],{"class":576},[402,2271,860],{"class":1023},[402,2273,850],{"class":576},[402,2275,2051],{"class":1023},[402,2277,1036],{"class":576},[402,2279,2280],{"class":404,"line":424},[402,2281,703],{"emptyLinePlaceholder":54},[402,2283,2284,2286,2289,2291,2293,2296,2299],{"class":404,"line":433},[402,2285,1465],{"class":1117},[402,2287,2288],{"class":1117}," final",[402,2290,1468],{"class":1117},[402,2292,2116],{"class":786},[402,2294,2295],{"class":1117}," implements",[402,2297,2298],{"class":786}," ConfigDirectorLogger",[402,2300,413],{"class":576},[402,2302,2303],{"class":404,"line":441},[402,2304,703],{"emptyLinePlaceholder":54},[402,2306,2307],{"class":404,"line":449},[402,2308,2309],{"class":708},"  \u002F\u002F Messages more verbose than this level are never passed to `log`.\n",[402,2311,2312,2314],{"class":404,"line":457},[402,2313,1502],{"class":576},[402,2315,1505],{"class":1117},[402,2317,2318,2320,2323,2326,2328],{"class":404,"line":465},[402,2319,1510],{"class":1117},[402,2321,2322],{"class":1023}," LogLevel",[402,2324,2325],{"class":408}," getLevel",[402,2327,1518],{"class":576},[402,2329,413],{"class":576},[402,2331,2332,2334,2336,2338,2340],{"class":404,"line":479},[402,2333,1675],{"class":1059},[402,2335,2322],{"class":412},[402,2337,850],{"class":576},[402,2339,1756],{"class":412},[402,2341,1036],{"class":576},[402,2343,2344],{"class":404,"line":499},[402,2345,1653],{"class":576},[402,2347,2348],{"class":404,"line":505},[402,2349,703],{"emptyLinePlaceholder":54},[402,2351,2352,2354],{"class":404,"line":511},[402,2353,1502],{"class":576},[402,2355,1505],{"class":1117},[402,2357,2358,2360,2362,2364,2366,2368,2372,2374,2377,2380,2382,2385,2388,2391],{"class":404,"line":519},[402,2359,1510],{"class":1117},[402,2361,1513],{"class":1117},[402,2363,2158],{"class":408},[402,2365,490],{"class":576},[402,2367,2051],{"class":1023},[402,2369,2371],{"class":2370},"s99_P"," level",[402,2373,844],{"class":576},[402,2375,2376],{"class":1023}," String",[402,2378,2379],{"class":2370}," message",[402,2381,844],{"class":576},[402,2383,2384],{"class":1023}," Throwable",[402,2386,2387],{"class":2370}," error",[402,2389,2390],{"class":576},")",[402,2392,413],{"class":576},[402,2394,2395],{"class":404,"line":532},[402,2396,2397],{"class":708},"    \u002F\u002F your specific logging library implementation here\n",[402,2399,2400],{"class":404,"line":537},[402,2401,1653],{"class":576},[402,2403,2404],{"class":404,"line":543},[402,2405,552],{"class":576},[1736,2407,2409],{"id":2408},"connection",[272,2410,2408],{},[265,2412,2413,2416],{},[272,2414,2415],{},"ConnectionOptions"," accepts five optional values:",[2418,2419,2420,2455,2488,2516,2539],"ul",{},[923,2421,2422,2425],{},[272,2423,2424],{},"mode",[2418,2426,2427,2445,2450],{},[923,2428,2429,2430,376,2433,2436,2437,2440,2441,2444],{},"The connection mode, which can be ",[272,2431,2432],{},"ConnectionMode.STREAMING",[272,2434,2435],{},"ConnectionMode.POLLING",". It is recommended to use the default of ",[272,2438,2439],{},"STREAMING"," unless you have a specific need to use ",[272,2442,2443],{},"POLLING"," instead.",[923,2446,2447,2449],{},[272,2448,2439],{}," holds a connection open and receives changes as they happen, reconnecting on its own with a backoff.",[923,2451,2452,2453],{},"Defaults to ",[272,2454,2432],{},[923,2456,2457,2460],{},[272,2458,2459],{},"pollingIntervalMillis",[2418,2461,2462,2482],{},[923,2463,2464,2465,2467,2468,2470,2471,2474,2475,2477,2478,850],{},"How often to re-fetch config state, in milliseconds, when ",[272,2466,2424],{}," is ",[272,2469,2435],{},". It has no effect in any other mode. A value below the minimum of ",[272,2472,2473],{},"30_000"," (30 seconds) is raised to ",[272,2476,2473],{}," and a warning is logged. See ",[369,2479,2481],{"href":2480},"\u002Fgetting-started\u002Farchitecture#polling-intervals","Polling intervals",[923,2483,2452,2484,2487],{},[272,2485,2486],{},"60_000"," (60 seconds)",[923,2489,2490,2493],{},[272,2491,2492],{},"timeoutMillis",[2418,2494,2495,2504,2510],{},[923,2496,2497,2498,2500,2501,2503],{},"The timeout to be used in initialization and when updating the context. This is how long ",[272,2499,1005],{}," will wait for data from ConfigDirector services before returning. If the timeout is reached, ",[272,2502,1005],{}," will return but the client will still be in an unready status and returning default values. The client will continue to attempt to connect and retrieve config values in the background.",[923,2505,2506,2507,2509],{},"If your application is used in environments where the users frequently have poor or no connection, you may want to use a lower timeout, or simply don't await the ",[272,2508,1005],{}," call.",[923,2511,2452,2512,2515],{},[272,2513,2514],{},"3_000"," (3 seconds)",[923,2517,2518,2521],{},[272,2519,2520],{},"pausesWhileBackgrounded",[2418,2522,2523,2534],{},[923,2524,2525,2526,2529,2530,384,2532,850],{},"Whether to pause the connection while the app is in the background and resume it when the app returns to the foreground. Android stops background connections on its own, so this is enabled by default. Set it to ",[272,2527,2528],{},"false"," to manage the connection yourself with ",[272,2531,1701],{},[272,2533,1704],{},[923,2535,2452,2536],{},[272,2537,2538],{},"true",[923,2540,2541,2544],{},[272,2542,2543],{},"baseUrl",[2418,2545,2546,2549],{},[923,2547,2548],{},"The base URL used to connect to ConfigDirector services.",[923,2550,2551],{},"This should only be provided if your environment requires you to configure a proxy server in order to connect to ConfigDirector services.",[390,2553,2554,2641],{},[393,2555,2557],{"className":395,"code":2556,"filename":938,"language":397,"meta":398,"style":398},"val client = ConfigDirectorClient(\n    applicationContext,\n    \"YOUR-CLIENT-SDK-KEY\",\n    ClientOptions.build {\n        connection {\n            mode(ConnectionMode.POLLING)\n            pollingIntervalMillis(600_000L)\n            timeoutMillis(2_000L)\n        }\n    },\n)\n",[272,2558,2559,2571,2575,2581,2589,2596,2604,2617,2629,2633,2637],{"__ignoreMap":398},[402,2560,2561,2563,2565,2567,2569],{"class":404,"line":405},[402,2562,967],{"class":471},[402,2564,970],{"class":412},[402,2566,472],{"class":471},[402,2568,975],{"class":408},[402,2570,1578],{"class":412},[402,2572,2573],{"class":404,"line":416},[402,2574,1781],{"class":412},[402,2576,2577,2579],{"class":404,"line":424},[402,2578,1786],{"class":475},[402,2580,1789],{"class":412},[402,2582,2583,2585,2587],{"class":404,"line":433},[402,2584,1794],{"class":412},[402,2586,1370],{"class":408},[402,2588,413],{"class":412},[402,2590,2591,2594],{"class":404,"line":441},[402,2592,2593],{"class":408},"        connection",[402,2595,413],{"class":412},[402,2597,2598,2601],{"class":404,"line":449},[402,2599,2600],{"class":408},"            mode",[402,2602,2603],{"class":412},"(ConnectionMode.POLLING)\n",[402,2605,2606,2609,2611,2615],{"class":404,"line":457},[402,2607,2608],{"class":408},"            pollingIntervalMillis",[402,2610,490],{"class":412},[402,2612,2614],{"class":2613},"srdBf","600_000L",[402,2616,496],{"class":412},[402,2618,2619,2622,2624,2627],{"class":404,"line":465},[402,2620,2621],{"class":408},"            timeoutMillis",[402,2623,490],{"class":412},[402,2625,2626],{"class":2613},"2_000L",[402,2628,496],{"class":412},[402,2630,2631],{"class":404,"line":479},[402,2632,540],{"class":412},[402,2634,2635],{"class":404,"line":499},[402,2636,1820],{"class":412},[402,2638,2639],{"class":404,"line":505},[402,2640,496],{"class":412},[393,2642,2644],{"className":1010,"code":2643,"filename":1012,"language":1013,"meta":398,"style":398},"ConfigDirectorClient client = new ConfigDirectorClient(\n    getApplicationContext(),\n    \"YOUR-CLIENT-SDK-KEY\",\n    ClientOptions.builder()\n        .connection(\n            ConnectionOptions.builder()\n                .mode(ConnectionMode.POLLING)\n                .pollingIntervalMillis(600_000L)\n                .timeoutMillis(2_000L)\n                .build())\n        .build());\n",[272,2645,2646,2660,2666,2676,2686,2694,2705,2723,2735,2747,2756],{"__ignoreMap":398},[402,2647,2648,2650,2652,2654,2656,2658],{"class":404,"line":405},[402,2649,1033],{"class":1023},[402,2651,970],{"class":412},[402,2653,472],{"class":471},[402,2655,1060],{"class":1059},[402,2657,975],{"class":408},[402,2659,1578],{"class":576},[402,2661,2662,2664],{"class":404,"line":416},[402,2663,1848],{"class":408},[402,2665,1609],{"class":576},[402,2667,2668,2670,2672,2674],{"class":404,"line":424},[402,2669,1855],{"class":606},[402,2671,1075],{"class":475},[402,2673,841],{"class":606},[402,2675,1789],{"class":576},[402,2677,2678,2680,2682,2684],{"class":404,"line":433},[402,2679,1866],{"class":412},[402,2681,850],{"class":576},[402,2683,1588],{"class":408},[402,2685,430],{"class":576},[402,2687,2688,2690,2692],{"class":404,"line":441},[402,2689,1877],{"class":576},[402,2691,2408],{"class":408},[402,2693,1578],{"class":576},[402,2695,2696,2699,2701,2703],{"class":404,"line":449},[402,2697,2698],{"class":412},"            ConnectionOptions",[402,2700,850],{"class":576},[402,2702,1588],{"class":408},[402,2704,430],{"class":576},[402,2706,2707,2710,2712,2714,2717,2719,2721],{"class":404,"line":457},[402,2708,2709],{"class":576},"                .",[402,2711,2424],{"class":408},[402,2713,490],{"class":576},[402,2715,2716],{"class":412},"ConnectionMode",[402,2718,850],{"class":576},[402,2720,2443],{"class":412},[402,2722,496],{"class":576},[402,2724,2725,2727,2729,2731,2733],{"class":404,"line":465},[402,2726,2709],{"class":576},[402,2728,2459],{"class":408},[402,2730,490],{"class":576},[402,2732,2614],{"class":2613},[402,2734,496],{"class":576},[402,2736,2737,2739,2741,2743,2745],{"class":404,"line":479},[402,2738,2709],{"class":576},[402,2740,2492],{"class":408},[402,2742,490],{"class":576},[402,2744,2626],{"class":2613},[402,2746,496],{"class":576},[402,2748,2749,2751,2753],{"class":404,"line":499},[402,2750,2709],{"class":576},[402,2752,1370],{"class":408},[402,2754,2755],{"class":576},"())\n",[402,2757,2758,2760,2762],{"class":404,"line":505},[402,2759,1877],{"class":576},[402,2761,1370],{"class":408},[402,2763,1917],{"class":576},[265,2765,2766,2767,2769],{},"Settings are checked as they are built, so an unusable one throws a ",[272,2768,1183],{}," where it was written rather than becoming a client that quietly never updates.",[1716,2771,2773],{"id":2772},"events","Events",[265,2775,2776,2777,2780,2781,2784,2785,2788,2789,384,2792,2795],{},"Events notify you of some key actions from the client. ",[272,2778,2779],{},"addEventListener"," registers a listener for the client's lifecycle changes, and ",[272,2782,2783],{},"addEvaluationListener"," registers one for every individual config evaluation. Both are called on the main thread, and both return a ",[272,2786,2787],{},"Subscription"," you close to stop listening. Kotlin callers have the same two as flows, ",[272,2790,2791],{},"client.events",[272,2793,2794],{},"client.evaluations","; each collection is independent, so several parts of your app can observe them at once, and every flow completes when the client is closed.",[390,2797,2798,2970],{},[393,2799,2801],{"className":395,"code":2800,"filename":938,"language":397,"meta":398,"style":398},"import com.configdirector.ClientEvent\nimport com.configdirector.events\n\nlifecycleScope.launch {\n    client.events.collect { event ->\n        when (event) {\n            is ClientEvent.Ready -> Log.i(\"MyApp\", \"Client is ready after ${event.reason}\")\n            is ClientEvent.ConfigsUpdated -> Log.i(\"MyApp\", \"Configs updated: ${event.keys}\")\n            is ClientEvent.ContextUpdated -> Log.i(\"MyApp\", \"Context updated: ${event.context?.id}\")\n        }\n    }\n}\n",[272,2802,2803,2810,2817,2821,2830,2844,2852,2892,2925,2958,2962,2966],{"__ignoreMap":398},[402,2804,2805,2807],{"class":404,"line":405},[402,2806,945],{"class":471},[402,2808,2809],{"class":786}," com.configdirector.ClientEvent\n",[402,2811,2812,2814],{"class":404,"line":416},[402,2813,945],{"class":471},[402,2815,2816],{"class":786}," com.configdirector.events\n",[402,2818,2819],{"class":404,"line":424},[402,2820,703],{"emptyLinePlaceholder":54},[402,2822,2823,2826,2828],{"class":404,"line":433},[402,2824,2825],{"class":412},"lifecycleScope.",[402,2827,1354],{"class":408},[402,2829,413],{"class":412},[402,2831,2832,2835,2838,2841],{"class":404,"line":441},[402,2833,2834],{"class":412},"    client.events.",[402,2836,2837],{"class":408},"collect",[402,2839,2840],{"class":412}," { event ",[402,2842,2843],{"class":1117},"->\n",[402,2845,2846,2849],{"class":404,"line":449},[402,2847,2848],{"class":1059},"        when",[402,2850,2851],{"class":412}," (event) {\n",[402,2853,2854,2857,2860,2863,2866,2868,2870,2873,2875,2878,2881,2885,2888,2890],{"class":404,"line":457},[402,2855,2856],{"class":471},"            is",[402,2858,2859],{"class":412}," ClientEvent.Ready ",[402,2861,2862],{"class":1117},"->",[402,2864,2865],{"class":412}," Log.",[402,2867,1126],{"class":408},[402,2869,490],{"class":412},[402,2871,2872],{"class":475},"\"MyApp\"",[402,2874,1335],{"class":412},[402,2876,2877],{"class":475},"\"Client is ready after ",[402,2879,2880],{"class":606},"${",[402,2882,2884],{"class":2883},"sfo-9","event.reason",[402,2886,2887],{"class":606},"}",[402,2889,841],{"class":475},[402,2891,496],{"class":412},[402,2893,2894,2896,2899,2901,2903,2905,2907,2909,2911,2914,2916,2919,2921,2923],{"class":404,"line":465},[402,2895,2856],{"class":471},[402,2897,2898],{"class":412}," ClientEvent.ConfigsUpdated ",[402,2900,2862],{"class":1117},[402,2902,2865],{"class":412},[402,2904,1126],{"class":408},[402,2906,490],{"class":412},[402,2908,2872],{"class":475},[402,2910,1335],{"class":412},[402,2912,2913],{"class":475},"\"Configs updated: ",[402,2915,2880],{"class":606},[402,2917,2918],{"class":2883},"event.keys",[402,2920,2887],{"class":606},[402,2922,841],{"class":475},[402,2924,496],{"class":412},[402,2926,2927,2929,2932,2934,2936,2938,2940,2942,2944,2947,2949,2952,2954,2956],{"class":404,"line":479},[402,2928,2856],{"class":471},[402,2930,2931],{"class":412}," ClientEvent.ContextUpdated ",[402,2933,2862],{"class":1117},[402,2935,2865],{"class":412},[402,2937,1126],{"class":408},[402,2939,490],{"class":412},[402,2941,2872],{"class":475},[402,2943,1335],{"class":412},[402,2945,2946],{"class":475},"\"Context updated: ",[402,2948,2880],{"class":606},[402,2950,2951],{"class":2883},"event.context?.id",[402,2953,2887],{"class":606},[402,2955,841],{"class":475},[402,2957,496],{"class":412},[402,2959,2960],{"class":404,"line":499},[402,2961,540],{"class":412},[402,2963,2964],{"class":404,"line":505},[402,2965,546],{"class":412},[402,2967,2968],{"class":404,"line":511},[402,2969,552],{"class":412},[393,2971,2973],{"className":1010,"code":2972,"filename":1012,"language":1013,"meta":398,"style":398},"import com.configdirector.ClientEvent;\nimport com.configdirector.Subscription;\n\nSubscription subscription = client.addEventListener(event -> {\n  if (event instanceof ClientEvent.Ready) {\n    Log.i(\"MyApp\", \"Client is ready after \" + ((ClientEvent.Ready) event).getReason());\n  } else if (event instanceof ClientEvent.ConfigsUpdated) {\n    Log.i(\"MyApp\", \"Configs updated: \" + ((ClientEvent.ConfigsUpdated) event).getKeys());\n  }\n});\n\n\u002F\u002F Close the subscription to stop listening\nsubscription.close();\n",[272,2974,2975,2992,3008,3012,3036,3061,3110,3138,3184,3188,3193,3197,3202],{"__ignoreMap":398},[402,2976,2977,2979,2981,2983,2985,2987,2990],{"class":404,"line":405},[402,2978,945],{"class":1020},[402,2980,1024],{"class":1023},[402,2982,850],{"class":576},[402,2984,860],{"class":1023},[402,2986,850],{"class":576},[402,2988,2989],{"class":1023},"ClientEvent",[402,2991,1036],{"class":576},[402,2993,2994,2996,2998,3000,3002,3004,3006],{"class":404,"line":416},[402,2995,945],{"class":1020},[402,2997,1024],{"class":1023},[402,2999,850],{"class":576},[402,3001,860],{"class":1023},[402,3003,850],{"class":576},[402,3005,2787],{"class":1023},[402,3007,1036],{"class":576},[402,3009,3010],{"class":404,"line":424},[402,3011,703],{"emptyLinePlaceholder":54},[402,3013,3014,3016,3019,3021,3023,3025,3027,3029,3032,3034],{"class":404,"line":433},[402,3015,2787],{"class":1023},[402,3017,3018],{"class":412}," subscription ",[402,3020,472],{"class":471},[402,3022,1150],{"class":412},[402,3024,850],{"class":576},[402,3026,2779],{"class":408},[402,3028,490],{"class":576},[402,3030,3031],{"class":412},"event ",[402,3033,2862],{"class":1117},[402,3035,413],{"class":576},[402,3037,3038,3041,3044,3046,3049,3052,3054,3057,3059],{"class":404,"line":441},[402,3039,3040],{"class":1059},"  if",[402,3042,3043],{"class":576}," (",[402,3045,3031],{"class":412},[402,3047,3048],{"class":471},"instanceof",[402,3050,3051],{"class":412}," ClientEvent",[402,3053,850],{"class":576},[402,3055,3056],{"class":412},"Ready",[402,3058,2390],{"class":576},[402,3060,413],{"class":576},[402,3062,3063,3066,3068,3070,3072,3074,3076,3078,3080,3082,3085,3087,3089,3092,3094,3096,3098,3100,3103,3105,3108],{"class":404,"line":449},[402,3064,3065],{"class":412},"    Log",[402,3067,850],{"class":576},[402,3069,1126],{"class":408},[402,3071,490],{"class":576},[402,3073,841],{"class":606},[402,3075,1133],{"class":475},[402,3077,841],{"class":606},[402,3079,844],{"class":576},[402,3081,800],{"class":606},[402,3083,3084],{"class":475},"Client is ready after ",[402,3086,841],{"class":606},[402,3088,1147],{"class":471},[402,3090,3091],{"class":576}," ((",[402,3093,2989],{"class":412},[402,3095,850],{"class":576},[402,3097,3056],{"class":412},[402,3099,2390],{"class":576},[402,3101,3102],{"class":412}," event",[402,3104,1604],{"class":576},[402,3106,3107],{"class":408},"getReason",[402,3109,1917],{"class":576},[402,3111,3112,3115,3118,3121,3123,3125,3127,3129,3131,3134,3136],{"class":404,"line":457},[402,3113,3114],{"class":576},"  }",[402,3116,3117],{"class":1059}," else",[402,3119,3120],{"class":1059}," if",[402,3122,3043],{"class":576},[402,3124,3031],{"class":412},[402,3126,3048],{"class":471},[402,3128,3051],{"class":412},[402,3130,850],{"class":576},[402,3132,3133],{"class":412},"ConfigsUpdated",[402,3135,2390],{"class":576},[402,3137,413],{"class":576},[402,3139,3140,3142,3144,3146,3148,3150,3152,3154,3156,3158,3161,3163,3165,3167,3169,3171,3173,3175,3177,3179,3182],{"class":404,"line":465},[402,3141,3065],{"class":412},[402,3143,850],{"class":576},[402,3145,1126],{"class":408},[402,3147,490],{"class":576},[402,3149,841],{"class":606},[402,3151,1133],{"class":475},[402,3153,841],{"class":606},[402,3155,844],{"class":576},[402,3157,800],{"class":606},[402,3159,3160],{"class":475},"Configs updated: ",[402,3162,841],{"class":606},[402,3164,1147],{"class":471},[402,3166,3091],{"class":576},[402,3168,2989],{"class":412},[402,3170,850],{"class":576},[402,3172,3133],{"class":412},[402,3174,2390],{"class":576},[402,3176,3102],{"class":412},[402,3178,1604],{"class":576},[402,3180,3181],{"class":408},"getKeys",[402,3183,1917],{"class":576},[402,3185,3186],{"class":404,"line":479},[402,3187,1653],{"class":576},[402,3189,3190],{"class":404,"line":499},[402,3191,3192],{"class":576},"});\n",[402,3194,3195],{"class":404,"line":505},[402,3196,703],{"emptyLinePlaceholder":54},[402,3198,3199],{"class":404,"line":511},[402,3200,3201],{"class":708},"\u002F\u002F Close the subscription to stop listening\n",[402,3203,3204,3207,3209,3212],{"class":404,"line":519},[402,3205,3206],{"class":412},"subscription",[402,3208,850],{"class":576},[402,3210,3211],{"class":408},"close",[402,3213,1533],{"class":576},[265,3215,3216],{},"The following events are published to an event listener:",[2418,3218,3219,3251,3279],{},[923,3220,3221,3226],{},[272,3222,3225],{"className":3223},[3224],"font-semibold","ClientEvent.Ready",[2418,3227,3228,3231],{},[923,3229,3230],{},"Emitted when the client is initialized, or after reconnection due to a context update or a resumed network connection. When this event is emitted it means the client has received a payload from the ConfigDirector servers and is ready to evaluate configs.",[923,3232,3233,3236,3237,3240,3241,1335,3244,3247,3248,850],{},[272,3234,3235],{},"reason"," - A ",[272,3238,3239],{},"ConnectReason",", the action that triggered the client to connect\u002Freconnect, which can be ",[272,3242,3243],{},"ConnectReason.INITIALIZATION",[272,3245,3246],{},"ConnectReason.CONTEXT_UPDATE",", or ",[272,3249,3250],{},"ConnectReason.NETWORK_RESUME",[923,3252,3253,3257],{},[272,3254,3256],{"className":3255},[3224],"ClientEvent.ConfigsUpdated",[2418,3258,3259,3262,3271],{},[923,3260,3261],{},"Emitted when a payload is received from the ConfigDirector servers with config data. It is emitted during initialization or context update when an entire config payload is received. After initialization or context update, it is emitted when updates are pushed from the server (or discovered via polling if that connection mode is used).",[923,3263,3264,3236,3267,3270],{},[272,3265,3266],{},"keys",[272,3268,3269],{},"List\u003CString>"," listing the config keys that were included in the payload from the server. On a delta update, these are only the configs that changed.",[923,3272,3273,3236,3276,3278],{},[272,3274,3275],{},"removedKeys",[272,3277,3269],{}," listing the keys of configs the payload removed. A config is removed when a full payload no longer includes it. Empty when nothing was removed, and always empty on a delta update.",[923,3280,3281,3285],{},[272,3282,3284],{"className":3283},[3224],"ClientEvent.ContextUpdated",[2418,3286,3287,3293],{},[923,3288,3289,3290,3292],{},"Emitted whenever the user context takes effect, including during initialization. It is emitted before ",[272,3291,3225],{},", therefore should not be relied upon as a lifecycle event but rather as an informational event to track updates to the user context.",[923,3294,3295,3298,3299,3301,3302,850],{},[272,3296,3297],{},"context"," - The ",[272,3300,1454],{}," the client is now evaluating against. It can be ",[272,3303,1109],{},[265,3305,3306,3307,3310,3311,3313],{},"An evaluation listener is handed a ",[272,3308,3309],{},"ConfigEvaluation"," every time a config is evaluated, which can be useful for debugging what a screen actually read, and for capturing additional context for analytics events. This includes every read through a getter and every re-evaluation a watch makes. A ",[272,3312,3309],{}," carries:",[2418,3315,3316,3322,3340,3353,3359,3365],{},[923,3317,3318,3321],{},[272,3319,3320],{},"key: String"," - The config key that was evaluated.",[923,3323,3324,3327,3328,1335,3331,1335,3333,376,3336,3339],{},[272,3325,3326],{},"value: Any"," - The value the config evaluated to. It can be the default value provided by the caller, for example if the config was evaluated before the client was initialized. It is a ",[272,3329,3330],{},"Boolean",[272,3332,2169],{},[272,3334,3335],{},"Integer",[272,3337,3338],{},"Double",", matching the accessor the config was read with.",[923,3341,3342,3345,3346,3349,3350,3352],{},[272,3343,3344],{},"valueId: String?"," - The value ID, which is a stable hash of the value that can be used for analytics or other third parties rather than sending the ",[272,3347,3348],{},"value",". This can be useful for large values, like a JSON config, or to avoid disclosing the values themselves to third parties. It is ",[272,3351,1109],{}," if the evaluation had to fall back to the default value.",[923,3354,3355,3358],{},[272,3356,3357],{},"isDefaultValue: Boolean"," - Whether or not the evaluation fell back to the default value provided in code.",[923,3360,3361,3364],{},[272,3362,3363],{},"context: ConfigDirectorContext?"," - The context the config was evaluated against, if one was set.",[923,3366,3367,3370,3371,3374,3375,3377,3378],{},[272,3368,3369],{},"reason: EvaluationReason"," - The reason for the evaluation resolution. In the case the config successfully evaluated based on server-provided targeting rules, it will be ",[272,3372,3373],{},"FOUND_MATCH",". If the evaluation had to fall back to the default value, the ",[272,3376,3235],{}," will encode why the fallback was required:\n",[2418,3379,3380,3386,3392,3398,3404,3410,3416],{},[923,3381,3382,3385],{},[272,3383,3384],{},"CLIENT_NOT_READY"," - The evaluation happened before the client finished initialization.",[923,3387,3388,3391],{},[272,3389,3390],{},"CONFIG_STATE_MISSING"," - The requested config key was not present in the payload received from the server. This could be due to an incorrect config key, or a config that was not enabled to be available to client SDKs.",[923,3393,3394,3397],{},[272,3395,3396],{},"VALUE_MISSING"," - The config had no value for the current context.",[923,3399,3400,3403],{},[272,3401,3402],{},"INVALID_NUMBER"," - The config was requested as a number but the value received from the server could not be converted to a number.",[923,3405,3406,3409],{},[272,3407,3408],{},"INVALID_BOOLEAN"," - The config was requested as a boolean but the value received from the server could not be converted to a boolean.",[923,3411,3412,3415],{},[272,3413,3414],{},"INVALID_JSON"," - The config was requested as JSON but the value received from the server could not be read as a JSON document.",[923,3417,3418,3421],{},[272,3419,3420],{},"TYPE_MISMATCH"," - The config was requested with a data type that did not match the type of the config and no reasonable type conversion was possible.",[393,3423,3425],{"className":395,"code":3424,"filename":938,"language":397,"meta":398,"style":398},"import com.configdirector.evaluations\n\nlifecycleScope.launch {\n    client.evaluations\n        .filter { it.isDefaultValue }\n        .collect { Log.w(\"MyApp\", \"'${it.key}' fell back to its default: ${it.reason.wireName}\") }\n}\n",[272,3426,3427,3434,3438,3446,3451,3461,3504],{"__ignoreMap":398},[402,3428,3429,3431],{"class":404,"line":405},[402,3430,945],{"class":471},[402,3432,3433],{"class":786}," com.configdirector.evaluations\n",[402,3435,3436],{"class":404,"line":416},[402,3437,703],{"emptyLinePlaceholder":54},[402,3439,3440,3442,3444],{"class":404,"line":424},[402,3441,2825],{"class":412},[402,3443,1354],{"class":408},[402,3445,413],{"class":412},[402,3447,3448],{"class":404,"line":433},[402,3449,3450],{"class":412},"    client.evaluations\n",[402,3452,3453,3455,3458],{"class":404,"line":441},[402,3454,1877],{"class":412},[402,3456,3457],{"class":408},"filter",[402,3459,3460],{"class":412}," { it.isDefaultValue }\n",[402,3462,3463,3465,3467,3470,3473,3475,3477,3479,3482,3484,3487,3489,3492,3494,3497,3499,3501],{"class":404,"line":449},[402,3464,1877],{"class":412},[402,3466,2837],{"class":408},[402,3468,3469],{"class":412}," { Log.",[402,3471,3472],{"class":408},"w",[402,3474,490],{"class":412},[402,3476,2872],{"class":475},[402,3478,1335],{"class":412},[402,3480,3481],{"class":475},"\"'",[402,3483,2880],{"class":606},[402,3485,3486],{"class":2883},"it.key",[402,3488,2887],{"class":606},[402,3490,3491],{"class":475},"' fell back to its default: ",[402,3493,2880],{"class":606},[402,3495,3496],{"class":2883},"it.reason.wireName",[402,3498,2887],{"class":606},[402,3500,841],{"class":475},[402,3502,3503],{"class":412},") }\n",[402,3505,3506],{"class":404,"line":457},[402,3507,552],{"class":412},[3509,3510,3511,3512,3515],"warning",{},"Do not read a config from an evaluation listener, and do not drive state from ",[272,3513,3514],{},"evaluations"," that a composable reads a config from. The read publishes another evaluation, which recomposes, which reads the config again.",[260,3517,3519],{"id":3518},"retrieve-config-values","Retrieve config values",[265,3521,3522,3523,1335,3526,1335,3529,1335,3532,1335,3535,384,3538,3541,3542,3545],{},"To synchronously retrieve config values, use the client's typed getters: ",[272,3524,3525],{},"getBoolean",[272,3527,3528],{},"getString",[272,3530,3531],{},"getInt",[272,3533,3534],{},"getDouble",[272,3536,3537],{},"getJsonObject",[272,3539,3540],{},"getJsonArray",". Each requires two arguments. The first argument is the config key, and the second is the default value to be returned if the client has not yet received config values from ConfigDirector services. Kotlin callers also have ",[272,3543,3544],{},"client.value(key, default)",", which takes the type from the default value.",[265,3547,3548,3549,1335,3552,1335,3555,1335,3558,1335,3561,384,3564,3567,3568,3570,3571,3574,3575,3577],{},"You can also subscribe to config value changes via the matching watches: ",[272,3550,3551],{},"watchBoolean",[272,3553,3554],{},"watchString",[272,3556,3557],{},"watchInt",[272,3559,3560],{},"watchDouble",[272,3562,3563],{},"watchJsonObject",[272,3565,3566],{},"watchJsonArray",". Each takes the config key, the default value, and a listener that is handed the config's current value straight away and then every time the evaluated value changes, whether because it was edited in the ConfigDirector dashboard or because the context was updated. Consecutive identical values are not delivered again. When a full payload no longer includes the watched config, the listener is handed the default value, as a getter would now return it. Close the returned ",[272,3569,2787],{}," to stop watching. In Kotlin, ",[272,3572,3573],{},"client.values(key, default)"," is the same thing as a ",[272,3576,278],{},", and cancelling the collector stops watching.",[390,3579,3580,3718,3889],{},[393,3581,3584],{"className":395,"code":3582,"filename":3583,"language":397,"meta":398,"style":398},"import com.configdirector.value\nimport com.configdirector.values\n\n\u002F\u002F Retrieve the current value. The default value decides the type the config\n\u002F\u002F is read as, and is returned until the client is ready.\nval darkMode = client.value(\"my-config-key\", false)\n\n\u002F\u002F Subscribe to value updates. The flow emits the current value right away\n\u002F\u002F and then every time the evaluated value changes.\nlifecycleScope.launch {\n    client.values(\"my-config-key\", false).collect { darkMode ->\n        Log.i(\"MyApp\", \"Value updated: $darkMode\")\n    }\n}\n","MainActivity.kt",[272,3585,3586,3593,3600,3604,3609,3614,3640,3644,3649,3654,3662,3687,3710,3714],{"__ignoreMap":398},[402,3587,3588,3590],{"class":404,"line":405},[402,3589,945],{"class":471},[402,3591,3592],{"class":786}," com.configdirector.value\n",[402,3594,3595,3597],{"class":404,"line":416},[402,3596,945],{"class":471},[402,3598,3599],{"class":786}," com.configdirector.values\n",[402,3601,3602],{"class":404,"line":424},[402,3603,703],{"emptyLinePlaceholder":54},[402,3605,3606],{"class":404,"line":433},[402,3607,3608],{"class":708},"\u002F\u002F Retrieve the current value. The default value decides the type the config\n",[402,3610,3611],{"class":404,"line":441},[402,3612,3613],{"class":708},"\u002F\u002F is read as, and is returned until the client is ready.\n",[402,3615,3616,3618,3621,3623,3626,3628,3630,3633,3635,3638],{"class":404,"line":449},[402,3617,967],{"class":471},[402,3619,3620],{"class":412}," darkMode ",[402,3622,472],{"class":471},[402,3624,3625],{"class":412}," client.",[402,3627,3348],{"class":408},[402,3629,490],{"class":412},[402,3631,3632],{"class":475},"\"my-config-key\"",[402,3634,1335],{"class":412},[402,3636,2528],{"class":3637},"syTEX",[402,3639,496],{"class":412},[402,3641,3642],{"class":404,"line":457},[402,3643,703],{"emptyLinePlaceholder":54},[402,3645,3646],{"class":404,"line":465},[402,3647,3648],{"class":708},"\u002F\u002F Subscribe to value updates. The flow emits the current value right away\n",[402,3650,3651],{"class":404,"line":479},[402,3652,3653],{"class":708},"\u002F\u002F and then every time the evaluated value changes.\n",[402,3655,3656,3658,3660],{"class":404,"line":499},[402,3657,2825],{"class":412},[402,3659,1354],{"class":408},[402,3661,413],{"class":412},[402,3663,3664,3667,3670,3672,3674,3676,3678,3680,3682,3685],{"class":404,"line":505},[402,3665,3666],{"class":412},"    client.",[402,3668,3669],{"class":408},"values",[402,3671,490],{"class":412},[402,3673,3632],{"class":475},[402,3675,1335],{"class":412},[402,3677,2528],{"class":3637},[402,3679,1604],{"class":412},[402,3681,2837],{"class":408},[402,3683,3684],{"class":412}," { darkMode ",[402,3686,2843],{"class":1117},[402,3688,3689,3692,3694,3696,3698,3700,3703,3706,3708],{"class":404,"line":511},[402,3690,3691],{"class":412},"        Log.",[402,3693,1126],{"class":408},[402,3695,490],{"class":412},[402,3697,2872],{"class":475},[402,3699,1335],{"class":412},[402,3701,3702],{"class":475},"\"Value updated: ",[402,3704,3705],{"class":1525},"$darkMode",[402,3707,841],{"class":475},[402,3709,496],{"class":412},[402,3711,3712],{"class":404,"line":519},[402,3713,546],{"class":412},[402,3715,3716],{"class":404,"line":532},[402,3717,552],{"class":412},[393,3719,3722],{"className":1010,"code":3720,"filename":3721,"language":1013,"meta":398,"style":398},"import com.configdirector.Subscription;\n\n\u002F\u002F Retrieve the current value. There is a getter per type a config can be read\n\u002F\u002F as, and each returns the default value until the client is ready.\nboolean darkMode = client.getBoolean(\"my-config-key\", false);\n\n\u002F\u002F Subscribe to value updates. The listener is called on the main thread with the\n\u002F\u002F current value, and then every time the evaluated value changes.\nSubscription subscription = client.watchBoolean(\n    \"my-config-key\",\n    false,\n    value -> Log.i(\"MyApp\", \"Value updated: \" + value));\n\n\u002F\u002F Close the subscription to stop watching\nsubscription.close();\n","MainActivity.java",[272,3723,3724,3740,3744,3749,3754,3785,3789,3794,3799,3815,3825,3832,3870,3874,3879],{"__ignoreMap":398},[402,3725,3726,3728,3730,3732,3734,3736,3738],{"class":404,"line":405},[402,3727,945],{"class":1020},[402,3729,1024],{"class":1023},[402,3731,850],{"class":576},[402,3733,860],{"class":1023},[402,3735,850],{"class":576},[402,3737,2787],{"class":1023},[402,3739,1036],{"class":576},[402,3741,3742],{"class":404,"line":416},[402,3743,703],{"emptyLinePlaceholder":54},[402,3745,3746],{"class":404,"line":424},[402,3747,3748],{"class":708},"\u002F\u002F Retrieve the current value. There is a getter per type a config can be read\n",[402,3750,3751],{"class":404,"line":433},[402,3752,3753],{"class":708},"\u002F\u002F as, and each returns the default value until the client is ready.\n",[402,3755,3756,3759,3761,3763,3765,3767,3769,3771,3773,3776,3778,3780,3783],{"class":404,"line":441},[402,3757,3758],{"class":1117},"boolean",[402,3760,3620],{"class":412},[402,3762,472],{"class":471},[402,3764,1150],{"class":412},[402,3766,850],{"class":576},[402,3768,3525],{"class":408},[402,3770,490],{"class":576},[402,3772,841],{"class":606},[402,3774,3775],{"class":475},"my-config-key",[402,3777,841],{"class":606},[402,3779,844],{"class":576},[402,3781,3782],{"class":1108}," false",[402,3784,1080],{"class":576},[402,3786,3787],{"class":404,"line":449},[402,3788,703],{"emptyLinePlaceholder":54},[402,3790,3791],{"class":404,"line":457},[402,3792,3793],{"class":708},"\u002F\u002F Subscribe to value updates. The listener is called on the main thread with the\n",[402,3795,3796],{"class":404,"line":465},[402,3797,3798],{"class":708},"\u002F\u002F current value, and then every time the evaluated value changes.\n",[402,3800,3801,3803,3805,3807,3809,3811,3813],{"class":404,"line":479},[402,3802,2787],{"class":1023},[402,3804,3018],{"class":412},[402,3806,472],{"class":471},[402,3808,1150],{"class":412},[402,3810,850],{"class":576},[402,3812,3551],{"class":408},[402,3814,1578],{"class":576},[402,3816,3817,3819,3821,3823],{"class":404,"line":499},[402,3818,1855],{"class":606},[402,3820,3775],{"class":475},[402,3822,841],{"class":606},[402,3824,1789],{"class":576},[402,3826,3827,3830],{"class":404,"line":505},[402,3828,3829],{"class":1108},"    false",[402,3831,1789],{"class":576},[402,3833,3834,3837,3839,3841,3843,3845,3847,3849,3851,3853,3855,3857,3860,3862,3864,3867],{"class":404,"line":511},[402,3835,3836],{"class":412},"    value ",[402,3838,2862],{"class":1117},[402,3840,1121],{"class":412},[402,3842,850],{"class":576},[402,3844,1126],{"class":408},[402,3846,490],{"class":576},[402,3848,841],{"class":606},[402,3850,1133],{"class":475},[402,3852,841],{"class":606},[402,3854,844],{"class":576},[402,3856,800],{"class":606},[402,3858,3859],{"class":475},"Value updated: ",[402,3861,841],{"class":606},[402,3863,1147],{"class":471},[402,3865,3866],{"class":412}," value",[402,3868,3869],{"class":576},"));\n",[402,3871,3872],{"class":404,"line":519},[402,3873,703],{"emptyLinePlaceholder":54},[402,3875,3876],{"class":404,"line":532},[402,3877,3878],{"class":708},"\u002F\u002F Close the subscription to stop watching\n",[402,3880,3881,3883,3885,3887],{"class":404,"line":537},[402,3882,3206],{"class":412},[402,3884,850],{"class":576},[402,3886,3211],{"class":408},[402,3888,1533],{"class":576},[393,3890,3893],{"className":395,"code":3891,"filename":3892,"language":397,"meta":398,"style":398},"import com.configdirector.compose.configValue\n\n@Composable\nfun SampleScreen() {\n    \u002F\u002F Recomposes whenever the evaluated value changes.\n    val darkMode = configValue(\"my-config-key\", false)\n\n    Text(\"my-config-key: $darkMode\")\n}\n","SampleScreen.kt (Compose)",[272,3894,3895,3902,3906,3911,3921,3926,3948,3952,3968],{"__ignoreMap":398},[402,3896,3897,3899],{"class":404,"line":405},[402,3898,945],{"class":471},[402,3900,3901],{"class":786}," com.configdirector.compose.configValue\n",[402,3903,3904],{"class":404,"line":416},[402,3905,703],{"emptyLinePlaceholder":54},[402,3907,3908],{"class":404,"line":424},[402,3909,3910],{"class":786},"@Composable\n",[402,3912,3913,3916,3919],{"class":404,"line":433},[402,3914,3915],{"class":471},"fun",[402,3917,3918],{"class":408}," SampleScreen",[402,3920,1259],{"class":412},[402,3922,3923],{"class":404,"line":441},[402,3924,3925],{"class":708},"    \u002F\u002F Recomposes whenever the evaluated value changes.\n",[402,3927,3928,3931,3933,3935,3938,3940,3942,3944,3946],{"class":404,"line":449},[402,3929,3930],{"class":471},"    val",[402,3932,3620],{"class":412},[402,3934,472],{"class":471},[402,3936,3937],{"class":408}," configValue",[402,3939,490],{"class":412},[402,3941,3632],{"class":475},[402,3943,1335],{"class":412},[402,3945,2528],{"class":3637},[402,3947,496],{"class":412},[402,3949,3950],{"class":404,"line":457},[402,3951,703],{"emptyLinePlaceholder":54},[402,3953,3954,3957,3959,3962,3964,3966],{"class":404,"line":465},[402,3955,3956],{"class":408},"    Text",[402,3958,490],{"class":412},[402,3960,3961],{"class":475},"\"my-config-key: ",[402,3963,3705],{"class":1525},[402,3965,841],{"class":475},[402,3967,496],{"class":412},[402,3969,3970],{"class":404,"line":479},[402,3971,552],{"class":412},[265,3973,3974],{},"There is one getter and one watch per type a config can be read as, so a default value of any other type is a compile error rather than a failure at runtime. If the served value does not match the type it is read as, the SDK will attempt to convert it. If the conversion fails, it will return the default value. Mismatched types at runtime are captured by the telemetry collector and will surface as warnings in the ConfigDirector dashboard.",[393,3976,3978],{"className":395,"code":3977,"filename":3583,"language":397,"meta":398,"style":398},"client.getString(\"my-string-config-key\", \"Default\")\n\nclient.getInt(\"my-integer-config-key\", 100)\n\nclient.getDouble(\"my-decimal-config-key\", 1.5)\n\nclient.getBoolean(\"my-boolean-config-key\", false)\n",[272,3979,3980,3998,4002,4020,4024,4042,4046],{"__ignoreMap":398},[402,3981,3982,3984,3986,3988,3991,3993,3996],{"class":404,"line":405},[402,3983,1002],{"class":412},[402,3985,3528],{"class":408},[402,3987,490],{"class":412},[402,3989,3990],{"class":475},"\"my-string-config-key\"",[402,3992,1335],{"class":412},[402,3994,3995],{"class":475},"\"Default\"",[402,3997,496],{"class":412},[402,3999,4000],{"class":404,"line":416},[402,4001,703],{"emptyLinePlaceholder":54},[402,4003,4004,4006,4008,4010,4013,4015,4018],{"class":404,"line":424},[402,4005,1002],{"class":412},[402,4007,3531],{"class":408},[402,4009,490],{"class":412},[402,4011,4012],{"class":475},"\"my-integer-config-key\"",[402,4014,1335],{"class":412},[402,4016,4017],{"class":2613},"100",[402,4019,496],{"class":412},[402,4021,4022],{"class":404,"line":433},[402,4023,703],{"emptyLinePlaceholder":54},[402,4025,4026,4028,4030,4032,4035,4037,4040],{"class":404,"line":441},[402,4027,1002],{"class":412},[402,4029,3534],{"class":408},[402,4031,490],{"class":412},[402,4033,4034],{"class":475},"\"my-decimal-config-key\"",[402,4036,1335],{"class":412},[402,4038,4039],{"class":2613},"1.5",[402,4041,496],{"class":412},[402,4043,4044],{"class":404,"line":449},[402,4045,703],{"emptyLinePlaceholder":54},[402,4047,4048,4050,4052,4054,4057,4059,4061],{"class":404,"line":457},[402,4049,1002],{"class":412},[402,4051,3525],{"class":408},[402,4053,490],{"class":412},[402,4055,4056],{"class":475},"\"my-boolean-config-key\"",[402,4058,1335],{"class":412},[402,4060,2528],{"class":3637},[402,4062,496],{"class":412},[265,4064,4065,4066,4068,4069,4071],{},"A string, enum, URL, or custom config can be read as a string, and so can a JSON config, as its raw document. A boolean, integer, or float config read as a string evaluates to the default value with the ",[272,4067,3420],{}," reason. A value written as a decimal and read with ",[272,4070,3531],{}," is truncated.",[1716,4073,4075],{"id":4074},"json-configs","JSON configs",[265,4077,4078,4079,376,4081,4083,4084,1335,4086,1335,4089,1335,4091,1335,4094,4097],{},"A config declared as JSON in the ConfigDirector dashboard is read with ",[272,4080,3537],{},[272,4082,3540],{},", depending on the shape of its document. The values inside are ",[272,4085,2169],{},[272,4087,4088],{},"Number",[272,4090,3330],{},[272,4092,4093],{},"List",[272,4095,4096],{},"Map",", or null, and the document cannot be modified. Only a JSON config reads as one; read it as a string to get its raw document.",[390,4099,4100,4198],{},[393,4101,4103],{"className":395,"code":4102,"filename":3583,"language":397,"meta":398,"style":398},"val theme = client.getJsonObject(\"theme\", mapOf(\"primary\" to \"#101010\"))\nval primary = theme[\"primary\"] as? String\n\nval regions = client.getJsonArray(\"regions\", listOf(\"us-east\"))\n",[272,4104,4105,4141,4164,4168],{"__ignoreMap":398},[402,4106,4107,4109,4112,4114,4116,4118,4120,4123,4125,4128,4130,4133,4136,4139],{"class":404,"line":405},[402,4108,967],{"class":471},[402,4110,4111],{"class":412}," theme ",[402,4113,472],{"class":471},[402,4115,3625],{"class":412},[402,4117,3537],{"class":408},[402,4119,490],{"class":412},[402,4121,4122],{"class":475},"\"theme\"",[402,4124,1335],{"class":412},[402,4126,4127],{"class":408},"mapOf",[402,4129,490],{"class":412},[402,4131,4132],{"class":475},"\"primary\"",[402,4134,4135],{"class":412}," to ",[402,4137,4138],{"class":475},"\"#101010\"",[402,4140,1908],{"class":412},[402,4142,4143,4145,4148,4150,4153,4155,4158,4161],{"class":404,"line":416},[402,4144,967],{"class":471},[402,4146,4147],{"class":412}," primary ",[402,4149,472],{"class":471},[402,4151,4152],{"class":412}," theme[",[402,4154,4132],{"class":475},[402,4156,4157],{"class":412},"] ",[402,4159,4160],{"class":471},"as",[402,4162,4163],{"class":412},"? String\n",[402,4165,4166],{"class":404,"line":424},[402,4167,703],{"emptyLinePlaceholder":54},[402,4169,4170,4172,4175,4177,4179,4181,4183,4186,4188,4191,4193,4196],{"class":404,"line":433},[402,4171,967],{"class":471},[402,4173,4174],{"class":412}," regions ",[402,4176,472],{"class":471},[402,4178,3625],{"class":412},[402,4180,3540],{"class":408},[402,4182,490],{"class":412},[402,4184,4185],{"class":475},"\"regions\"",[402,4187,1335],{"class":412},[402,4189,4190],{"class":408},"listOf",[402,4192,490],{"class":412},[402,4194,4195],{"class":475},"\"us-east\"",[402,4197,1908],{"class":412},[393,4199,4201],{"className":1010,"code":4200,"filename":3721,"language":1013,"meta":398,"style":398},"Map\u003CString, Object> theme = client.getJsonObject(\"theme\", Map.of(\"primary\", \"#101010\"));\nString primary = (String) theme.get(\"primary\");\n\nList\u003CObject> regions = client.getJsonArray(\"regions\", List.of(\"us-east\"));\n",[272,4202,4203,4269,4301,4305],{"__ignoreMap":398},[402,4204,4205,4207,4210,4212,4214,4217,4220,4222,4224,4226,4228,4230,4232,4234,4237,4239,4241,4244,4246,4249,4251,4253,4256,4258,4260,4262,4265,4267],{"class":404,"line":405},[402,4206,4096],{"class":1023},[402,4208,4209],{"class":576},"\u003C",[402,4211,2169],{"class":1117},[402,4213,844],{"class":576},[402,4215,4216],{"class":1117}," Object",[402,4218,4219],{"class":576},">",[402,4221,4111],{"class":412},[402,4223,472],{"class":471},[402,4225,1150],{"class":412},[402,4227,850],{"class":576},[402,4229,3537],{"class":408},[402,4231,490],{"class":576},[402,4233,841],{"class":606},[402,4235,4236],{"class":475},"theme",[402,4238,841],{"class":606},[402,4240,844],{"class":576},[402,4242,4243],{"class":412}," Map",[402,4245,850],{"class":576},[402,4247,4248],{"class":408},"of",[402,4250,490],{"class":576},[402,4252,841],{"class":606},[402,4254,4255],{"class":475},"primary",[402,4257,841],{"class":606},[402,4259,844],{"class":576},[402,4261,800],{"class":606},[402,4263,4264],{"class":475},"#101010",[402,4266,841],{"class":606},[402,4268,3869],{"class":576},[402,4270,4271,4273,4275,4277,4279,4281,4283,4286,4288,4291,4293,4295,4297,4299],{"class":404,"line":416},[402,4272,2169],{"class":1023},[402,4274,4147],{"class":412},[402,4276,472],{"class":471},[402,4278,3043],{"class":576},[402,4280,2169],{"class":412},[402,4282,2390],{"class":576},[402,4284,4285],{"class":412}," theme",[402,4287,850],{"class":576},[402,4289,4290],{"class":408},"get",[402,4292,490],{"class":576},[402,4294,841],{"class":606},[402,4296,4255],{"class":475},[402,4298,841],{"class":606},[402,4300,1080],{"class":576},[402,4302,4303],{"class":404,"line":424},[402,4304,703],{"emptyLinePlaceholder":54},[402,4306,4307,4309,4311,4314,4316,4318,4320,4322,4324,4326,4328,4330,4333,4335,4337,4340,4342,4344,4346,4348,4351,4353],{"class":404,"line":433},[402,4308,4093],{"class":1023},[402,4310,4209],{"class":576},[402,4312,4313],{"class":1117},"Object",[402,4315,4219],{"class":576},[402,4317,4174],{"class":412},[402,4319,472],{"class":471},[402,4321,1150],{"class":412},[402,4323,850],{"class":576},[402,4325,3540],{"class":408},[402,4327,490],{"class":576},[402,4329,841],{"class":606},[402,4331,4332],{"class":475},"regions",[402,4334,841],{"class":606},[402,4336,844],{"class":576},[402,4338,4339],{"class":412}," List",[402,4341,850],{"class":576},[402,4343,4248],{"class":408},[402,4345,490],{"class":576},[402,4347,841],{"class":606},[402,4349,4350],{"class":475},"us-east",[402,4352,841],{"class":606},[402,4354,3869],{"class":576},[1716,4356,4358],{"id":4357},"reading-configs-in-jetpack-compose","Reading configs in Jetpack Compose",[265,4360,1743,4361,4364],{},[272,4362,4363],{},"android-sdk-compose"," artifact reads configs as Compose state, so a composable recomposes on its own whenever an evaluated value changes.",[265,4366,4367,4368,4371],{},"Wrap your content in a ",[272,4369,4370],{},"ConfigDirectorProvider"," and every binding below it reads from that client:",[393,4373,4375],{"className":395,"code":4374,"filename":3583,"language":397,"meta":398,"style":398},"import com.configdirector.compose.ConfigDirectorProvider\n\nclass MainActivity : ComponentActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        val client = (application as MyApplication).client\n        setContent {\n            ConfigDirectorProvider(client) {\n                MaterialTheme { HomeScreen() }\n            }\n        }\n    }\n}\n",[272,4376,4377,4384,4388,4402,4406,4422,4433,4437,4454,4461,4469,4482,4486,4490,4494],{"__ignoreMap":398},[402,4378,4379,4381],{"class":404,"line":405},[402,4380,945],{"class":471},[402,4382,4383],{"class":786}," com.configdirector.compose.ConfigDirectorProvider\n",[402,4385,4386],{"class":404,"line":416},[402,4387,703],{"emptyLinePlaceholder":54},[402,4389,4390,4392,4395,4397,4400],{"class":404,"line":424},[402,4391,1248],{"class":471},[402,4393,4394],{"class":786}," MainActivity",[402,4396,1254],{"class":412},[402,4398,4399],{"class":786},"ComponentActivity",[402,4401,1259],{"class":412},[402,4403,4404],{"class":404,"line":433},[402,4405,703],{"emptyLinePlaceholder":54},[402,4407,4408,4410,4412,4414,4417,4420],{"class":404,"line":441},[402,4409,1294],{"class":1117},[402,4411,1297],{"class":471},[402,4413,1300],{"class":408},[402,4415,4416],{"class":412},"(savedInstanceState: ",[402,4418,4419],{"class":786},"Bundle",[402,4421,2178],{"class":412},[402,4423,4424,4426,4428,4430],{"class":404,"line":449},[402,4425,1307],{"class":1108},[402,4427,850],{"class":412},[402,4429,1312],{"class":408},[402,4431,4432],{"class":412},"(savedInstanceState)\n",[402,4434,4435],{"class":404,"line":457},[402,4436,703],{"emptyLinePlaceholder":54},[402,4438,4439,4442,4444,4446,4449,4451],{"class":404,"line":465},[402,4440,4441],{"class":471},"        val",[402,4443,970],{"class":412},[402,4445,472],{"class":471},[402,4447,4448],{"class":412}," (application ",[402,4450,4160],{"class":471},[402,4452,4453],{"class":412}," MyApplication).client\n",[402,4455,4456,4459],{"class":404,"line":479},[402,4457,4458],{"class":408},"        setContent",[402,4460,413],{"class":412},[402,4462,4463,4466],{"class":404,"line":499},[402,4464,4465],{"class":408},"            ConfigDirectorProvider",[402,4467,4468],{"class":412},"(client) {\n",[402,4470,4471,4474,4476,4479],{"class":404,"line":505},[402,4472,4473],{"class":408},"                MaterialTheme",[402,4475,1373],{"class":412},[402,4477,4478],{"class":408},"HomeScreen",[402,4480,4481],{"class":412},"() }\n",[402,4483,4484],{"class":404,"line":511},[402,4485,508],{"class":412},[402,4487,4488],{"class":404,"line":519},[402,4489,540],{"class":412},[402,4491,4492],{"class":404,"line":532},[402,4493,546],{"class":412},[402,4495,4496],{"class":404,"line":537},[402,4497,552],{"class":412},[265,4499,4500,4503],{},[272,4501,4502],{},"configValue"," then reads a config anywhere inside it, with one overload per type a config can be read as. Until the client is ready, and for a value that cannot be read as the requested type, it is the default value:",[393,4505,4508],{"className":395,"code":4506,"filename":4507,"language":397,"meta":398,"style":398},"import com.configdirector.compose.configContext\nimport com.configdirector.compose.configValue\nimport com.configdirector.compose.isClientReady\n\n@Composable\nfun HomeScreen() {\n    val darkMode = configValue(\"dark-mode\", false)\n    val greeting = configValue(\"greeting\", \"Hello\")\n\n    \u002F\u002F Recomposes when config state arrives, which is useful to show a loading\n    \u002F\u002F state rather than flashing the in-code default value on a slow connection.\n    if (!isClientReady()) {\n        LoadingScreen()\n        return\n    }\n\n    Text(text = greeting, color = if (darkMode) Color.White else Color.Black)\n}\n","HomeScreen.kt",[272,4509,4510,4517,4523,4530,4534,4538,4547,4568,4591,4595,4600,4605,4621,4628,4633,4637,4641,4666],{"__ignoreMap":398},[402,4511,4512,4514],{"class":404,"line":405},[402,4513,945],{"class":471},[402,4515,4516],{"class":786}," com.configdirector.compose.configContext\n",[402,4518,4519,4521],{"class":404,"line":416},[402,4520,945],{"class":471},[402,4522,3901],{"class":786},[402,4524,4525,4527],{"class":404,"line":424},[402,4526,945],{"class":471},[402,4528,4529],{"class":786}," com.configdirector.compose.isClientReady\n",[402,4531,4532],{"class":404,"line":433},[402,4533,703],{"emptyLinePlaceholder":54},[402,4535,4536],{"class":404,"line":441},[402,4537,3910],{"class":786},[402,4539,4540,4542,4545],{"class":404,"line":449},[402,4541,3915],{"class":471},[402,4543,4544],{"class":408}," HomeScreen",[402,4546,1259],{"class":412},[402,4548,4549,4551,4553,4555,4557,4559,4562,4564,4566],{"class":404,"line":457},[402,4550,3930],{"class":471},[402,4552,3620],{"class":412},[402,4554,472],{"class":471},[402,4556,3937],{"class":408},[402,4558,490],{"class":412},[402,4560,4561],{"class":475},"\"dark-mode\"",[402,4563,1335],{"class":412},[402,4565,2528],{"class":3637},[402,4567,496],{"class":412},[402,4569,4570,4572,4575,4577,4579,4581,4584,4586,4589],{"class":404,"line":465},[402,4571,3930],{"class":471},[402,4573,4574],{"class":412}," greeting ",[402,4576,472],{"class":471},[402,4578,3937],{"class":408},[402,4580,490],{"class":412},[402,4582,4583],{"class":475},"\"greeting\"",[402,4585,1335],{"class":412},[402,4587,4588],{"class":475},"\"Hello\"",[402,4590,496],{"class":412},[402,4592,4593],{"class":404,"line":479},[402,4594,703],{"emptyLinePlaceholder":54},[402,4596,4597],{"class":404,"line":499},[402,4598,4599],{"class":708},"    \u002F\u002F Recomposes when config state arrives, which is useful to show a loading\n",[402,4601,4602],{"class":404,"line":505},[402,4603,4604],{"class":708},"    \u002F\u002F state rather than flashing the in-code default value on a slow connection.\n",[402,4606,4607,4610,4612,4615,4618],{"class":404,"line":511},[402,4608,4609],{"class":1059},"    if",[402,4611,3043],{"class":412},[402,4613,4614],{"class":471},"!",[402,4616,4617],{"class":408},"isClientReady",[402,4619,4620],{"class":412},"()) {\n",[402,4622,4623,4626],{"class":404,"line":519},[402,4624,4625],{"class":408},"        LoadingScreen",[402,4627,430],{"class":412},[402,4629,4630],{"class":404,"line":532},[402,4631,4632],{"class":1059},"        return\n",[402,4634,4635],{"class":404,"line":537},[402,4636,546],{"class":412},[402,4638,4639],{"class":404,"line":543},[402,4640,703],{"emptyLinePlaceholder":54},[402,4642,4643,4645,4648,4650,4653,4655,4657,4660,4663],{"class":404,"line":549},[402,4644,3956],{"class":408},[402,4646,4647],{"class":412},"(text ",[402,4649,472],{"class":471},[402,4651,4652],{"class":412}," greeting, color ",[402,4654,472],{"class":471},[402,4656,3120],{"class":1059},[402,4658,4659],{"class":412}," (darkMode) Color.White ",[402,4661,4662],{"class":1059},"else",[402,4664,4665],{"class":412}," Color.Black)\n",[402,4667,4668],{"class":404,"line":1359},[402,4669,552],{"class":412},[265,4671,4672,384,4675,4678],{},[272,4673,4674],{},"isClientReady()",[272,4676,4677],{},"configContext()"," expose the client's readiness and its current context as state, recomposing when either changes.",[1175,4680,4681,4682,4685],{},"Each binding takes the client from ",[272,4683,4684],{},"LocalConfigDirectorClient"," unless one is passed to it explicitly. Reading a binding with no provider above it in the tree fails rather than serving default values that look like real ones.",[1716,4687,4689],{"id":4688},"reading-configs-with-framework-views","Reading configs with framework views",[265,4691,4692],{},"With framework views, register a watch when the view is created and close its subscription when the view goes away:",[393,4694,4696],{"className":395,"code":4695,"filename":3583,"language":397,"meta":398,"style":398},"class MainActivity : AppCompatActivity() {\n\n    private var subscription: Subscription? = null\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        val client = (application as MyApplication).client\n        subscription = client.watchBoolean(\"dark-mode\", false) { darkMode ->\n            \u002F\u002F Called on the main thread with the current value, and on every change.\n            findViewById\u003CSwitch>(R.id.dark_mode).isChecked = darkMode\n        }\n    }\n\n    override fun onDestroy() {\n        subscription?.close()\n        super.onDestroy()\n    }\n}\n",[272,4697,4698,4711,4715,4735,4739,4753,4763,4767,4781,4805,4810,4828,4832,4836,4840,4851,4860,4871,4875],{"__ignoreMap":398},[402,4699,4700,4702,4704,4706,4709],{"class":404,"line":405},[402,4701,1248],{"class":471},[402,4703,4394],{"class":786},[402,4705,1254],{"class":412},[402,4707,4708],{"class":786},"AppCompatActivity",[402,4710,1259],{"class":412},[402,4712,4713],{"class":404,"line":416},[402,4714,703],{"emptyLinePlaceholder":54},[402,4716,4717,4720,4722,4725,4727,4730,4732],{"class":404,"line":424},[402,4718,4719],{"class":1117},"    private",[402,4721,1271],{"class":471},[402,4723,4724],{"class":412}," subscription: ",[402,4726,2787],{"class":786},[402,4728,4729],{"class":412},"? ",[402,4731,472],{"class":471},[402,4733,4734],{"class":1108}," null\n",[402,4736,4737],{"class":404,"line":433},[402,4738,703],{"emptyLinePlaceholder":54},[402,4740,4741,4743,4745,4747,4749,4751],{"class":404,"line":441},[402,4742,1294],{"class":1117},[402,4744,1297],{"class":471},[402,4746,1300],{"class":408},[402,4748,4416],{"class":412},[402,4750,4419],{"class":786},[402,4752,2178],{"class":412},[402,4754,4755,4757,4759,4761],{"class":404,"line":449},[402,4756,1307],{"class":1108},[402,4758,850],{"class":412},[402,4760,1312],{"class":408},[402,4762,4432],{"class":412},[402,4764,4765],{"class":404,"line":457},[402,4766,703],{"emptyLinePlaceholder":54},[402,4768,4769,4771,4773,4775,4777,4779],{"class":404,"line":465},[402,4770,4441],{"class":471},[402,4772,970],{"class":412},[402,4774,472],{"class":471},[402,4776,4448],{"class":412},[402,4778,4160],{"class":471},[402,4780,4453],{"class":412},[402,4782,4783,4786,4788,4790,4792,4794,4796,4798,4800,4803],{"class":404,"line":479},[402,4784,4785],{"class":412},"        subscription ",[402,4787,472],{"class":471},[402,4789,3625],{"class":412},[402,4791,3551],{"class":408},[402,4793,490],{"class":412},[402,4795,4561],{"class":475},[402,4797,1335],{"class":412},[402,4799,2528],{"class":3637},[402,4801,4802],{"class":412},") { darkMode ",[402,4804,2843],{"class":1117},[402,4806,4807],{"class":404,"line":499},[402,4808,4809],{"class":708},"            \u002F\u002F Called on the main thread with the current value, and on every change.\n",[402,4811,4812,4815,4817,4820,4823,4825],{"class":404,"line":505},[402,4813,4814],{"class":408},"            findViewById",[402,4816,4209],{"class":412},[402,4818,4819],{"class":786},"Switch",[402,4821,4822],{"class":412},">(R.id.dark_mode).isChecked ",[402,4824,472],{"class":471},[402,4826,4827],{"class":412}," darkMode\n",[402,4829,4830],{"class":404,"line":511},[402,4831,540],{"class":412},[402,4833,4834],{"class":404,"line":519},[402,4835,546],{"class":412},[402,4837,4838],{"class":404,"line":532},[402,4839,703],{"emptyLinePlaceholder":54},[402,4841,4842,4844,4846,4849],{"class":404,"line":537},[402,4843,1294],{"class":1117},[402,4845,1297],{"class":471},[402,4847,4848],{"class":408}," onDestroy",[402,4850,1259],{"class":412},[402,4852,4853,4856,4858],{"class":404,"line":543},[402,4854,4855],{"class":412},"        subscription?.",[402,4857,3211],{"class":408},[402,4859,430],{"class":412},[402,4861,4862,4864,4866,4869],{"class":404,"line":549},[402,4863,1307],{"class":1108},[402,4865,850],{"class":412},[402,4867,4868],{"class":408},"onDestroy",[402,4870,430],{"class":412},[402,4872,4873],{"class":404,"line":1359},[402,4874,546],{"class":412},[402,4876,4877],{"class":404,"line":1387},[402,4878,552],{"class":412},[260,4880,4882],{"id":4881},"update-the-user-context","Update the user context",[265,4884,4885],{},"A user context can be provided when initializing the client:",[390,4887,4888,5000],{},[393,4889,4891],{"className":395,"code":4890,"filename":938,"language":397,"meta":398,"style":398},"import com.configdirector.ConfigDirectorClient\nimport com.configdirector.ConfigDirectorContext\n\nval client = ConfigDirectorClient(applicationContext, \"YOUR-CLIENT-SDK-KEY\")\n\nclient.initialize(\n    ConfigDirectorContext.build {\n        id(\"12345\")\n        name(\"Example User\")\n        \u002F\u002F Any arbitrary traits which can be referenced in targeting rules\n        trait(\"region\", \"North America\")\n    },\n)\n",[272,4892,4893,4899,4905,4909,4925,4929,4937,4946,4958,4970,4975,4992,4996],{"__ignoreMap":398},[402,4894,4895,4897],{"class":404,"line":405},[402,4896,945],{"class":471},[402,4898,948],{"class":786},[402,4900,4901,4903],{"class":404,"line":416},[402,4902,945],{"class":471},[402,4904,1225],{"class":786},[402,4906,4907],{"class":404,"line":424},[402,4908,703],{"emptyLinePlaceholder":54},[402,4910,4911,4913,4915,4917,4919,4921,4923],{"class":404,"line":433},[402,4912,967],{"class":471},[402,4914,970],{"class":412},[402,4916,472],{"class":471},[402,4918,975],{"class":408},[402,4920,978],{"class":412},[402,4922,981],{"class":475},[402,4924,496],{"class":412},[402,4926,4927],{"class":404,"line":441},[402,4928,703],{"emptyLinePlaceholder":54},[402,4930,4931,4933,4935],{"class":404,"line":449},[402,4932,1002],{"class":412},[402,4934,1005],{"class":408},[402,4936,1578],{"class":412},[402,4938,4939,4942,4944],{"class":404,"line":457},[402,4940,4941],{"class":412},"    ConfigDirectorContext.",[402,4943,1370],{"class":408},[402,4945,413],{"class":412},[402,4947,4948,4951,4953,4956],{"class":404,"line":465},[402,4949,4950],{"class":408},"        id",[402,4952,490],{"class":412},[402,4954,4955],{"class":475},"\"12345\"",[402,4957,496],{"class":412},[402,4959,4960,4963,4965,4968],{"class":404,"line":479},[402,4961,4962],{"class":408},"        name",[402,4964,490],{"class":412},[402,4966,4967],{"class":475},"\"Example User\"",[402,4969,496],{"class":412},[402,4971,4972],{"class":404,"line":499},[402,4973,4974],{"class":708},"        \u002F\u002F Any arbitrary traits which can be referenced in targeting rules\n",[402,4976,4977,4980,4982,4985,4987,4990],{"class":404,"line":505},[402,4978,4979],{"class":408},"        trait",[402,4981,490],{"class":412},[402,4983,4984],{"class":475},"\"region\"",[402,4986,1335],{"class":412},[402,4988,4989],{"class":475},"\"North America\"",[402,4991,496],{"class":412},[402,4993,4994],{"class":404,"line":511},[402,4995,1820],{"class":412},[402,4997,4998],{"class":404,"line":519},[402,4999,496],{"class":412},[393,5001,5003],{"className":1010,"code":5002,"filename":1012,"language":1013,"meta":398,"style":398},"import com.configdirector.ConfigDirectorClient;\nimport com.configdirector.ConfigDirectorContext;\n\nConfigDirectorClient client = new ConfigDirectorClient(getApplicationContext(), \"YOUR-CLIENT-SDK-KEY\");\n\nConfigDirectorContext context = ConfigDirectorContext.builder()\n    .id(\"12345\")\n    .name(\"Example User\")\n    \u002F\u002F Any arbitrary traits which can be referenced in targeting rules\n    .trait(\"region\", \"North America\")\n    .build();\n\nclient.initialize(context, () -> Log.i(\"MyApp\", \"ConfigDirector ready: \" + client.isReady()));\n",[272,5004,5005,5021,5037,5041,5067,5071,5089,5107,5125,5130,5157,5165,5169],{"__ignoreMap":398},[402,5006,5007,5009,5011,5013,5015,5017,5019],{"class":404,"line":405},[402,5008,945],{"class":1020},[402,5010,1024],{"class":1023},[402,5012,850],{"class":576},[402,5014,860],{"class":1023},[402,5016,850],{"class":576},[402,5018,1033],{"class":1023},[402,5020,1036],{"class":576},[402,5022,5023,5025,5027,5029,5031,5033,5035],{"class":404,"line":416},[402,5024,945],{"class":1020},[402,5026,1024],{"class":1023},[402,5028,850],{"class":576},[402,5030,860],{"class":1023},[402,5032,850],{"class":576},[402,5034,1454],{"class":1023},[402,5036,1036],{"class":576},[402,5038,5039],{"class":404,"line":424},[402,5040,703],{"emptyLinePlaceholder":54},[402,5042,5043,5045,5047,5049,5051,5053,5055,5057,5059,5061,5063,5065],{"class":404,"line":433},[402,5044,1033],{"class":1023},[402,5046,970],{"class":412},[402,5048,472],{"class":471},[402,5050,1060],{"class":1059},[402,5052,975],{"class":408},[402,5054,490],{"class":576},[402,5056,1067],{"class":408},[402,5058,1070],{"class":576},[402,5060,800],{"class":606},[402,5062,1075],{"class":475},[402,5064,841],{"class":606},[402,5066,1080],{"class":576},[402,5068,5069],{"class":404,"line":441},[402,5070,703],{"emptyLinePlaceholder":54},[402,5072,5073,5075,5078,5080,5083,5085,5087],{"class":404,"line":449},[402,5074,1454],{"class":1023},[402,5076,5077],{"class":412}," context ",[402,5079,472],{"class":471},[402,5081,5082],{"class":412}," ConfigDirectorContext",[402,5084,850],{"class":576},[402,5086,1588],{"class":408},[402,5088,430],{"class":576},[402,5090,5091,5094,5096,5098,5100,5103,5105],{"class":404,"line":457},[402,5092,5093],{"class":576},"    .",[402,5095,1376],{"class":408},[402,5097,490],{"class":576},[402,5099,841],{"class":606},[402,5101,5102],{"class":475},"12345",[402,5104,841],{"class":606},[402,5106,496],{"class":576},[402,5108,5109,5111,5114,5116,5118,5121,5123],{"class":404,"line":465},[402,5110,5093],{"class":576},[402,5112,5113],{"class":408},"name",[402,5115,490],{"class":576},[402,5117,841],{"class":606},[402,5119,5120],{"class":475},"Example User",[402,5122,841],{"class":606},[402,5124,496],{"class":576},[402,5126,5127],{"class":404,"line":479},[402,5128,5129],{"class":708},"    \u002F\u002F Any arbitrary traits which can be referenced in targeting rules\n",[402,5131,5132,5134,5137,5139,5141,5144,5146,5148,5150,5153,5155],{"class":404,"line":499},[402,5133,5093],{"class":576},[402,5135,5136],{"class":408},"trait",[402,5138,490],{"class":576},[402,5140,841],{"class":606},[402,5142,5143],{"class":475},"region",[402,5145,841],{"class":606},[402,5147,844],{"class":576},[402,5149,800],{"class":606},[402,5151,5152],{"class":475},"North America",[402,5154,841],{"class":606},[402,5156,496],{"class":576},[402,5158,5159,5161,5163],{"class":404,"line":505},[402,5160,5093],{"class":576},[402,5162,1370],{"class":408},[402,5164,1533],{"class":576},[402,5166,5167],{"class":404,"line":511},[402,5168,703],{"emptyLinePlaceholder":54},[402,5170,5171,5173,5175,5177,5179,5181,5183,5185,5187,5189,5191,5193,5195,5197,5199,5201,5203,5205,5207,5209,5211,5213,5215,5217],{"class":404,"line":519},[402,5172,1099],{"class":412},[402,5174,850],{"class":576},[402,5176,1005],{"class":408},[402,5178,490],{"class":576},[402,5180,3297],{"class":412},[402,5182,844],{"class":576},[402,5184,1114],{"class":576},[402,5186,1118],{"class":1117},[402,5188,1121],{"class":412},[402,5190,850],{"class":576},[402,5192,1126],{"class":408},[402,5194,490],{"class":576},[402,5196,841],{"class":606},[402,5198,1133],{"class":475},[402,5200,841],{"class":606},[402,5202,844],{"class":576},[402,5204,800],{"class":606},[402,5206,1142],{"class":475},[402,5208,841],{"class":606},[402,5210,1147],{"class":471},[402,5212,1150],{"class":412},[402,5214,850],{"class":576},[402,5216,1155],{"class":408},[402,5218,1158],{"class":576},[265,5220,5221,5222,388],{},"The user context can also be updated via ",[272,5223,5224],{},"updateContext",[390,5226,5227,5338],{},[393,5228,5230],{"className":395,"code":5229,"filename":3583,"language":397,"meta":398,"style":398},"import com.configdirector.ConfigDirectorContext\n\nclient.updateContext(\n    ConfigDirectorContext.build {\n        id(\"654321\")\n        name(\"Another User\")\n        trait(\"region\", \"Australia\")\n    },\n)\n\n\u002F\u002F Update it to an anonymous context when a user signs out. Leaving `id` unset\n\u002F\u002F makes the server derive a stable identifier from this SDK instance.\nclient.updateContext(ConfigDirectorContext.build { anonymous(true) })\n",[272,5231,5232,5238,5242,5250,5258,5269,5280,5295,5299,5303,5307,5312,5317],{"__ignoreMap":398},[402,5233,5234,5236],{"class":404,"line":405},[402,5235,945],{"class":471},[402,5237,1225],{"class":786},[402,5239,5240],{"class":404,"line":416},[402,5241,703],{"emptyLinePlaceholder":54},[402,5243,5244,5246,5248],{"class":404,"line":424},[402,5245,1002],{"class":412},[402,5247,5224],{"class":408},[402,5249,1578],{"class":412},[402,5251,5252,5254,5256],{"class":404,"line":433},[402,5253,4941],{"class":412},[402,5255,1370],{"class":408},[402,5257,413],{"class":412},[402,5259,5260,5262,5264,5267],{"class":404,"line":441},[402,5261,4950],{"class":408},[402,5263,490],{"class":412},[402,5265,5266],{"class":475},"\"654321\"",[402,5268,496],{"class":412},[402,5270,5271,5273,5275,5278],{"class":404,"line":449},[402,5272,4962],{"class":408},[402,5274,490],{"class":412},[402,5276,5277],{"class":475},"\"Another User\"",[402,5279,496],{"class":412},[402,5281,5282,5284,5286,5288,5290,5293],{"class":404,"line":457},[402,5283,4979],{"class":408},[402,5285,490],{"class":412},[402,5287,4984],{"class":475},[402,5289,1335],{"class":412},[402,5291,5292],{"class":475},"\"Australia\"",[402,5294,496],{"class":412},[402,5296,5297],{"class":404,"line":465},[402,5298,1820],{"class":412},[402,5300,5301],{"class":404,"line":479},[402,5302,496],{"class":412},[402,5304,5305],{"class":404,"line":499},[402,5306,703],{"emptyLinePlaceholder":54},[402,5308,5309],{"class":404,"line":505},[402,5310,5311],{"class":708},"\u002F\u002F Update it to an anonymous context when a user signs out. Leaving `id` unset\n",[402,5313,5314],{"class":404,"line":511},[402,5315,5316],{"class":708},"\u002F\u002F makes the server derive a stable identifier from this SDK instance.\n",[402,5318,5319,5321,5323,5325,5327,5329,5332,5334,5336],{"class":404,"line":519},[402,5320,1002],{"class":412},[402,5322,5224],{"class":408},[402,5324,1367],{"class":412},[402,5326,1370],{"class":408},[402,5328,1373],{"class":412},[402,5330,5331],{"class":408},"anonymous",[402,5333,490],{"class":412},[402,5335,2538],{"class":3637},[402,5337,1384],{"class":412},[393,5339,5341],{"className":1010,"code":5340,"filename":3721,"language":1013,"meta":398,"style":398},"import com.configdirector.ConfigDirectorContext;\n\nclient.updateContext(\n    ConfigDirectorContext.builder()\n        .id(\"654321\")\n        .name(\"Another User\")\n        .trait(\"region\", \"Australia\")\n        .build(),\n    () -> Log.i(\"MyApp\", \"Context updated\"));\n\n\u002F\u002F Update it to an anonymous context when a user signs out. Leaving `id` unset\n\u002F\u002F makes the server derive a stable identifier from this SDK instance.\nclient.updateContext(\n    ConfigDirectorContext.builder().anonymous(true).build(),\n    () -> Log.i(\"MyApp\", \"Signed out\"));\n",[272,5342,5343,5359,5363,5373,5384,5401,5418,5443,5451,5483,5487,5491,5495,5505,5527],{"__ignoreMap":398},[402,5344,5345,5347,5349,5351,5353,5355,5357],{"class":404,"line":405},[402,5346,945],{"class":1020},[402,5348,1024],{"class":1023},[402,5350,850],{"class":576},[402,5352,860],{"class":1023},[402,5354,850],{"class":576},[402,5356,1454],{"class":1023},[402,5358,1036],{"class":576},[402,5360,5361],{"class":404,"line":416},[402,5362,703],{"emptyLinePlaceholder":54},[402,5364,5365,5367,5369,5371],{"class":404,"line":424},[402,5366,1099],{"class":412},[402,5368,850],{"class":576},[402,5370,5224],{"class":408},[402,5372,1578],{"class":576},[402,5374,5375,5378,5380,5382],{"class":404,"line":433},[402,5376,5377],{"class":412},"    ConfigDirectorContext",[402,5379,850],{"class":576},[402,5381,1588],{"class":408},[402,5383,430],{"class":576},[402,5385,5386,5388,5390,5392,5394,5397,5399],{"class":404,"line":441},[402,5387,1877],{"class":576},[402,5389,1376],{"class":408},[402,5391,490],{"class":576},[402,5393,841],{"class":606},[402,5395,5396],{"class":475},"654321",[402,5398,841],{"class":606},[402,5400,496],{"class":576},[402,5402,5403,5405,5407,5409,5411,5414,5416],{"class":404,"line":449},[402,5404,1877],{"class":576},[402,5406,5113],{"class":408},[402,5408,490],{"class":576},[402,5410,841],{"class":606},[402,5412,5413],{"class":475},"Another User",[402,5415,841],{"class":606},[402,5417,496],{"class":576},[402,5419,5420,5422,5424,5426,5428,5430,5432,5434,5436,5439,5441],{"class":404,"line":457},[402,5421,1877],{"class":576},[402,5423,5136],{"class":408},[402,5425,490],{"class":576},[402,5427,841],{"class":606},[402,5429,5143],{"class":475},[402,5431,841],{"class":606},[402,5433,844],{"class":576},[402,5435,800],{"class":606},[402,5437,5438],{"class":475},"Australia",[402,5440,841],{"class":606},[402,5442,496],{"class":576},[402,5444,5445,5447,5449],{"class":404,"line":465},[402,5446,1877],{"class":576},[402,5448,1370],{"class":408},[402,5450,1609],{"class":576},[402,5452,5453,5456,5458,5460,5462,5464,5466,5468,5470,5472,5474,5476,5479,5481],{"class":404,"line":479},[402,5454,5455],{"class":576},"    ()",[402,5457,1118],{"class":1117},[402,5459,1121],{"class":412},[402,5461,850],{"class":576},[402,5463,1126],{"class":408},[402,5465,490],{"class":576},[402,5467,841],{"class":606},[402,5469,1133],{"class":475},[402,5471,841],{"class":606},[402,5473,844],{"class":576},[402,5475,800],{"class":606},[402,5477,5478],{"class":475},"Context updated",[402,5480,841],{"class":606},[402,5482,3869],{"class":576},[402,5484,5485],{"class":404,"line":499},[402,5486,703],{"emptyLinePlaceholder":54},[402,5488,5489],{"class":404,"line":505},[402,5490,5311],{"class":708},[402,5492,5493],{"class":404,"line":511},[402,5494,5316],{"class":708},[402,5496,5497,5499,5501,5503],{"class":404,"line":519},[402,5498,1099],{"class":412},[402,5500,850],{"class":576},[402,5502,5224],{"class":408},[402,5504,1578],{"class":576},[402,5506,5507,5509,5511,5513,5515,5517,5519,5521,5523,5525],{"class":404,"line":532},[402,5508,5377],{"class":412},[402,5510,850],{"class":576},[402,5512,1588],{"class":408},[402,5514,1351],{"class":576},[402,5516,5331],{"class":408},[402,5518,490],{"class":576},[402,5520,2538],{"class":1108},[402,5522,1604],{"class":576},[402,5524,1370],{"class":408},[402,5526,1609],{"class":576},[402,5528,5529,5531,5533,5535,5537,5539,5541,5543,5545,5547,5549,5551,5554,5556],{"class":404,"line":537},[402,5530,5455],{"class":576},[402,5532,1118],{"class":1117},[402,5534,1121],{"class":412},[402,5536,850],{"class":576},[402,5538,1126],{"class":408},[402,5540,490],{"class":576},[402,5542,841],{"class":606},[402,5544,1133],{"class":475},[402,5546,841],{"class":606},[402,5548,844],{"class":576},[402,5550,800],{"class":606},[402,5552,5553],{"class":475},"Signed out",[402,5555,841],{"class":606},[402,5557,3869],{"class":576},[1175,5559,5560,5561,5564,5565,5567],{},"In client SDKs (browser and mobile), updating the user context re-establishes a new connection to ConfigDirector servers with the new context. While the new connection is in flight, config values will continue to evaluate to the currently cached values from the prior user context.",[5562,5563],"br",{},"\nAwaiting ",[272,5566,5224],{}," will wait until the new config values are downloaded or the connection times out. In the case of a timeout, the client will continue to attempt to connect with the new context in the background.",[265,5569,5570,5571,1335,5573,1335,5575,1335,5577,1335,5579,5581,5582,5584],{},"Traits are JSON-shaped values: ",[272,5572,2169],{},[272,5574,4088],{},[272,5576,3330],{},[272,5578,4093],{},[272,5580,4096],{},", or null. A trait of any other type could never match a targeting rule, so building the context throws a ",[272,5583,1183],{}," rather than sending something the server cannot evaluate.",[393,5586,5588],{"className":395,"code":5587,"filename":3583,"language":397,"meta":398,"style":398},"client.updateContext(\n    ConfigDirectorContext.build {\n        id(\"user-123\")\n        name(\"Ada Lovelace\")\n        traits(\n            mapOf(\n                \"plan\" to \"pro\",\n                \"seats\" to 12,\n                \"beta\" to true,\n                \"regions\" to listOf(\"us-east\", \"eu-west\"),\n            ),\n        )\n    },\n)\n",[272,5589,5590,5598,5606,5616,5627,5634,5641,5653,5665,5676,5697,5702,5707,5711],{"__ignoreMap":398},[402,5591,5592,5594,5596],{"class":404,"line":405},[402,5593,1002],{"class":412},[402,5595,5224],{"class":408},[402,5597,1578],{"class":412},[402,5599,5600,5602,5604],{"class":404,"line":416},[402,5601,4941],{"class":412},[402,5603,1370],{"class":408},[402,5605,413],{"class":412},[402,5607,5608,5610,5612,5614],{"class":404,"line":424},[402,5609,4950],{"class":408},[402,5611,490],{"class":412},[402,5613,1381],{"class":475},[402,5615,496],{"class":412},[402,5617,5618,5620,5622,5625],{"class":404,"line":433},[402,5619,4962],{"class":408},[402,5621,490],{"class":412},[402,5623,5624],{"class":475},"\"Ada Lovelace\"",[402,5626,496],{"class":412},[402,5628,5629,5632],{"class":404,"line":441},[402,5630,5631],{"class":408},"        traits",[402,5633,1578],{"class":412},[402,5635,5636,5639],{"class":404,"line":449},[402,5637,5638],{"class":408},"            mapOf",[402,5640,1578],{"class":412},[402,5642,5643,5646,5648,5651],{"class":404,"line":457},[402,5644,5645],{"class":475},"                \"plan\"",[402,5647,4135],{"class":412},[402,5649,5650],{"class":475},"\"pro\"",[402,5652,1789],{"class":412},[402,5654,5655,5658,5660,5663],{"class":404,"line":465},[402,5656,5657],{"class":475},"                \"seats\"",[402,5659,4135],{"class":412},[402,5661,5662],{"class":2613},"12",[402,5664,1789],{"class":412},[402,5666,5667,5670,5672,5674],{"class":404,"line":479},[402,5668,5669],{"class":475},"                \"beta\"",[402,5671,4135],{"class":412},[402,5673,2538],{"class":3637},[402,5675,1789],{"class":412},[402,5677,5678,5681,5683,5685,5687,5689,5691,5694],{"class":404,"line":499},[402,5679,5680],{"class":475},"                \"regions\"",[402,5682,4135],{"class":412},[402,5684,4190],{"class":408},[402,5686,490],{"class":412},[402,5688,4195],{"class":475},[402,5690,1335],{"class":412},[402,5692,5693],{"class":475},"\"eu-west\"",[402,5695,5696],{"class":412},"),\n",[402,5698,5699],{"class":404,"line":505},[402,5700,5701],{"class":412},"            ),\n",[402,5703,5704],{"class":404,"line":511},[402,5705,5706],{"class":412},"        )\n",[402,5708,5709],{"class":404,"line":519},[402,5710,1820],{"class":412},[402,5712,5713],{"class":404,"line":532},[402,5714,496],{"class":412},[265,5716,5717,5718,4135,5720,5722,5723,5725,5726,5728],{},"For a signed-out user, set ",[272,5719,5331],{},[272,5721,2538],{},". The values are still used to evaluate targeting rules, but the context is not persisted and does not appear in the dashboard. Leaving ",[272,5724,1376],{}," unset makes the ConfigDirector server derive an identifier from the SDK instance, so the user keeps the same place in percentage rollouts for as long as that client instance lives; a new client instance gets a new identifier, which can move the user into a different percentile. Pass your own ",[272,5727,1376],{}," when a rollout must stay stable across app launches.",[260,5730,5732],{"id":5731},"other-useful-client-features","Other useful client features",[265,5734,5735],{},"The client provides additional properties and methods.",[1716,5737,5738],{"id":3297},[272,5739,3297],{},[265,5741,5742,5743,5745,5746,5748,5749,5751,5752,5754],{},"Returns the current user context (which may be ",[272,5744,1109],{},"). When calling ",[272,5747,5224],{},", the ",[272,5750,3297],{}," is not immediately updated. The ",[272,5753,3297],{}," is updated after the new connection for the new context succeeds (or times out and goes on retry).",[1716,5756,5758],{"id":5757},"isready",[272,5759,1155],{},[265,5761,5762,5763,5765,5766,5768,5769,5771,5772,5774,5775,5777,5778,5780,5781,5783,5784,5786],{},"Returns a ",[272,5764,3330],{}," indicating if the client has been successfully initialized and is ready to evaluate configs for the given user context. It is initially ",[272,5767,2528],{}," and becomes ",[272,5770,2538],{}," after ",[272,5773,1005],{}," succeeds.\nUpon calling ",[272,5776,5224],{}," it becomes ",[272,5779,2528],{}," again and it is set to ",[272,5782,2538],{}," once ",[272,5785,5224],{}," succeeds.",[1716,5788,5790],{"id":5789},"isinitializing",[272,5791,5792],{},"isInitializing",[265,5794,5762,5795,5797,5798,5800,5801,5803,5804,5806,5807,5809,5810,5812,5813,5815,5816,384,5818,5821],{},[272,5796,3330],{}," indicating whether the client is trying to get its very first config state from the server. It is ",[272,5799,2528],{}," on creation, becomes ",[272,5802,2538],{}," when ",[272,5805,1005],{}," is called on a client that has never received config state, stays ",[272,5808,2538],{}," through timeouts and retries, and becomes ",[272,5811,2528],{}," when the first config state arrives, when an unrecoverable connection error stops the retries, or on ",[272,5814,3211],{},". ",[272,5817,5224],{},[272,5819,5820],{},"resumeNetwork"," never set it. This is useful to show a loading state instead of transitioning from the in-code default value to the evaluated value on a slow connection.",[1716,5823,5825,384,5827],{"id":5824},"pausenetwork-and-resumenetwork",[272,5826,1701],{},[272,5828,1704],{},[265,5830,5831,5833,5834,5836,5837,376,5839,5841,5842,2467,5844,5846],{},[272,5832,1701],{}," releases the network connection without discarding config state, watches, or listeners, and ",[272,5835,1704],{}," re-establishes it using the last context given to ",[272,5838,1005],{},[272,5840,5224],{},". Reads keep serving the last config state the client received, and ",[272,5843,1155],{},[272,5845,2528],{}," until the connection is back.",[265,5848,5849,5850,4135,5852,5854],{},"The client already does this on its own while the app is backgrounded, so these are only needed if you set ",[272,5851,2520],{},[272,5853,2528],{}," in order to manage the connection yourself.",[265,5856,5857,5859,5860,5862,5863,5865,5866,850],{},[272,5858,5820],{}," has the same two forms as ",[272,5861,1005],{},": a ",[272,5864,274],{}," function for Kotlin, and one taking a ",[272,5867,1172],{},[1716,5869,5870],{"id":3211},[272,5871,1713],{},[265,5873,5874],{},"Closes the connection, every watch, and every listener registration, and reports whatever telemetry is left. The client cannot be used afterwards: it stops receiving config state and never becomes ready again, though reads keep serving the last config state it received.",[265,5876,5877],{},"Most applications never need to call it — the client lives as long as the process, and Android reclaims everything when the process ends. Call it when an application wants the client gone before that, on sign-out for instance.",[260,5879,5881],{"id":5880},"test-your-code","Test your code",[265,5883,5884,5885,5887,5888,5892,5893,5896],{},"Use the SDK's testing artifact, ",[272,5886,343],{},", to test the code that reads your configs and flags. It creates a ",[5889,5890,5891],"strong",{},"test client",": the SDK's real client connected to an in-memory server that your test controls. Only the connection to ConfigDirector, the telemetry, and the app lifecycle observer are replaced. Everything else is the same code that runs in production, so the code under test behaves exactly as it does against ConfigDirector, and no network connection is opened, no telemetry is sent, and no Android ",[272,5894,5895],{},"Context"," is needed. It runs in a plain JVM unit test, under Robolectric, and in an instrumented test alike.",[265,5898,5899,5900,5902,5903,5906],{},"The artifact is released together with the SDK and must be the same version as the ",[272,5901,258],{}," on your test classpath; ",[272,5904,5905],{},"createTestClient"," refuses any other. Add it in test scope:",[390,5908,5909,5952],{},[393,5910,5912],{"className":395,"code":5911,"filename":677,"language":397,"meta":398,"style":398},"dependencies {\n    testImplementation(\"com.configdirector:android-sdk-testing:1.7.1\")\n    \u002F\u002F For a Main dispatcher in plain JVM tests, see below\n    testImplementation(\"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0\")\n}\n",[272,5913,5914,5920,5932,5937,5948],{"__ignoreMap":398},[402,5915,5916,5918],{"class":404,"line":405},[402,5917,684],{"class":408},[402,5919,413],{"class":412},[402,5921,5922,5925,5927,5930],{"class":404,"line":416},[402,5923,5924],{"class":408},"    testImplementation",[402,5926,490],{"class":412},[402,5928,5929],{"class":475},"\"com.configdirector:android-sdk-testing:1.7.1\"",[402,5931,496],{"class":412},[402,5933,5934],{"class":404,"line":424},[402,5935,5936],{"class":708},"    \u002F\u002F For a Main dispatcher in plain JVM tests, see below\n",[402,5938,5939,5941,5943,5946],{"class":404,"line":433},[402,5940,5924],{"class":408},[402,5942,490],{"class":412},[402,5944,5945],{"class":475},"\"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0\"",[402,5947,496],{"class":412},[402,5949,5950],{"class":404,"line":441},[402,5951,552],{"class":412},[393,5953,5955],{"className":555,"code":5954,"filename":728,"language":557,"meta":398,"style":398},"dependencies {\n    testImplementation 'com.configdirector:android-sdk-testing:1.7.1'\n    \u002F\u002F For a Main dispatcher in plain JVM tests, see below\n    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0'\n}\n",[272,5956,5957,5961,5973,5977,5988],{"__ignoreMap":398},[402,5958,5959],{"class":404,"line":405},[402,5960,735],{"class":412},[402,5962,5963,5966,5968,5971],{"class":404,"line":416},[402,5964,5965],{"class":412},"    testImplementation ",[402,5967,647],{"class":606},[402,5969,5970],{"class":475},"com.configdirector:android-sdk-testing:1.7.1",[402,5972,613],{"class":606},[402,5974,5975],{"class":404,"line":424},[402,5976,5936],{"class":708},[402,5978,5979,5981,5983,5986],{"class":404,"line":433},[402,5980,5965],{"class":412},[402,5982,647],{"class":606},[402,5984,5985],{"class":475},"org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0",[402,5987,613],{"class":606},[402,5989,5990],{"class":404,"line":441},[402,5991,552],{"class":412},[393,5993,5996],{"className":395,"code":5994,"filename":5995,"language":397,"meta":398,"style":398},"import com.configdirector.testing.createTestClient\n\nclass CheckoutTest {\n\n    @Test\n    fun `enables the new checkout when the flag is on`() = runBlocking {\n        val testClient = createTestClient(values = mapOf(\"new-checkout\" to true, \"max-items\" to 20))\n        testClient.client.initialize()\n\n        val checkout = Checkout(testClient.client)\n        assertThat(checkout.isNewCheckoutEnabled).isTrue()\n\n        testClient.setValue(\"new-checkout\", false)\n        assertThat(checkout.isNewCheckoutEnabled).isFalse()\n\n        testClient.client.close()\n    }\n}\n","CheckoutTest.kt",[272,5997,5998,6005,6009,6018,6022,6027,6045,6086,6095,6099,6114,6127,6131,6149,6160,6164,6172,6176],{"__ignoreMap":398},[402,5999,6000,6002],{"class":404,"line":405},[402,6001,945],{"class":471},[402,6003,6004],{"class":786}," com.configdirector.testing.createTestClient\n",[402,6006,6007],{"class":404,"line":416},[402,6008,703],{"emptyLinePlaceholder":54},[402,6010,6011,6013,6016],{"class":404,"line":424},[402,6012,1248],{"class":471},[402,6014,6015],{"class":786}," CheckoutTest",[402,6017,413],{"class":412},[402,6019,6020],{"class":404,"line":433},[402,6021,703],{"emptyLinePlaceholder":54},[402,6023,6024],{"class":404,"line":441},[402,6025,6026],{"class":786},"    @Test\n",[402,6028,6029,6032,6035,6038,6040,6043],{"class":404,"line":449},[402,6030,6031],{"class":471},"    fun",[402,6033,6034],{"class":408}," `enables the new checkout when the flag is on`",[402,6036,6037],{"class":412},"() ",[402,6039,472],{"class":471},[402,6041,6042],{"class":408}," runBlocking",[402,6044,413],{"class":412},[402,6046,6047,6049,6052,6054,6057,6060,6062,6065,6067,6070,6072,6074,6076,6079,6081,6084],{"class":404,"line":457},[402,6048,4441],{"class":471},[402,6050,6051],{"class":412}," testClient ",[402,6053,472],{"class":471},[402,6055,6056],{"class":408}," createTestClient",[402,6058,6059],{"class":412},"(values ",[402,6061,472],{"class":471},[402,6063,6064],{"class":408}," mapOf",[402,6066,490],{"class":412},[402,6068,6069],{"class":475},"\"new-checkout\"",[402,6071,4135],{"class":412},[402,6073,2538],{"class":3637},[402,6075,1335],{"class":412},[402,6077,6078],{"class":475},"\"max-items\"",[402,6080,4135],{"class":412},[402,6082,6083],{"class":2613},"20",[402,6085,1908],{"class":412},[402,6087,6088,6091,6093],{"class":404,"line":465},[402,6089,6090],{"class":412},"        testClient.client.",[402,6092,1005],{"class":408},[402,6094,430],{"class":412},[402,6096,6097],{"class":404,"line":479},[402,6098,703],{"emptyLinePlaceholder":54},[402,6100,6101,6103,6106,6108,6111],{"class":404,"line":499},[402,6102,4441],{"class":471},[402,6104,6105],{"class":412}," checkout ",[402,6107,472],{"class":471},[402,6109,6110],{"class":408}," Checkout",[402,6112,6113],{"class":412},"(testClient.client)\n",[402,6115,6116,6119,6122,6125],{"class":404,"line":505},[402,6117,6118],{"class":408},"        assertThat",[402,6120,6121],{"class":412},"(checkout.isNewCheckoutEnabled).",[402,6123,6124],{"class":408},"isTrue",[402,6126,430],{"class":412},[402,6128,6129],{"class":404,"line":511},[402,6130,703],{"emptyLinePlaceholder":54},[402,6132,6133,6136,6139,6141,6143,6145,6147],{"class":404,"line":519},[402,6134,6135],{"class":412},"        testClient.",[402,6137,6138],{"class":408},"setValue",[402,6140,490],{"class":412},[402,6142,6069],{"class":475},[402,6144,1335],{"class":412},[402,6146,2528],{"class":3637},[402,6148,496],{"class":412},[402,6150,6151,6153,6155,6158],{"class":404,"line":532},[402,6152,6118],{"class":408},[402,6154,6121],{"class":412},[402,6156,6157],{"class":408},"isFalse",[402,6159,430],{"class":412},[402,6161,6162],{"class":404,"line":537},[402,6163,703],{"emptyLinePlaceholder":54},[402,6165,6166,6168,6170],{"class":404,"line":543},[402,6167,6090],{"class":412},[402,6169,3211],{"class":408},[402,6171,430],{"class":412},[402,6173,6174],{"class":404,"line":549},[402,6175,546],{"class":412},[402,6177,6178],{"class":404,"line":1359},[402,6179,552],{"class":412},[265,6181,6182,1166,6185,6187,6188,6190,6191,6193],{},[272,6183,6184],{},"testClient.client",[272,6186,1033],{},", so it goes anywhere your code accepts one. It starts uninitialized, like a production client, because the code under test usually owns the call to ",[272,6189,1005],{},"; with nothing held or failed, ",[272,6192,1005],{}," completes at once with the client ready. Close it when the test is done, as your production code would.",[265,6195,6196,6197,6200],{},"From Java, the factory is ",[272,6198,6199],{},"ConfigDirectorTesting.createTestClient(values)",", with overloads that also take the timeout and the logger. The callback overloads of the client complete on the Main dispatcher, so a plain JVM test sets one first (see below):",[393,6202,6205],{"className":1010,"code":6203,"filename":6204,"language":1013,"meta":398,"style":398},"import com.configdirector.testing.ConfigDirectorTesting;\nimport com.configdirector.testing.TestClient;\n\nTestClient testClient = ConfigDirectorTesting.createTestClient(Collections.singletonMap(\"new-checkout\", true));\nCountDownLatch initialized = new CountDownLatch(1);\ntestClient.getClient().initialize(null, initialized::countDown);\ninitialized.await(5, TimeUnit.SECONDS);\n\nCheckout checkout = new Checkout(testClient.getClient());\nassertThat(checkout.isNewCheckoutEnabled()).isTrue();\n\ntestClient.setValue(\"new-checkout\", false);\nassertThat(checkout.isNewCheckoutEnabled()).isFalse();\n\ntestClient.getClient().close();\n","CheckoutTest.java",[272,6206,6207,6229,6250,6254,6295,6317,6348,6375,6379,6402,6424,6428,6450,6468,6472],{"__ignoreMap":398},[402,6208,6209,6211,6213,6215,6217,6219,6222,6224,6227],{"class":404,"line":405},[402,6210,945],{"class":1020},[402,6212,1024],{"class":1023},[402,6214,850],{"class":576},[402,6216,860],{"class":1023},[402,6218,850],{"class":576},[402,6220,6221],{"class":1023},"testing",[402,6223,850],{"class":576},[402,6225,6226],{"class":1023},"ConfigDirectorTesting",[402,6228,1036],{"class":576},[402,6230,6231,6233,6235,6237,6239,6241,6243,6245,6248],{"class":404,"line":416},[402,6232,945],{"class":1020},[402,6234,1024],{"class":1023},[402,6236,850],{"class":576},[402,6238,860],{"class":1023},[402,6240,850],{"class":576},[402,6242,6221],{"class":1023},[402,6244,850],{"class":576},[402,6246,6247],{"class":1023},"TestClient",[402,6249,1036],{"class":576},[402,6251,6252],{"class":404,"line":424},[402,6253,703],{"emptyLinePlaceholder":54},[402,6255,6256,6258,6260,6262,6265,6267,6269,6271,6274,6276,6279,6281,6283,6286,6288,6290,6293],{"class":404,"line":433},[402,6257,6247],{"class":1023},[402,6259,6051],{"class":412},[402,6261,472],{"class":471},[402,6263,6264],{"class":412}," ConfigDirectorTesting",[402,6266,850],{"class":576},[402,6268,5905],{"class":408},[402,6270,490],{"class":576},[402,6272,6273],{"class":412},"Collections",[402,6275,850],{"class":576},[402,6277,6278],{"class":408},"singletonMap",[402,6280,490],{"class":576},[402,6282,841],{"class":606},[402,6284,6285],{"class":475},"new-checkout",[402,6287,841],{"class":606},[402,6289,844],{"class":576},[402,6291,6292],{"class":1108}," true",[402,6294,3869],{"class":576},[402,6296,6297,6300,6303,6305,6307,6310,6312,6315],{"class":404,"line":441},[402,6298,6299],{"class":1023},"CountDownLatch",[402,6301,6302],{"class":412}," initialized ",[402,6304,472],{"class":471},[402,6306,1060],{"class":1059},[402,6308,6309],{"class":408}," CountDownLatch",[402,6311,490],{"class":576},[402,6313,6314],{"class":2613},"1",[402,6316,1080],{"class":576},[402,6318,6319,6322,6324,6327,6329,6331,6333,6335,6337,6340,6343,6346],{"class":404,"line":449},[402,6320,6321],{"class":412},"testClient",[402,6323,850],{"class":576},[402,6325,6326],{"class":408},"getClient",[402,6328,1351],{"class":576},[402,6330,1005],{"class":408},[402,6332,490],{"class":576},[402,6334,1109],{"class":1108},[402,6336,844],{"class":576},[402,6338,6339],{"class":412}," initialized",[402,6341,6342],{"class":1059},"::",[402,6344,6345],{"class":412},"countDown",[402,6347,1080],{"class":576},[402,6349,6350,6353,6355,6358,6360,6363,6365,6368,6370,6373],{"class":404,"line":457},[402,6351,6352],{"class":412},"initialized",[402,6354,850],{"class":576},[402,6356,6357],{"class":408},"await",[402,6359,490],{"class":576},[402,6361,6362],{"class":2613},"5",[402,6364,844],{"class":576},[402,6366,6367],{"class":412}," TimeUnit",[402,6369,850],{"class":576},[402,6371,6372],{"class":412},"SECONDS",[402,6374,1080],{"class":576},[402,6376,6377],{"class":404,"line":465},[402,6378,703],{"emptyLinePlaceholder":54},[402,6380,6381,6384,6386,6388,6390,6392,6394,6396,6398,6400],{"class":404,"line":479},[402,6382,6383],{"class":1023},"Checkout",[402,6385,6105],{"class":412},[402,6387,472],{"class":471},[402,6389,1060],{"class":1059},[402,6391,6110],{"class":408},[402,6393,490],{"class":576},[402,6395,6321],{"class":412},[402,6397,850],{"class":576},[402,6399,6326],{"class":408},[402,6401,1917],{"class":576},[402,6403,6404,6407,6409,6412,6414,6417,6420,6422],{"class":404,"line":499},[402,6405,6406],{"class":408},"assertThat",[402,6408,490],{"class":576},[402,6410,6411],{"class":412},"checkout",[402,6413,850],{"class":576},[402,6415,6416],{"class":408},"isNewCheckoutEnabled",[402,6418,6419],{"class":576},"()).",[402,6421,6124],{"class":408},[402,6423,1533],{"class":576},[402,6425,6426],{"class":404,"line":505},[402,6427,703],{"emptyLinePlaceholder":54},[402,6429,6430,6432,6434,6436,6438,6440,6442,6444,6446,6448],{"class":404,"line":511},[402,6431,6321],{"class":412},[402,6433,850],{"class":576},[402,6435,6138],{"class":408},[402,6437,490],{"class":576},[402,6439,841],{"class":606},[402,6441,6285],{"class":475},[402,6443,841],{"class":606},[402,6445,844],{"class":576},[402,6447,3782],{"class":1108},[402,6449,1080],{"class":576},[402,6451,6452,6454,6456,6458,6460,6462,6464,6466],{"class":404,"line":519},[402,6453,6406],{"class":408},[402,6455,490],{"class":576},[402,6457,6411],{"class":412},[402,6459,850],{"class":576},[402,6461,6416],{"class":408},[402,6463,6419],{"class":576},[402,6465,6157],{"class":408},[402,6467,1533],{"class":576},[402,6469,6470],{"class":404,"line":532},[402,6471,703],{"emptyLinePlaceholder":54},[402,6473,6474,6476,6478,6480,6482,6484],{"class":404,"line":537},[402,6475,6321],{"class":412},[402,6477,850],{"class":576},[402,6479,6326],{"class":408},[402,6481,1351],{"class":576},[402,6483,3211],{"class":408},[402,6485,1533],{"class":576},[1716,6487,6489],{"id":6488},"the-main-dispatcher","The Main dispatcher",[265,6491,6492,6493,384,6495,6497,6498,6501,6502,6505,6506,6508],{},"The client hands listeners, watches, the ",[272,6494,3669],{},[272,6496,2772],{}," flows, the Compose bindings, and the Java callback overloads back on the Main dispatcher. Robolectric and instrumented tests have one. A plain JVM test does not, so it sets one from ",[272,6499,6500],{},"kotlinx-coroutines-test",". With ",[272,6503,6504],{},"UnconfinedTestDispatcher",", watches and listeners run inline, so a watch has seen a ",[272,6507,6138],{}," by the time it returns:",[393,6510,6512],{"className":395,"code":6511,"language":397,"meta":398,"style":398},"@Before\nfun setUpMainDispatcher() {\n    Dispatchers.setMain(UnconfinedTestDispatcher())\n}\n\n@After\nfun tearDown() {\n    testClient.client.close()\n    Dispatchers.resetMain()\n}\n",[272,6513,6514,6519,6528,6542,6546,6550,6555,6564,6573,6582],{"__ignoreMap":398},[402,6515,6516],{"class":404,"line":405},[402,6517,6518],{"class":786},"@Before\n",[402,6520,6521,6523,6526],{"class":404,"line":416},[402,6522,3915],{"class":471},[402,6524,6525],{"class":408}," setUpMainDispatcher",[402,6527,1259],{"class":412},[402,6529,6530,6533,6536,6538,6540],{"class":404,"line":424},[402,6531,6532],{"class":412},"    Dispatchers.",[402,6534,6535],{"class":408},"setMain",[402,6537,490],{"class":412},[402,6539,6504],{"class":408},[402,6541,2755],{"class":412},[402,6543,6544],{"class":404,"line":433},[402,6545,552],{"class":412},[402,6547,6548],{"class":404,"line":441},[402,6549,703],{"emptyLinePlaceholder":54},[402,6551,6552],{"class":404,"line":449},[402,6553,6554],{"class":786},"@After\n",[402,6556,6557,6559,6562],{"class":404,"line":457},[402,6558,3915],{"class":471},[402,6560,6561],{"class":408}," tearDown",[402,6563,1259],{"class":412},[402,6565,6566,6569,6571],{"class":404,"line":465},[402,6567,6568],{"class":412},"    testClient.client.",[402,6570,3211],{"class":408},[402,6572,430],{"class":412},[402,6574,6575,6577,6580],{"class":404,"line":479},[402,6576,6532],{"class":412},[402,6578,6579],{"class":408},"resetMain",[402,6581,430],{"class":412},[402,6583,6584],{"class":404,"line":499},[402,6585,552],{"class":412},[265,6587,6588,6589,6592,6593,6596,6597,6599,6600,6602,6603,6606,6607,6610],{},"From Java, call ",[272,6590,6591],{},"TestDispatchers.setMain(Dispatchers.INSTANCE, Dispatchers.getDefault())"," before the test and ",[272,6594,6595],{},"TestDispatchers.resetMain(Dispatchers.INSTANCE)"," after it. Reads through ",[272,6598,3525],{}," and the other getters need no Main dispatcher. Without one, the first client call that needs it, such as registering a watch or ",[272,6601,1005],{},", fails with an ",[272,6604,6605],{},"IllegalStateException"," saying that ",[272,6608,6609],{},"Dispatchers.Main"," is missing.",[1716,6612,6614],{"id":6613},"in-jetpack-compose","In Jetpack Compose",[265,6616,6617,6618,6621,6622,6624,6625,6627],{},"A composable needs a composition to run in, which on the JVM means Robolectric with ",[272,6619,6620],{},"createComposeRule",", or an instrumented test. Wrap the content in the production ",[272,6623,4370],{}," with the test client's client, as the app does. The client hands values to the bindings on the main looper, which Robolectric only runs when the test lets it, so idle it after ",[272,6626,1005],{}," and after every change:",[393,6629,6632],{"className":395,"code":6630,"filename":6631,"language":397,"meta":398,"style":398},"import com.configdirector.compose.ConfigDirectorProvider\nimport com.configdirector.testing.createTestClient\n\n@RunWith(RobolectricTestRunner::class)\nclass HomeScreenTest {\n\n    @get:Rule\n    val compose = createComposeRule()\n\n    private val testClient = createTestClient(values = mapOf(\"greeting\" to \"hello\"))\n\n    @After\n    fun tearDown() = testClient.client.close()\n\n    private fun settle() {\n        shadowOf(Looper.getMainLooper()).idle()\n        compose.waitForIdle()\n    }\n\n    @Test\n    fun `shows the greeting from the config`() {\n        compose.setContent { ConfigDirectorProvider(testClient.client) { HomeScreen() } }\n        runBlocking { testClient.client.initialize() }\n        settle()\n        compose.onNodeWithText(\"hello\").assertIsDisplayed()\n\n        testClient.setValue(\"greeting\", \"hi\")\n        settle()\n        compose.onNodeWithText(\"hi\").assertIsDisplayed()\n    }\n}\n","HomeScreenTest.kt",[272,6633,6634,6640,6646,6650,6662,6671,6675,6685,6699,6703,6732,6736,6741,6758,6762,6773,6791,6801,6805,6809,6813,6822,6841,6853,6861,6880,6885,6903,6910,6927,6932],{"__ignoreMap":398},[402,6635,6636,6638],{"class":404,"line":405},[402,6637,945],{"class":471},[402,6639,4383],{"class":786},[402,6641,6642,6644],{"class":404,"line":416},[402,6643,945],{"class":471},[402,6645,6004],{"class":786},[402,6647,6648],{"class":404,"line":424},[402,6649,703],{"emptyLinePlaceholder":54},[402,6651,6652,6655,6658,6660],{"class":404,"line":433},[402,6653,6654],{"class":786},"@RunWith",[402,6656,6657],{"class":412},"(RobolectricTestRunner::",[402,6659,1248],{"class":408},[402,6661,496],{"class":412},[402,6663,6664,6666,6669],{"class":404,"line":441},[402,6665,1248],{"class":471},[402,6667,6668],{"class":786}," HomeScreenTest",[402,6670,413],{"class":412},[402,6672,6673],{"class":404,"line":449},[402,6674,703],{"emptyLinePlaceholder":54},[402,6676,6677,6680,6682],{"class":404,"line":457},[402,6678,6679],{"class":786},"    @get",[402,6681,388],{"class":412},[402,6683,6684],{"class":786},"Rule\n",[402,6686,6687,6689,6692,6694,6697],{"class":404,"line":465},[402,6688,3930],{"class":471},[402,6690,6691],{"class":412}," compose ",[402,6693,472],{"class":471},[402,6695,6696],{"class":408}," createComposeRule",[402,6698,430],{"class":412},[402,6700,6701],{"class":404,"line":479},[402,6702,703],{"emptyLinePlaceholder":54},[402,6704,6705,6707,6709,6711,6713,6715,6717,6719,6721,6723,6725,6727,6730],{"class":404,"line":499},[402,6706,4719],{"class":1117},[402,6708,2134],{"class":471},[402,6710,6051],{"class":412},[402,6712,472],{"class":471},[402,6714,6056],{"class":408},[402,6716,6059],{"class":412},[402,6718,472],{"class":471},[402,6720,6064],{"class":408},[402,6722,490],{"class":412},[402,6724,4583],{"class":475},[402,6726,4135],{"class":412},[402,6728,6729],{"class":475},"\"hello\"",[402,6731,1908],{"class":412},[402,6733,6734],{"class":404,"line":505},[402,6735,703],{"emptyLinePlaceholder":54},[402,6737,6738],{"class":404,"line":511},[402,6739,6740],{"class":786},"    @After\n",[402,6742,6743,6745,6747,6749,6751,6754,6756],{"class":404,"line":519},[402,6744,6031],{"class":471},[402,6746,6561],{"class":408},[402,6748,6037],{"class":412},[402,6750,472],{"class":471},[402,6752,6753],{"class":412}," testClient.client.",[402,6755,3211],{"class":408},[402,6757,430],{"class":412},[402,6759,6760],{"class":404,"line":532},[402,6761,703],{"emptyLinePlaceholder":54},[402,6763,6764,6766,6768,6771],{"class":404,"line":537},[402,6765,4719],{"class":1117},[402,6767,1297],{"class":471},[402,6769,6770],{"class":408}," settle",[402,6772,1259],{"class":412},[402,6774,6775,6778,6781,6784,6786,6789],{"class":404,"line":543},[402,6776,6777],{"class":408},"        shadowOf",[402,6779,6780],{"class":412},"(Looper.",[402,6782,6783],{"class":408},"getMainLooper",[402,6785,6419],{"class":412},[402,6787,6788],{"class":408},"idle",[402,6790,430],{"class":412},[402,6792,6793,6796,6799],{"class":404,"line":549},[402,6794,6795],{"class":412},"        compose.",[402,6797,6798],{"class":408},"waitForIdle",[402,6800,430],{"class":412},[402,6802,6803],{"class":404,"line":1359},[402,6804,546],{"class":412},[402,6806,6807],{"class":404,"line":1387},[402,6808,703],{"emptyLinePlaceholder":54},[402,6810,6811],{"class":404,"line":1392},[402,6812,6026],{"class":786},[402,6814,6815,6817,6820],{"class":404,"line":1397},[402,6816,6031],{"class":471},[402,6818,6819],{"class":408}," `shows the greeting from the config`",[402,6821,1259],{"class":412},[402,6823,6824,6826,6829,6831,6833,6836,6838],{"class":404,"line":1682},[402,6825,6795],{"class":412},[402,6827,6828],{"class":408},"setContent",[402,6830,1373],{"class":412},[402,6832,4370],{"class":408},[402,6834,6835],{"class":412},"(testClient.client) { ",[402,6837,4478],{"class":408},[402,6839,6840],{"class":412},"() } }\n",[402,6842,6843,6846,6849,6851],{"class":404,"line":1687},[402,6844,6845],{"class":408},"        runBlocking",[402,6847,6848],{"class":412}," { testClient.client.",[402,6850,1005],{"class":408},[402,6852,4481],{"class":412},[402,6854,6856,6859],{"class":404,"line":6855},24,[402,6857,6858],{"class":408},"        settle",[402,6860,430],{"class":412},[402,6862,6864,6866,6869,6871,6873,6875,6878],{"class":404,"line":6863},25,[402,6865,6795],{"class":412},[402,6867,6868],{"class":408},"onNodeWithText",[402,6870,490],{"class":412},[402,6872,6729],{"class":475},[402,6874,1604],{"class":412},[402,6876,6877],{"class":408},"assertIsDisplayed",[402,6879,430],{"class":412},[402,6881,6883],{"class":404,"line":6882},26,[402,6884,703],{"emptyLinePlaceholder":54},[402,6886,6888,6890,6892,6894,6896,6898,6901],{"class":404,"line":6887},27,[402,6889,6135],{"class":412},[402,6891,6138],{"class":408},[402,6893,490],{"class":412},[402,6895,4583],{"class":475},[402,6897,1335],{"class":412},[402,6899,6900],{"class":475},"\"hi\"",[402,6902,496],{"class":412},[402,6904,6906,6908],{"class":404,"line":6905},28,[402,6907,6858],{"class":408},[402,6909,430],{"class":412},[402,6911,6913,6915,6917,6919,6921,6923,6925],{"class":404,"line":6912},29,[402,6914,6795],{"class":412},[402,6916,6868],{"class":408},[402,6918,490],{"class":412},[402,6920,6900],{"class":475},[402,6922,1604],{"class":412},[402,6924,6877],{"class":408},[402,6926,430],{"class":412},[402,6928,6930],{"class":404,"line":6929},30,[402,6931,546],{"class":412},[402,6933,6935],{"class":404,"line":6934},31,[402,6936,552],{"class":412},[1716,6938,6939],{"id":3669},"Values",[265,6941,6942,1335,6944,6946,6947,6950,6951,6953,6954,376,6957,6960,6961,376,6964,6966,6967,6969,6970,6972,6973,6975,6976,6978,6979,6981,6982,6984,6985,6987,6988,6990,6991,6993,6994,6996,6997,6999,7000,850],{},[272,6943,3669],{},[272,6945,6138],{},", and ",[272,6948,6949],{},"replaceValues"," take native values, and the config type follows from each value's type: a ",[272,6952,3330],{},"; an ",[272,6955,6956],{},"Int",[272,6958,6959],{},"Long"," (an integer config); a ",[272,6962,6963],{},"Float",[272,6965,3338],{}," (a float config); a ",[272,6968,2169],{},"; or a ",[272,6971,4096],{}," with ",[272,6974,2169],{}," keys or a ",[272,6977,4093],{}," (a JSON config). A ",[272,6980,2169],{}," is always a string config, so JSON text meant as a JSON config is given as a ",[272,6983,4096],{}," or a ",[272,6986,4093],{},". Every value is served to every context; a test that needs different values per context is written as one test per value. A blank key, a non-finite number, a value of any other type, a ",[272,6989,4096],{}," with a non-",[272,6992,2169],{}," key, or JSON contents of any other type throw a ",[272,6995,1183],{},", and nothing changes. From Java, a ",[272,6998,1109],{}," value is a ",[272,7001,7002],{},"NullPointerException",[265,7004,7005,7006,7009,7010,7012,7013,7015,7016,7019,7020,7022,7023,7026,7027,7029,7030,7032,7033,7035,7036,7038,7039,7041,7042,7045,7046,7048,7049,7052,7053,7055,7056,7058,7059,7062,7063,7065],{},"Reads behave as they do in production: ",[272,7007,7008],{},"setValue(\"k\", true)"," read as a ",[272,7011,2169],{}," returns the in-code default value with the ",[272,7014,3420],{}," reason, ",[272,7017,7018],{},"setValue(\"k\", 2.5)"," read with ",[272,7021,3531],{}," returns ",[272,7024,7025],{},"2",", a ",[272,7028,6959],{}," beyond the ",[272,7031,6956],{}," range reads through ",[272,7034,3534],{}," and gives ",[272,7037,3531],{}," the ",[272,7040,3402],{}," reason, and ",[272,7043,7044],{},"setValue(\"k\", \"\")"," serves the in-code default value with the ",[272,7047,3396],{}," reason. A JSON object is encoded in the insertion order of a ",[272,7050,7051],{},"LinkedHashMap",", which is what ",[272,7054,4127],{}," builds, and with sorted keys for any other map; ",[272,7057,3537],{}," returns it in ",[272,7060,7061],{},"org.json","'s order, as in production. JSON configs parse through ",[272,7064,7061],{},", which the artifact brings for plain JVM tests, where Android's own is a stub; on a device Android's own is used.",[1716,7067,7069],{"id":7068},"controls","Controls",[281,7071,7072,7082],{},[284,7073,7074],{},[287,7075,7076,7079],{},[290,7077,7078],{},"Control",[290,7080,7081],{},"Effect",[303,7083,7084,7106,7130,7140,7163,7178,7193,7211],{},[287,7085,7086,7091],{},[308,7087,7088],{},[272,7089,7090],{},"setValue(key, value)",[308,7092,7093,7094,7097,7098,7100,7101,384,7103,7105],{},"Stores the value and, once the client is connected, delivers an update carrying only ",[272,7095,7096],{},"key",". Reads see it when ",[272,7099,6138],{}," returns; watches of ",[272,7102,7096],{},[272,7104,3133],{}," listeners see it once the Main dispatcher runs them.",[287,7107,7108,7113],{},[308,7109,7110],{},[272,7111,7112],{},"removeValue(key)",[308,7114,7115,7116,7118,7119,7121,7122,7124,7125,7127,7128,850],{},"Removes the value and delivers a full update without it. Reads return the in-code default value with the ",[272,7117,3390],{}," reason, watches of ",[272,7120,7096],{}," are handed the default, and ",[272,7123,3133],{}," lists ",[272,7126,7096],{}," in ",[272,7129,3275],{},[287,7131,7132,7137],{},[308,7133,7134],{},[272,7135,7136],{},"replaceValues(values)",[308,7138,7139],{},"Replaces every stored value, disarms any armed hold or failure, and delivers a full update. Use it to reset a test client shared across tests.",[287,7141,7142,7147],{},[308,7143,7144],{},[272,7145,7146],{},"holdInitialization()",[308,7148,7149,7150,7152,7153,376,7156,7159,7160,7162],{},"The next ",[272,7151,1005],{}," waits until ",[272,7154,7155],{},"completeInitialization()",[272,7157,7158],{},"failInitialization()",", or until the client's ",[272,7161,2492],{}," elapses.",[287,7164,7165,7169],{},[308,7166,7167],{},[272,7168,7155],{},[308,7170,7171,7172,7174,7175,7177],{},"Delivers the stored values to the held ",[272,7173,1005],{},", so the client is ready when it returns, and lets ",[272,7176,1005],{}," complete. Called while a hold is armed but not picked up, it disarms the hold.",[287,7179,7180,7184],{},[308,7181,7182],{},[272,7183,7158],{},[308,7185,7186,7187,7189,7190,7192],{},"Fails the held ",[272,7188,1005],{}," the way an invalid SDK key does: it completes promptly, the client is not ready, and an error is logged. Called with no ",[272,7191,1005],{}," held, it arms the next one to fail.",[287,7194,7195,7206],{},[308,7196,7197,1335,7200,1335,7203],{},[272,7198,7199],{},"holdContextUpdate()",[272,7201,7202],{},"completeContextUpdate()",[272,7204,7205],{},"failContextUpdate()",[308,7207,7208,7209,850],{},"The same for the next ",[272,7210,5224],{},[287,7212,7213,7218],{},[308,7214,7215],{},[272,7216,7217],{},"contextUpdates",[308,7219,7220,7221,384,7223,7225,7226,7228,7229,7231],{},"The context of every ",[272,7222,1005],{},[272,7224,5224],{}," call, in order. ",[272,7227,1005],{}," without a context records an empty context, and ",[272,7230,5820],{}," is not recorded.",[265,7233,7234,7235,7237,7238,7240,7241,7243,7244,7246],{},"The initialization controls act only on ",[272,7236,1005],{}," and the context update controls only on ",[272,7239,5224],{},"; ",[272,7242,5820],{}," is never held or failed. After a failed attempt, the next attempt succeeds and delivers the values stored in the meantime. A held ",[272,7245,1005],{}," suspends its caller, so a test that acts while it is held starts it on another dispatcher, or uses the callback overload:",[393,7248,7251],{"className":395,"code":7249,"filename":7250,"language":397,"meta":398,"style":398},"val testClient = createTestClient(values = mapOf(\"new-checkout\" to true), timeoutMillis = 500)\ntestClient.holdInitialization()\n\nval initialization = launch(Dispatchers.Default) { testClient.client.initialize() }\nassertThat(testClient.client.isReady).isFalse()\n\ntestClient.completeInitialization()\ninitialization.join()\nassertThat(testClient.client.isReady).isTrue()\n","LoadingTest.kt",[272,7252,7253,7287,7297,7301,7320,7331,7335,7344,7354],{"__ignoreMap":398},[402,7254,7255,7257,7259,7261,7263,7265,7267,7269,7271,7273,7275,7277,7280,7282,7285],{"class":404,"line":405},[402,7256,967],{"class":471},[402,7258,6051],{"class":412},[402,7260,472],{"class":471},[402,7262,6056],{"class":408},[402,7264,6059],{"class":412},[402,7266,472],{"class":471},[402,7268,6064],{"class":408},[402,7270,490],{"class":412},[402,7272,6069],{"class":475},[402,7274,4135],{"class":412},[402,7276,2538],{"class":3637},[402,7278,7279],{"class":412},"), timeoutMillis ",[402,7281,472],{"class":471},[402,7283,7284],{"class":2613}," 500",[402,7286,496],{"class":412},[402,7288,7289,7292,7295],{"class":404,"line":416},[402,7290,7291],{"class":412},"testClient.",[402,7293,7294],{"class":408},"holdInitialization",[402,7296,430],{"class":412},[402,7298,7299],{"class":404,"line":424},[402,7300,703],{"emptyLinePlaceholder":54},[402,7302,7303,7305,7308,7310,7313,7316,7318],{"class":404,"line":433},[402,7304,967],{"class":471},[402,7306,7307],{"class":412}," initialization ",[402,7309,472],{"class":471},[402,7311,7312],{"class":408}," launch",[402,7314,7315],{"class":412},"(Dispatchers.Default) { testClient.client.",[402,7317,1005],{"class":408},[402,7319,4481],{"class":412},[402,7321,7322,7324,7327,7329],{"class":404,"line":441},[402,7323,6406],{"class":408},[402,7325,7326],{"class":412},"(testClient.client.isReady).",[402,7328,6157],{"class":408},[402,7330,430],{"class":412},[402,7332,7333],{"class":404,"line":449},[402,7334,703],{"emptyLinePlaceholder":54},[402,7336,7337,7339,7342],{"class":404,"line":457},[402,7338,7291],{"class":412},[402,7340,7341],{"class":408},"completeInitialization",[402,7343,430],{"class":412},[402,7345,7346,7349,7352],{"class":404,"line":465},[402,7347,7348],{"class":412},"initialization.",[402,7350,7351],{"class":408},"join",[402,7353,430],{"class":412},[402,7355,7356,7358,7360,7362],{"class":404,"line":479},[402,7357,6406],{"class":408},[402,7359,7326],{"class":412},[402,7361,6124],{"class":408},[402,7363,430],{"class":412},[1716,7365,7367],{"id":7366},"options","Options",[265,7369,7370,7372,7373,1335,7375,7377,7378,7380,7381,7384,7385,7387,7388,7391,7392,7394],{},[272,7371,5905],{}," takes ",[272,7374,3669],{},[272,7376,2492],{}," (the client's connection timeout, which bounds how long a held attempt waits; defaults to the SDK's production timeout of 3 seconds), and ",[272,7379,1920],{},". The logger defaults to a ",[272,7382,7383],{},"StandardErrorLogger",", which writes warnings and errors to standard error, because the SDK's default ",[272,7386,1934],{}," writes to logcat, which a plain JVM test does not have; pass ",[272,7389,7390],{},"StandardErrorLogger(LogLevel.DEBUG)"," to see everything, or any ",[272,7393,1938],{}," of your own.",[1716,7396,7398],{"id":7397},"what-to-expect","What to expect",[2418,7400,7401,7415,7429,7438,7448],{},[923,7402,7403,7404,7406,7407,7409,7410,7409,7412,850],{},"Under the test client, ",[272,7405,1005],{}," publishes ",[272,7408,3056],{},", then ",[272,7411,3133],{},[272,7413,7414],{},"ContextUpdated",[923,7416,7417,7418,1335,7421,7423,7424,2467,7426,7428],{},"A held attempt that times out, or that is interrupted by ",[272,7419,7420],{},"pauseNetwork",[272,7422,3211],{},", or a new attempt, leaves the client not ready until the next attempt and logs \"An error occurred during initialization\" (or \"during context update\") at error level, as production does after a connection timeout. ",[272,7425,5792],{},[272,7427,2528],{}," afterwards.",[923,7430,7431,7432,7434,7435,7437],{},"Watches are called on registration and then only when the evaluated value changes, as in production, so a ",[272,7433,6138],{}," to the value already served calls no watch, while ",[272,7436,3133],{}," still fires.",[923,7439,7440,7442,7443,384,7445,7447],{},[272,7441,2520],{}," has no effect: the test client does not follow the app lifecycle, so backgrounding the app under Robolectric does not pause the connection. Call ",[272,7444,7420],{},[272,7446,5820],{}," to test that path; values set while paused are delivered on resume.",[923,7449,7450,7451,7453],{},"After ",[272,7452,3211],{},", the test client's controls are silent no-ops, and no thread or coroutine from the SDK is left running.",[7455,7456,7457],"style",{},"html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_bVq, html code.shiki .s_bVq{--shiki-light:#9C3EDA;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sfo-9, html code.shiki .sfo-9{--shiki-light:#90A4AE;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":398,"searchDepth":416,"depth":416,"links":7459},[7460,7461,7462,7466,7471,7472,7480],{"id":262,"depth":416,"text":263},{"id":363,"depth":416,"text":364},{"id":917,"depth":416,"text":918,"children":7463},[7464,7465],{"id":1718,"depth":424,"text":1719},{"id":2772,"depth":424,"text":2773},{"id":3518,"depth":416,"text":3519,"children":7467},[7468,7469,7470],{"id":4074,"depth":424,"text":4075},{"id":4357,"depth":424,"text":4358},{"id":4688,"depth":424,"text":4689},{"id":4881,"depth":416,"text":4882},{"id":5731,"depth":416,"text":5732,"children":7473},[7474,7475,7476,7477,7479],{"id":3297,"depth":424,"text":3297},{"id":5757,"depth":424,"text":1155},{"id":5789,"depth":424,"text":5792},{"id":5824,"depth":424,"text":7478},"pauseNetwork() and resumeNetwork()",{"id":3211,"depth":424,"text":1713},{"id":5880,"depth":416,"text":5881,"children":7481},[7482,7483,7484,7485,7486,7487],{"id":6488,"depth":424,"text":6489},{"id":6613,"depth":424,"text":6614},{"id":3669,"depth":424,"text":6939},{"id":7068,"depth":424,"text":7069},{"id":7366,"depth":424,"text":7367},{"id":7397,"depth":424,"text":7398},"Install and configure the Android SDK, evaluate configs and feature flags, and keep your UI current as values change","md",null,{"modifiedAt":7492},"2026-10-12T00:22:49.000Z",{"title":130,"icon":133},{"title":246,"description":7488},"fTuRRUmFERoynRClIaAqx5PJmLUaqS180OKgrC-x2Fw",[7497,7499],{"title":125,"path":126,"stem":127,"description":7498,"icon":128,"children":-1},"Install and configure the Swift SDK, evaluate configs and feature flags, and keep SwiftUI views current as values change",{"title":141,"path":142,"stem":143,"description":7500,"icon":144,"children":-1},"Evaluate configs and feature flags in the browser, in server routes, and during SSR with the Next.js SDK",1791783865135]