Agrega el SDK de Outline a tu app para dispositivos móviles
Organiza tus páginas con colecciones
Guarda y categoriza el contenido según tus preferencias.
En este documento, se describe cómo integrar el SDK de Outline en tus aplicaciones
para dispositivos móviles, con un enfoque en la biblioteca MobileProxy para simplificar la administración del proxy
local.
MobileProxy es una biblioteca basada en Go diseñada para optimizar la integración de las
funciones del proxy en apps para dispositivos móviles. Utiliza Go
para dispositivos móviles con el objetivo de generar bibliotecas para dispositivos móviles, lo que te permite
configurar las bibliotecas de redes de tu app para enrutar el tráfico a través de un proxy
local.
App sin MobileProxy
App con MobileProxy
Paso 1: Compila las bibliotecas MobileProxy para dispositivos móviles
Usa gomobile para compilar
el código de Go en bibliotecas para iOS y Android.
Puedes agregar compatibilidad con el uso de la red de Psiphon
siguiendo estos pasos adicionales:
Comunícate con el equipo de Psiphon para obtener un archivo de configuración que te otorgue acceso a
su red (lo que puede requerir la celebración de un contrato).
Agrega el archivo de configuración de Psiphon a la sección fallback de tu
archivo de configuración SmartDialer.
La marca -tags psiphon es obligatoria porque la base de código de Psiphon tiene
una licencia de GPL, que puede imponer restricciones de licencia en tu propio
código. Te recomendamos que obtengas una licencia especial de Psiphon.
Genera bibliotecas para dispositivos móviles y agrégalas a tu proyecto:
En Android Studio, selecciona File > Import Project… para importar el paquete out/mobileproxy.aar generado. Para obtener más ayuda, consulta la sección Building and deploying to Android del artículo sobre Go para dispositivos móviles.
Arrastra el paquete out/mobileproxy.xcframework al proyecto de Xcode. Para
obtener más ayuda, consulta la sección Building and deploying to iOS del artículo sobre Go para
dispositivos móviles.
Paso 2: Ejecuta MobileProxy
Inicializa e inicia el proxy local MobileProxy en el entorno de ejecución de tu app.
Puedes usar una configuración de transporte estático o el proxy inteligente para
la selección de una estrategia dinámica.
Configuración de transporte estático: Usa la función RunProxy con una dirección
local y una configuración de transporte.
Android
importmobileproxy.*valdialer=StreamDialer("split:3")// Use port zero to let the system pick an open port for you.valproxy=Mobileproxy.runProxy("localhost:0",dialer)// Configure your networking library using proxy.host() and proxy.port() or proxy.address().// ...// Stop running the proxy.proxy.stop()
iOS
importMobileproxyletdialer=MobileproxyStreamDialer("split:3")// Use port zero to let the system pick an open port for you.letproxy=MobileproxyRunProxy("localhost:0",dialer)// Configure your networking library using proxy.host() and proxy.port() or proxy.address().// ...// Stop running the proxy.proxy.stop()
Smart Proxy: Smart Proxy selecciona de forma dinámica estrategias de DNS y TLS
en función de dominios de prueba especificados. Debes especificar la estrategia de
configuración en formato YAML
(ejemplo).
Android
valtestDomains=Mobileproxy.newListFromLines("www.youtube.com\ni.ytimg.com")valstrategiesConfig="..."// Config YAML.valdialer=Mobileproxy.newSmartStreamDialer(testDomains,strategiesConfig,Mobileproxy.newStderrLogWriter())// Use port zero to let the system pick an open port for you.valproxy=Mobileproxy.runProxy("localhost:0",dialer)// Configure your networking library using proxy.host() and proxy.port() or proxy.address().// ...// Stop running the proxy.proxy.stop()
iOS
importMobileproxyvardialerError:NSError?lettestDomains=MobileproxyNewListFromLines("www.youtube.com\ni.ytimg.com")letstrategiesConfig="..."// Config YAML.letdialer=MobileproxyNewSmartStreamDialer(testDomains,strategiesConfig,MobileproxyNewStderrLogWriter(),&dialerError)varproxyError:NSError?// Use port zero to let the system pick an open port for you.MobileproxyRunProxy("localhost:0",dialer,&proxyError)// Configure your networking library using proxy.host() and proxy.port() or proxy.address().// ...// Stop running the proxy.proxy.stop()
Paso 3: Configura clientes HTTP y bibliotecas de redes
Configura tus bibliotecas de redes para que usen el puerto y la dirección del proxy local.
Aplica la configuración de proxy a todas las vistas web de tu aplicación con
la
biblioteca
androidx.webview:
ProxyController.getInstance().setProxyOverride(ProxyConfig.Builder().addProxyRule(this.proxy!!.address()).build(),{},// execution context for the following callback - do anything needed here once the proxy is applied, like refreshing web views{}// callback to be called once the ProxyConfig is applied)
WebView de iOS
A partir de iOS 17, puedes agregar una configuración de proxy a WKWebView usando su
propiedad
WKWebsiteDataStore:
[null,null,["Última actualización: 2025-07-11 (UTC)"],[],[],null,["# Add Outline SDK to your mobile app\n\nThis document outlines how to integrate the Outline SDK into your mobile\napplications, focusing on the `MobileProxy` library for simplified local proxy\nmanagement.\n\n`MobileProxy` is a Go-based library designed to streamline the integration of\nproxy functionalities into mobile apps. It utilizes [Go\nMobile](https://go.dev/wiki/Mobile) to generate mobile libraries, enabling you\nto configure your app's networking libraries to route traffic through a local\nproxy.\n\n**App without MobileProxy**\n\n**App with MobileProxy**\n\nStep 1: Building MobileProxy mobile libraries\n---------------------------------------------\n\nUse [gomobile](https://pkg.go.dev/golang.org/x/mobile/cmd/gomobile) to compile\nthe Go code into libraries for Android and iOS.\n\n1. Clone the Outline SDK repository:\n\n git clone https://github.com/Jigsaw-Code/outline-sdk.git\n cd outline-sdk/x\n\n2. Build the Go Mobile binaries with [`go\n build`](https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies):\n\n go build -o \"$(pwd)/out/\" golang.org/x/mobile/cmd/gomobile golang.org/x/mobile/cmd/gobind\n\n #### Adding Psiphon Support\n\n You can add support to use the [Psiphon](https://psiphon.ca/) network by\n following these extra steps:\n - Contact the Psiphon team to obtain a config that gives you access to their network. This may require a contract.\n - Add the received Psiphon config to the `fallback` section of your `SmartDialer` config.\n - Build the Mobile Proxy using the `-tags psiphon` flag:\n\n go build -tags psiphon -o \"$(pwd)/out/\" golang.org/x/mobile/cmd/gomobile golang.org/x/mobile/cmd/gobind\n\n The `-tags psiphon` flag is required because the Psiphon codebase is\n licensed under the GPL, which can impose license restrictions on your own\n code. You may want to consider obtaining a special license from them.\n3. Generate mobile libraries and add them to your project:\n\n ### Android\n\n PATH=\"$(pwd)/out:$PATH\" gomobile bind -ldflags='-s -w' -target=android -androidapi=21 -o \"$(pwd)/out/mobileproxy.aar\" github.com/Jigsaw-Code/outline-sdk/x/mobileproxy\n\n In Android Studio select **File \\\u003e Import Project...** to import the generated `out/mobileproxy.aar` bundle. For more help see Go Mobile's [Building and deploying to Android](https://go.dev/wiki/Mobile#building-and-deploying-to-android-1).\n\n ### iOS\n\n PATH=\"$(pwd)/out:$PATH\" gomobile bind -ldflags='-s -w' -target=ios -iosversion=11.0 -o \"out/mobileproxy.xcframework\" github.com/Jigsaw-Code/outline-sdk/x/mobileproxy\n\n Drag the `out/mobileproxy.xcframework` bundle to the Xcode project. For\n more help see Go Mobile's [Building and deploying to\n iOS](https://go.dev/wiki/Mobile#building-and-deploying-to-ios-1).\n\nStep 2: Run the MobileProxy\n---------------------------\n\nInitialize and start the `MobileProxy` local proxy within your app's runtime.\nYou can use either a static transport configuration or the Smart Proxy for\ndynamic strategy selection.\n\n- **Static transport configuration** : Use the `RunProxy` function with a local\n address and transport configuration.\n\n ### Android\n\n import mobileproxy.*\n\n val dialer = StreamDialer(\"split:3\")\n\n // Use port zero to let the system pick an open port for you.\n val proxy = Mobileproxy.runProxy(\"localhost:0\", dialer)\n // Configure your networking library using proxy.host() and proxy.port() or proxy.address().\n // ...\n // Stop running the proxy.\n proxy.stop()\n\n ### iOS\n\n import Mobileproxy\n\n let dialer = MobileproxyStreamDialer(\"split:3\")\n\n // Use port zero to let the system pick an open port for you.\n let proxy = MobileproxyRunProxy(\"localhost:0\", dialer)\n // Configure your networking library using proxy.host() and proxy.port() or proxy.address().\n // ...\n // Stop running the proxy.\n proxy.stop()\n\n- **Smart Proxy** : The Smart Proxy dynamically selects DNS and TLS strategies\n based on specified test domains. You need to specify the configuration\n strategy in YAML format\n ([example](https://github.com/Jigsaw-Code/outline-sdk/blob/master/x/examples/smart-proxy/config.yaml)).\n\n ### Android\n\n val testDomains = Mobileproxy.newListFromLines(\"www.youtube.com\\ni.ytimg.com\")\n val strategiesConfig = \"...\" // Config YAML.\n val dialer = Mobileproxy.newSmartStreamDialer(testDomains, strategiesConfig, Mobileproxy.newStderrLogWriter())\n\n // Use port zero to let the system pick an open port for you.\n val proxy = Mobileproxy.runProxy(\"localhost:0\", dialer)\n // Configure your networking library using proxy.host() and proxy.port() or proxy.address().\n // ...\n // Stop running the proxy.\n proxy.stop()\n\n ### iOS\n\n import Mobileproxy\n\n var dialerError: NSError?\n let testDomains = MobileproxyNewListFromLines(\"www.youtube.com\\ni.ytimg.com\")\n let strategiesConfig = \"...\" // Config YAML.\n let dialer = MobileproxyNewSmartStreamDialer(\n testDomains,\n strategiesConfig,\n MobileproxyNewStderrLogWriter(),\n &dialerError\n )\n\n var proxyError: NSError?\n // Use port zero to let the system pick an open port for you.\n MobileproxyRunProxy(\"localhost:0\", dialer, &proxyError)\n // Configure your networking library using proxy.host() and proxy.port() or proxy.address().\n // ...\n // Stop running the proxy.\n proxy.stop()\n\nStep 3: Configure HTTP clients and networking libraries\n-------------------------------------------------------\n\nConfigure your networking libraries to use the local proxy address and port. \n\n### Dart/Flutter HttpClient\n\nSet the proxy with\n[`HttpClient.findProxy`](https://api.flutter.dev/flutter/dart-io/HttpClient/findProxy.html). \n\n HttpClient client = HttpClient();\n client.findProxy = (Uri uri) {\n return \"PROXY \" + proxy.address();\n };\n\n### OkHttp (Android)\n\nSet the proxy with\n[`OkHttpClient.Builder.proxy`](https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/-builder/proxy/). \n\n val proxyConfig = Proxy(Proxy.Type.HTTP, InetSocketAddress(proxy.host(), proxy.port()))\n val client = OkHttpClient.Builder().proxy(proxyConfig).build()\n\n### JVM (Java, Kotlin)\n\nConfigure the proxy to use with [system\nproperties](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html): \n\n System.setProperty(\"http.proxyHost\", proxy.host())\n System.setProperty(\"http.proxyPort\", String.valueOf(proxy.port()))\n System.setProperty(\"https.proxyHost\", proxy.host())\n System.setProperty(\"https.proxyPort\", String.valueOf(proxy.port()))\n\n### Android Web View\n\nApply a proxy configuration to all the web views in your application with\nthe\n[`androidx.webview`](https://developer.android.com/reference/androidx/webkit/ProxyController)\nlibrary: \n\n ProxyController.getInstance()\n .setProxyOverride(\n ProxyConfig.Builder()\n .addProxyRule(this.proxy!!.address())\n .build(),\n {}, // execution context for the following callback - do anything needed here once the proxy is applied, like refreshing web views\n {} // callback to be called once the ProxyConfig is applied\n )\n\n### iOS Web View\n\n\u003cbr /\u003e\n\nAs of iOS 17, you can add a proxy configuration to a `WKWebView` using its\n[`WKWebsiteDataStore`\nproperty](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration): \n\n let configuration = WKWebViewConfiguration()\n let endpoint = NWEndpoint.hostPort(host: NWEndpoint.Host(proxyHost), port: NWEndpoint.Port(proxyPort)!)\n let proxyConfig = ProxyConfiguration.init(httpCONNECTProxy: endpoint)\n let websiteDataStore = WKWebsiteDataStore.default()\n websiteDataStore.proxyConfigurations = [proxyConfig]\n let webview = WKWebView(configuration: configuration)\n\nAdvanced: Generate a custom mobile library\n------------------------------------------\n\nFor advanced use cases, you can generate your own mobile libraries:\n\n1. **Create a Go library**: Develop a Go package wrapping the required SDK functionalities.\n2. **Generate mobile libraries** : Use `gomobile bind` to produce Android Archives (AAR) and Apple Frameworks. Examples:\n - [Outline Android Archive](https://github.com/Jigsaw-Code/outline-apps/blob/7058a89530a25a3de376a6ea2d4433a926787f50/client/go/Taskfile.yml#L67-L81)\n - [Outline Apple Framework](https://github.com/Jigsaw-Code/outline-apps/blob/7058a89530a25a3de376a6ea2d4433a926787f50/client/go/Taskfile.yml#L83-L95)\n3. **Integrate into your app**: Add the generated library to your mobile application.\n\n| **Note:** Use `gomobile bind` on your custom package, not directly on the SDK packages."]]