{"id":18463972,"url":"https://github.com/unleash/unleash-android-proxy-sdk","last_synced_at":"2025-04-08T08:30:54.766Z","repository":{"id":37865066,"uuid":"369129274","full_name":"Unleash/unleash-android-proxy-sdk","owner":"Unleash","description":null,"archived":false,"fork":false,"pushed_at":"2024-07-25T16:25:36.000Z","size":3837,"stargazers_count":7,"open_issues_count":0,"forks_count":16,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-03-23T08:51:12.463Z","etag":null,"topics":["android","featuretoggle","hacktoberfest","unleash"],"latest_commit_sha":null,"homepage":"https://docs.getunleash.io/unleash-android-proxy-sdk","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Unleash.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-20T08:03:07.000Z","updated_at":"2025-03-18T21:49:03.000Z","dependencies_parsed_at":"2023-02-12T02:40:20.359Z","dependency_job_id":"5654b603-6958-4c12-b3ee-f489c093cb55","html_url":"https://github.com/Unleash/unleash-android-proxy-sdk","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-android-proxy-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-android-proxy-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-android-proxy-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Unleash%2Funleash-android-proxy-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Unleash","download_url":"https://codeload.github.com/Unleash/unleash-android-proxy-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247804318,"owners_count":20998949,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","featuretoggle","hacktoberfest","unleash"],"created_at":"2024-11-06T09:08:30.506Z","updated_at":"2025-04-08T08:30:54.449Z","avatar_url":"https://github.com/Unleash.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Unleash Android SDK\n[![Coverage Status](https://coveralls.io/repos/github/Unleash/unleash-android-proxy-sdk/badge.svg?branch=main)](https://coveralls.io/github/Unleash/unleash-android-proxy-sdk?branch=main)\n[![main](https://github.com/Unleash/unleash-android-proxy-sdk/actions/workflows/test.yml/badge.svg)](https://github.com/Unleash/unleash-android-proxy-sdk/actions/workflows/test.yml)\n[![latest](https://badgen.net/maven/v/maven-central/io.getunleash/unleash-android-proxy-sdk)](https://search.maven.org/search?q=g:io.getunleash%20AND%20a:unleash-android-proxy-sdk)\n[KDoc](https://unleash.github.io/unleash-android-proxy-sdk)\n\n# Deprecation notice\nThis repository is deprecated since July 25th of 2024 in favor of [unleash-android](https://github.com/Unleash/unleash-android).\nConsider migrating to the new SDK as this repository will no longer be maintained.\nCheck out the [migration guide](https://github.com/Unleash/unleash-android/blob/main/docs/MigrationGuide.md) for more information.\n\n## Getting started\n\n### Step 1\n\nYou will require the SDK on your classpath, so go ahead and add it to your dependency management file\n\n#### Gradle\n```kotlin\nimplementation(\"io.getunleash:unleash-android-proxy-sdk:${unleash.sdk.version}\")\n```\n#### Maven\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.getunleash\u003c/groupId\u003e\n    \u003cartifactId\u003eunleash-android-proxy-sdk\u003c/artifactId\u003e\n    \u003cversion\u003eLatest version here\u003c/version\u003e\n\u003c/dependency\u003e\n```\n#### Minimum Android SDK\n- We are currently aiming for a minimum SDK level of 21. Keeping in tune with OkHttp's requirement.\n\n#### Proguard\nFor now, you'll need to have Proguard ignore our classes as well as fasterxml (Jackson)\n```\n-keep public class io.getunleash.** {*;}\n-keep class com.fasterxml.** { *; }\n```\n\n### Step 2: Enable internet\n\nYour app will need internet permission in order to reach the proxy. So in your manifest file add\n\n```xml\n\u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\n```\n\n### Step 3: Configure your client instance\n\nNow configure your client instance\n\nYou should use a singleton pattern to avoid file contention on cache directory.\n\n#### Step 3a: Unleash Context\n\nThe important properties to configure on the context are\n* UserId - GradualRolloutStrategies often use this to decide stickiness when assigning which group of users the user end up in\n* SessionId - GradualRolloutStrategies often use this to decide stickiness\n\n```kotlin\nimport io.getunleash.UnleashContext\n\nval context = UnleashContext.newBuilder()\n    .userId(\"However you resolve your userid\")\n    .sessionId(\"However you resolve your session id\") \n    .build()\n```\n\n#### Step 3b: Unleash Config\nTo create a client, use the UnleashConfig.newBuilder method. When building a configuration, you'll need to provide it with:\n\n- `appName`: the name of the application to be used in strategies and metrics\n- `proxyUrl`: the URL the Unleash front-end API is available at **OR** the URL your proxy is available at\n- `clientKey`: the API token or proxy client key you wish to use (this method was known as clientSecret prior to version 0.4.0)\n- `pollMode`: how you want to load the toggle status\n\nAs of v0.1 the SDK supports an automatic polling with an adjustable poll period or loading the state from disk. Most users will probably want to use the polling client, but it's nice to know that you can instantiate your client without actually needing Internet if you choose loading from File\n\n\n##### Connection options\n\nTo connect this SDK to your Unleash instance's [front-end API](https://docs.getunleash.io/reference/front-end-api), use the URL to your Unleash instance's front-end API (`\u003cunleash-url\u003e/api/frontend`) as the `proxyUrl` argument. For the `clientKey` parameter, use a `FRONTEND` token generated from your Unleash instance. Refer to the [_how to create API tokens_](https://docs.getunleash.io/how-to/how-to-create-api-tokens) guide for the necessary steps.\n\nTo connect this SDK to the [Unleash proxy](https://docs.getunleash.io/reference/unleash-proxy), use the proxy's URL and a [proxy client key](https://docs.getunleash.io/reference/api-tokens-and-client-keys#proxy-client-keys). The [_configuration_ section of the Unleash proxy docs](https://docs.getunleash.io/reference/unleash-proxy#configuration) contains more info on how to configure client keys for your proxy.\n\n\n##### Step 3b: Configure client polling proxy\n\nConfiguring a client with a 60 seconds poll interval:\n\n```kotlin\nval config = UnleashConfig.newBuilder()\n    .appName(\"Your AppName\")\n    .proxyUrl(\"URL to your front-end API or proxy\")\n    .clientKey(\"your front-end API token or proxy client key\")\n    .pollingMode(PollingModes.autoPoll(60) { // poll interval in seconds\n        featuresUpdated()\n    })\n    .build()\n```\n\n##### Step 3b: Configure client loading toggles from a file\n\nIf you need to have a known state for your UnleashClient, you can perform a query against the proxy using your HTTP client of choice and save the output as a json file. Then you can tell Unleash to use this file to setup toggle states.\n\n```kotlin\nimport io.getunleash.UnleashConfig\nimport io.getunleash.polling.PollingModes\n\nval toggles = File(\"/tmp/proxyresponse.json\")\nval pollingMode = PollingModes.fileMode(toggles)\n\nval config = UnleashConfig.newBuilder()\n    .appName(\"Your AppName\")\n    .proxyUrl(\"Doesn't matter since we don't use it when sent a file\")\n    .clientKey(\"Doesn't matter since we don't use it when sent a file\")\n    .pollMode(pollingMode)\n    .build()\n```\n\n### Step 4: Instantiate the client\nHaving created your UnleashContext and your UnleashConfig you can now instantiate your client. Make sure you only do this once, and pass the instantiated client to classes/functions that need it.\n\n```kotlin\nimport io.getunleash.UnleashClient\n\nval unleashClient = UnleashClient(unleashConfig = config, unleashContext = context)\n```\n\n### Details\n#### PollingModes\n##### Autopolling\nIf you'd like for changes in toggles to take effect for you; use AutoPolling.\nYou can configure the pollInterval and a listener that gets notified when toggles are updated in the background thread. \nIf you set the poll interval to 0, the SDK will fetch once, but not set up polling.\n\nThe listener is a no-argument lambda that gets called by the RefreshPolicy for every poll that\n1. Does not return `304 - Not Modified`\n2. Does not return a list of toggles that's exactly the same as the one we've already stored in local cache. Just in case the ETag/If-None-Match fails.\n\nExample usage is equal to the `Example setup` above\n```kotlin\nval context = UnleashContext.newBuilder()\n    .userId(\"However you resolve your userid\")\n    .sessionId(\"However you resolve your session id\")\n    .build()\nval config = UnleashConfig.newBuilder()\n    .appName(\"Your AppName\")\n    .proxyUrl(\"URL to your front-end API or proxy\")\n    .clientKey(\"your front-end API token or proxy client key\")\n    .pollingMode(PollingModes.autoPoll(60) { // poll interval in seconds\n        featuresUpdated()\n    })\n    .build()\nval client = UnleashClient(unleashConfig = config, unleashContext = context)\n```\n\n##### FilePolling (since v0.2)\nThe name `FilePolling` can be a tad misleading, since this policy doesn't actually poll, it simply loads a file of toggles from disk on startup, and uses that to answer all client calls.\nUseful when your app might have limited internet connectivity, you'd like to run tests with a known toggle state or you simply do not want background activity.\n\nThe following example shows how to use it, provided the file to use is located at /tmp/proxyresponse.json\n```kotlin\nval toggles = File(\"/tmp/proxyresponse.json\")\nval pollingMode = PollingModes.fileMode(toggles)\nval context = UnleashContext.newBuilder()\n    .userId(\"However you resolve your userid\")\n    .sessionId(\"However you resolve your session id\")\n    .build()\nval config = UnleashConfig.newBuilder()\n    .appName(\"Your AppName\")\n    .proxyUrl(\"URL to your front-end API or proxy\") // These two don't matter for FilePolling,\n    .clientKey(\"front-end API token / proxy client key\") // since the client never speaks to the proxy\n    .pollingMode(pollingMode)\n    .build()\nval client = UnleashClient(unleashConfig = config, unleashContext = context)\n\n```\n\n### Metrics (since v0.2)\nMetrics are automatically posted to the upstream, so the admin interface can be updated. To disable automatic metrics posting, call `disableMetrics()` on the builder.\n\nThe default configuration configures a daemon to report metrics once every minute, this can be altered using the `metricsInterval(long milliseconds)` method on the builder, so if you'd rather see us post in 5 minutes intervals you could do\n```kotlin\nUnleashConfig().newBuilder().metricsInterval(300000) // Every 5 minutes\n```\n\n#### Example main activity\nIn [the sample app](./samples/android/app/src/main/java/com/example/unleash/MainActivity.kt)\nwe use this to update the text on the first view\n\n```kotlin\n this@MainActivity.runOnUiThread {\n    val firstFragmentText = findViewById\u003cTextView\u003e(R.id.textview_first)\n    firstFragmentText.text = \"Variant ${unleashClient.getVariant(\"unleash_android_sdk_demo\").name}\"\n }\n```\n\n## Releasing\n\n### Create a github tag prefixed with v\n- So, if you want to release 0.6.0, make a tag v0.6.0 and push it.\n### Using gradle\n- To release next patch version run `./gradlew release`\n\n## Publishing to Maven central\nThis is automatically handled when tags with v prefix is created in the repo. See `.github/workflows/deployrelease.yml`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funleash%2Funleash-android-proxy-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funleash%2Funleash-android-proxy-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funleash%2Funleash-android-proxy-sdk/lists"}