# Welcome to Onion Mobile Devs!

Where to begin with integrating Tor support into your mobile app or service

Tor, a [free and open-source software](/the-history-of-tor) for enabling anonymous communication, routes Internet traffic through a worldwide, volunteer overlay network, consisting of thousands of relays, to conceal a user's location and usage from network surveillance or traffic analysis. By integrating [Tor into your mobile app](/mobile-concepts/mobile-apps-with-tor), you provide your users with the ability to [maintain privacy and evade censorship](/the-tor-protocol).

By the end of this guide, you will have a thorough understanding of how to [integrate Tor into a mobile application](/mobile-concepts/all-the-ways-to-tor), aligning with the best practices of open-source development and contributing to the broader goal of [promoting online privacy and freedom](/the-history-of-tor).

<figure><img src="/files/3go1sv9L8RCQMrmNRwQl" alt=""><figcaption><p>Classic Orbot user interface.... the original Tor on Mobile app!</p></figcaption></figure>


# The History of Tor

About Tor, Tor Project and Onion Routing

The [Tor Project, Inc,](https://torproject.org) became a 501(c)(3) nonprofit in 2006, but the idea of "onion routing" [began in the mid 1990s](https://www.onion-router.net/).

Just like Tor users, the developers, researchers, and founders who've made Tor possible are a diverse group of people. But all of the people who have been involved in Tor are united by a common belief: internet users should have private access to an uncensored web.

<figure><img src="/files/pCYWpMUpnG0kPIITwSIU" alt=""><figcaption><p>The Humans of Tor</p></figcaption></figure>

In the 1990s, the lack of security on the internet and its ability to be used for tracking and surveillance was becoming clear, and in 1995, David Goldschlag, Mike Reed, and Paul Syverson at the U.S. Naval Research Lab (NRL) asked themselves if there was a way to create internet connections that don't reveal who is talking to whom, even to someone monitoring the network. Their answer was to create and deploy the first research designs and prototypes of onion routing.

The goal of onion routing was to have a way to use the internet with as much privacy as possible, and the idea was to route traffic through multiple servers and encrypt it each step of the way. This is still a simple explanation for how Tor works today.

In the early 2000s, Roger Dingledine, a recent [Massachusetts Institute of Technology (MIT)](https://web.mit.edu/) graduate, began working on an NRL onion routing project with Paul Syverson. To distinguish this original work at NRL from other onion routing efforts that were starting to pop up elsewhere, Roger called the project Tor, which stood for The Onion Routing. Nick Mathewson, a classmate of Roger's at MIT, joined the project soon after.

From its inception in the 1990s, onion routing was conceived to rely on a decentralized network. The network needed to be operated by entities with diverse interests and trust assumptions, and the software needed to be free and open to maximize transparency and decentralization. That's why in October 2002 when the Tor network was initially deployed, its code was released under a free and open software license. By the end of 2003, the network had about a dozen volunteer nodes, mostly in the U.S., plus one in Germany.

Recognizing the benefit of Tor to digital rights, the [Electronic Frontier Foundation (EFF)](https://www.eff.org/) began funding Roger's and Nick's work on Tor in 2004. In 2006, the Tor Project, Inc., a 501(c)(3) nonprofit organization, was founded to maintain Tor's development.

In 2007, the organization began developing bridges to the Tor network to address censorship, such as the need to get around government firewalls, in order for its users to access the open web.

Tor began gaining popularity among activists and tech-savvy users interested in privacy, but it was still difficult for less-technically savvy people to use, so starting in 2005, development of tools beyond just the Tor proxy began. Development of Tor Browser began in [2008](https://lists.torproject.org/pipermail/tor-talk/2008-January/007837.html).

With Tor Browser having made Tor more accessible to everyday internet users and activists, Tor was an instrumental tool during the [Arab Spring](https://en.wikipedia.org/wiki/Arab_Spring) beginning in late 2010. It not only protected people's identity online but also allowed them to access critical resources, social media, and websites which were blocked.

The need for tools safeguarding against mass surveillance became a mainstream concern thanks to the [Snowden revelations in 2013](https://www.theguardian.com/world/interactive/2013/nov/01/snowden-nsa-files-surveillance-revelations-decoded#section/1). Not only was Tor instrumental to Snowden's whistleblowing, but content of the documents also upheld assurances that, at that time, [Tor could not be cracked](https://www.wired.com/story/the-grand-tor/).

People's awareness of tracking, surveillance, and censorship may have increased, but so has the prevalence of these hindrances to internet freedom. Today, the network has [thousands of relays](https://metrics.torproject.org/) run by volunteers and millions of users worldwide. And it is this diversity that keeps Tor users safe.


# The Tor Protocol

How Tor works at the packet and network level

<figure><img src="/files/q8AvTEMe95LGzxFI1drN" alt=""><figcaption><p><a href="https://unit42.paloaltonetworks.com/tor-traffic-enterprise-networks/">"Tor 101"</a> from Palo Alto Networks</p></figcaption></figure>

Internet communication is based on a store-and-forward model that can be understood in analogy to postal mail: Data is transmitted in blocks called IP datagrams or packets. Every packet includes a source IP address (of the sender) and a destination IP address (of the receiver), just as ordinary letters contain postal addresses of sender and receiver. The way from sender to receiver involves multiple hops of routers, where each router inspects the destination IP address and forwards the packet closer to its destination. Thus, every router between sender and receiver learns that the sender is communicating with the receiver. In particular, your local ISP is in the position to build a complete profile of your Internet usage. In addition, every server in the Internet that can see any of the packets can profile your behavior.

The aim of Tor is to improve your privacy by sending your traffic through a series of proxies. Your communication is encrypted in multiple layers and routed via multiple hops through the Tor network to the final receiver. More details on this process can be found in this [visualization](https://support.torproject.org/https/https-1/). Note that all your local ISP can observe now is that you are communicating with Tor nodes. Similarly, servers in the Internet just see that they are being contacted by Tor nodes.

Generally speaking, Tor aims to solve three privacy problems:

**First**, Tor prevents websites and other services from learning your location, which they can use to build databases about your habits and interests. With Tor, your Internet connections don't give you away by default -- now you can have the ability to choose, for each connection, how much information to reveal.

**Second**, Tor prevents people watching your traffic locally (such as your ISP or someone with access to your home wifi or router) from learning what information you're fetching and where you're fetching it from. It also stops them from deciding what you're allowed to learn and publish -- if you can get to any part of the Tor network, you can reach any site on the Internet.

**Third**, Tor routes your connection through more than one Tor relay so no single relay can learn what you're up to. Because these relays are run by different individuals or organizations, distributing trust provides more security than the old [one hop proxy](https://support.torproject.org/about/how-is-tor-different-from-other-proxies/) approach.

Note, however, that there are situations where Tor fails to solve these privacy problems entirely: see the entry below on [remaining attacks](https://support.torproject.org/about/attacks-on-onion-routing/).


# Tor ("C Tor") vs Arti: What?!

The state of the two primary Tor implementations

For software projects with recurring bugs, efficiency or security issues there’s a joke making the rounds in the software industry: “Let’s re-write it in [Rust](https://en.wikipedia.org/wiki/Rust_\(programming_language\))!” It’s a fairly new low-level programming language with the declared goal to help developers avoid entire classes of bugs, security issues and other pitfalls. Re-writing software is very time consuming, so it rarely happens, especially when just one more fix will keep a project up and running.

[Tor-Project](https://torproject.org/) was started in 2001 using the [C programming lanugage](https://en.wikipedia.org/wiki/C_\(programming_language\)). However a few years ago they set out to actually re-write their project in Rust. That projects codename is [Arti](https://arti.torproject.org/) and it was [first released](https://blog.torproject.org/arti_100_released/) in 2022. While Arti is working great, it doesn’t have all features of the original Tor implementation yet. However, they are steadily working on getting there. For example, rough [Pluggable Transports](https://www.pluggabletransports.info/) support was added to [Arti in the recent 1.1.0 release](https://blog.torproject.org/arti_111_released/).

<figure><img src="/files/cdRSSJTBYjWNn6FWiEQe" alt=""><figcaption></figcaption></figure>

We already have early [test builds of Arti](https://gitlab.com/guardianproject/arti-mobile-ex/) running on both Android and iOS. The integration we came up with is pretty basic, but so far it seems to work reliable for accessing the Tor network. Maintaining code for both iOS and Android in the same project will hopefully simplify shipping new Arti releases for us, make integrating Tor capabilities into any app simpler. To make it useful for the broader mobile developer community, we’re also investigating whether we can provide easy to use API bindings. We’ve created a [sample app](https://gitlab.com/guardianproject/arti-mobile-ex/-/tree/main/android/sample) on Android to test and illustrate what a minimalistic integration of Arti looks like. It’s as simple as adding a few lines of code.

Support for features like advanced censorship circumvention or onion services is not exactly straight forward on mobile operating systems, because they tend to be way more locked down than traditional computers. Currently, we can successfully test pluggable transports in “managed” mode on old versions of Android. However this technique will likely not work on the latest version of Android and never worked on iOS to begin with. We have shared our findings with the Arti developer team and hope they’ll work on getting us to full Pluggable Transports support, integraing with our existing [IPtProxy Library](https://gitlab.com/guardianproject/IPtProxy) soon.


# Mobile Apps with Tor

Summary of known mobile applications with Tor Support

{% embed url="<https://www.youtube.com/watch?v=F1ddl6XMnQU>" %}
From 2020 - a summary of some mobile apps with Tor at that time
{% endembed %}

[**Orbot: Tor VPN for Android and iOS**](https://orbot.app)

Orbot is a free proxy app that empowers other apps to use the internet more securely. It uses Tor to encrypt your internet traffic and then hides it by bouncing through a series of computers around the world. Orbot is the only app that creates a truly private internet connection on Android and iOS devices. As a Tor VPN, it provides the benefits of the Tor network to mobile users, ensuring privacy and access to blocked websites and services.

[**Tor Browser for Android**](https://torproject.org)

Tor Browser for Android is the official Tor Project browser for Android devices. It's a mobile browser that focuses on privacy and security, allowing users to browse the internet anonymously. The browser blocks trackers, defends against surveillance, and resists fingerprinting. It’s built on the same principles as the desktop version, providing a similar experience of private and secure web browsing on mobile devices.

[**OnionBrowser for iOS**](https://onionbrowser.com)

Like Tor Browser, OnionBrowser is a mobile browser that focuses on privacy and security, allowing users to browse the internet anonymously through built-in Tor support on iOS devices. In this case, it is built upon the Apple WKWebView component, which provides its own methods for enhancing privacy and reducing tracking that OnionBrowser takes advantage of. It isn't a 1-1 perfect clone of Tor Browser, but it does everything possible to be at parity within the constraints of the Apple operating system.

[**OnionShare for Android and iOS**](https://onionshare.org/mobile)

OnionShare is an open-source tool that lets you securely and anonymously share files, host websites, and chat using the Tor network. Available for both Android and iOS, this app sets up a secure server directly on your device, allowing you to send and receive files without any third-party involvement. The unique aspect of OnionShare is its use of onion services, ensuring that all data remains encrypted and private during transit.

[**F-Droid for Android**](https://f-droid.org)

F-Droid is an installable catalogue of FOSS (Free and Open Source Software) applications for the Android platform. It functions as an alternative to Google Play Store, focusing on privacy and security. Users can browse, install, and keep track of updates on their device in a similar manner to other app stores, but with the assurance that the apps are open-source and have gone through a rigorous vetting process.

[**Briar**](https://briarproject.org/)

Briar is a unique messaging app designed for activists, journalists, and anyone needing a safe and secure communication platform. Unlike conventional messaging apps, Briar doesn’t rely on a central server - messages are synchronized directly between users' devices. If the internet's down, Briar can sync via Bluetooth or Wi-Fi, keeping the information flowing in a crisis. It's perfect for those in situations where security and privacy are paramount.

[**Save by OpenArchive**](https://open-archive.org/save)

Save by OpenArchive is a mobile app designed to help users preserve, protect, and authenticate their digital media. It allows individuals to securely archive their media to trusted, decentralized, and long-term storage providers. The app ensures that valuable digital information, such as videos and photos, are protected from loss, manipulation, or deletion. It's an essential tool for journalists, human rights activists, and archivists who need to safeguard digital evidence and important media assets.

[**Quiet**](https://tryquiet.org)

Whether it's for an organization, a community, or a group chat with friends, Quiet lets you control all your data without running your own servers. While apps like Slack, Discord, and Signal use central servers, Quiet syncs messages directly between a team’s devices, over Tor, with no server required. Quiet stores your community's data only on your community's phones and laptops, so it's always under your control. Quiet gives you a peer-to-peer network that just works, so you can be independent and private without running your own server.

Each of these apps offers unique features and capabilities, particularly focusing on privacy, security, and open-source development, catering to specific needs in the digital privacy and mobile communication space.


# Possible Ways to Tor Your App

Summary of different ways an app can integrate with Tor

{% embed url="<https://www.youtube.com/watch?v=DgWZjP1UkxQ>" %}
Tor Ecosystem on Mobile from Tor State of the Onion 2023
{% endembed %}

### Build Tor into your app

It is now easier than ever to directly build Tor into your app, hiding all complexity of setup and configuration from your users. Whether you use [Tor-Android](/tor-on-android/tor-android-library), [Arti](/tor-c-tor-vs-arti-what), or [Tor.framework](/tor-on-ios/tor.framework-for-ios), there are many options ready to go. Apps like Tor Browser for Android do this today, to provide a seamless, integrated experience for browsing the web over Tor.

### Integrate with external Orbot or TorServices app

If you do not want to add the additional code complexity and size directly into your app, you can instead only offer active Tor features if the user has [Orbot](/tor-on-android/netcipher-with-orbot-legacy) or [TorServices](/tor-on-android/torservices) installed on their device. Apps like [F-Droid](/mobile-concepts/mobile-apps-with-tor), [Save by OpenArchive](/mobile-concepts/mobile-apps-with-tor), and [ReThinkDNS](/mobile-concepts/mobile-apps-with-tor) do this today, to enable proxying through Tor without having to build in all of Tor.

### Implement Tor in a VPN or Network Extension

If you want to build your own VPN, or want to ensure that all possible network traffic from your app (and even the whole device) is automatically routed through Tor, then this might be the approach you take. Apps like Orbot do this today, to provide an easy Tor-based "VPN" for users.

### Run an OnionService in your app

Using Tor, you can turn your app into a server, that any other Tor client can connect to. This enables you to host content and services just like you are on the open web, directly from your device. Apps like [OnionShare](/mobile-concepts/mobile-apps-with-tor), [Briar](/mobile-concepts/mobile-apps-with-tor) and [Quiet](/mobile-concepts/mobile-apps-with-tor) do this today to enable file sharing and chat.


# Limitations of Mobile Devices

Aspects of mobile device challenges that should always be considered when integrating Tor

## <mark style="color:purple;">**Processing Power**</mark>

### Tor's encryption and routing mechanisms require significant processing power.&#x20;

On mobile devices, this can lead to slower performance, especially on lower-end models. Developers must optimize Tor integration to minimize CPU usage and ensure that the app remains responsive while maintaining the security and anonymity features of Tor.

## <mark style="color:purple;">**Battery Impact**</mark>

### The Tor network, due to its layered encryption and routing through multiple nodes, can be more power-intensive compared to standard internet connections.&#x20;

This increased power consumption can drain the battery faster. Developers need to optimize the Tor integration for energy efficiency, perhaps by managing when and how frequently the app accesses the Tor network.

## <mark style="color:purple;">**Storage Impact**</mark>

### Tor integration can increase an app's size and storage requirements.&#x20;

The additional libraries and cache data associated with Tor can occupy significant space on a mobile device. Efficient storage management and minimization of the app's footprint are essential to ensure it doesn't consume excessive storage space.

## <mark style="color:purple;">**Operating System**</mark>

### Different operating systems (iOS, Android) have varied levels of support and limitations for Tor integration.&#x20;

For instance, iOS has more stringent background process limitations, which can affect Tor's functionality. Developers must understand and work within each platform's constraints to effectively integrate Tor.

## <mark style="color:purple;">**Bandwidth Speeds**</mark>

### Tor typically has a slower connection speed due to its multi-node routing.&#x20;

This can be more pronounced on mobile devices, where bandwidth might already be limited. Optimizing data usage and managing user expectations regarding connection speeds are crucial aspects of integrating Tor on mobile.

## <mark style="color:purple;">**Network Performance**</mark>

### Mobile network connectivity can be inconsistent, impacting Tor's performance.&#x20;

Switching between Wi-Fi and mobile data or dealing with poor connectivity can disrupt the Tor connection, necessitating robust network handling strategies within the app.

## <mark style="color:purple;">**Screen Size and User Interface**</mark>

### The smaller screen size of mobile devices means less room to indicate Tor status.

Any user interfaces related to Tor (such as settings, status indicators) need to be carefully designed to be clear and usable on a small display. This involves thoughtful UI/UX design to accommodate Tor's complex functionalities in a simplified manner.

## <mark style="color:purple;">**Foreground vs Background Modes**</mark>

### Mobile operating systems often restrict what apps can do in the background.&#x20;

This can impact Tor's functionality, as maintaining an anonymous connection might require persistent background activity. Developers need to navigate these restrictions to maintain Tor's effectiveness, especially when the app is not in the foreground.

## <mark style="color:purple;">Addressing these challenges requires a careful balancing act between maintaining the integrity of Tor's privacy and security features and providing a smooth, user-friendly experience on mobile devices.</mark>


# Mobile Users in the OnionVerse

Why and how a user of an app might benefit from Tor integration

User personas are a key component of [Tor's human-centered design process](https://community.torproject.org/user-research/). They help foster empathy by encouraging our developers to better understand the motivations, pain points and goals of our users. The f[irst generation of Tor personas](https://community.torproject.org/user-research/personas/) were created following a series of field studies in the Global South from 2018 to 2019, where we were fortunate to meet many different kinds of Tor users – including activists, journalists and other human rights defenders. You can view them all on the [Tor Persona User Research page](https://community.torproject.org/user-research/personas/).

Below are some additional lightweight, mobile centric user stories that can also help consider the types of users who may benefit from Tor support being built into your app.

**User Needs to Use App in a Place Where It May Be Blocked**

<figure><img src="https://images.unsplash.com/photo-1569016832321-084c128adeb8?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw4fHxqb3VybmFsaXN0fGVufDB8fHx8MTcwMTIwMzgyNXww&#x26;ixlib=rb-4.0.3&#x26;q=85" alt=""><figcaption><p>Alex, a journalist working in a region with strict internet censorship</p></figcaption></figure>

Imagine a user, Alex, a journalist working in a region with strict internet censorship. Alex needs to access vital information and communicate with their team using a specific app. However, in the region where Alex is stationed, this app is blocked by the government. Alex relies on this app for up-to-date information and coordination with their team. The ability to use the app in such a restrictive environment is crucial for Alex to perform their job effectively and safely. They need a solution that allows them to bypass these blockages without drawing attention to their activities, ensuring they can access the necessary information and maintain communication with their colleagues.

**User Wants to Share Data Privately and Directly**

<figure><img src="https://images.unsplash.com/photo-1591848478625-de43268e6fb8?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwxfHxhY3RpdmlzdHxlbnwwfHx8fDE3MDEyMDM4NzZ8MA&#x26;ixlib=rb-4.0.3&#x26;q=85" alt=""><figcaption><p>Sarah, a human rights activist</p></figcaption></figure>

Consider Sarah, a human rights activist, who needs to share sensitive documents with her network. These documents contain critical evidence of human rights violations, and it is imperative that this exchange remains confidential and direct, without any third-party interception. Sarah is aware of the risks involved in digital communication and seeks a way to share these files securely. She needs a method that ensures end-to-end encryption, where only the intended recipient can access the data. The solution must be reliable and straightforward, as some of her colleagues are not tech-savvy. The ability to share these sensitive documents safely can have significant implications for her cause.

**User Wants to Search or Browse Data Without It Being Linked to Their IP Address**

<figure><img src="https://images.unsplash.com/photo-1622556498246-755f44ca76f3?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHwxfHxwZXJzb24lMjB1c2luZyUyMHBob25lfGVufDB8fHx8MTcxNjMzNTMwOXww&#x26;ixlib=rb-4.0.3&#x26;q=85" alt=""><figcaption></figcaption></figure>

Envision Tom, a researcher who frequently needs to access various online resources for his work. However, Tom is concerned about privacy and does not want his searches and browsing history to be tracked or linked to his IP address. He is wary of surveillance and data collection practices that could compromise his anonymity and the confidentiality of his research. Tom seeks a solution that allows him to browse the internet freely, without leaving a digital footprint that could be traced back to him. This capability is not just a matter of privacy but also a professional necessity to ensure the integrity and confidentiality of his research work.

*In each of these scenarios, the users face distinct challenges that necessitate robust, privacy-focused solutions. Whether it's bypassing censorship, secure data sharing, or anonymous browsing, each scenario underscores the importance of having access to tools and technologies that protect digital privacy and ensure secure communication.*


# All The Onions on Android

Summary of ways to integrate Tor on Android devices

* Tor-Android <https://github.com/guardianproject/tor-android/>
  * Android is a mobile operating system
* TorService / NetCipher <https://gitlab.com/guardianproject/torservices>
* IPtProxy Pluggable Transports: <https://github.com/tladesignz/IPtProxy/>
* Arti Mobile: <https://gitlab.com/guardianproject/arti-mobile-ex>

<figure><img src="/files/382FBDpvnjmHH6ltq6ai" alt=""><figcaption></figcaption></figure>


# Tor-Android library

Integrating Tor directly into your mobile app

Source repository: <https://github.com/guardianproject/tor-android/>

Easy to integrate as a Maven dependency

```
dependencies {
    implementation 'info.guardianproject:tor-android:0.4.8.7'
    implementation 'info.guardianproject:jtorctl:0.4.5.7'
}
```

Bind to Tor as a Service

```
bindService(new Intent(this, TorService.class), new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {

                TorService torService = ((TorService.LocalBinder) service).getService();

                Toast.makeText(MainActivity.this, "Got Tor control connection", Toast.LENGTH_LONG).show();
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        },BIND_AUTO_CREATE);
```


# Pluggable Transports for Android

Lyrebird/Obfs4proxy and Snowflake Pluggable Transports for iOS, MacOS and Android

IPtProxy is the primary reusable library for integrating the latest anti-censorhip capabilities into your mobile app. You can find IPtProxy at <https://gitlab.com/guardianproject/IPtProxy> with the "live" development work also done at <https://github.com/tladesignz/IPtProxy/>

Both Lyrebird/Obfs4proxy and Snowflake Pluggable Transports are written in Go, which is a little annoying to use on iOS and Android. This project encapsulates all the machinations to make it work and provides an easy to install binary including a wrapper around both.

Problems solved in particular are:

* One cannot compile `main` packages with `gomobile`. Both PTs are patched to avoid this.
* Both PTs are gathered under one roof here, since you cannot have two `gomobile` frameworks as dependencies, since there are some common Go runtime functions exported, which would create a name clash.
* Environment variable changes during runtime will not be recognized by `goptlib` when done from within Swift/Objective-C. Therefore, sensible values are hardcoded in the Go wrapper.
* Snowflake and Lyrebird/Obfs4proxy are patched to accept all configuration parameters directly.
* Free ports to be used are automatically found by this library and returned to the consuming app. You can use the initial values for premature configuration, which is just fine in situations, where you can be pretty sure, they're going to be available (typically on iOS). When that's not the case (e.g. multiple instances of your app on a multi-user Android), you should first start the transports and then use the returned ports for configuration of other components (e.g. Tor).


# NetCipher with Orbot (Legacy)

Time-tested way to integrate with Orbot for Android

You can find the NetCipher homepage at <https://guardianproject.info/code/netcipher/>

NetCipher is a library for Android that provides multiple means to improve network security in mobile applications. It provides best practices TLS settings using the standard Android methods [`HttpURLConnection`](https://developer.android.com/reference/java/net/HttpURLConnection.html), OkHTTP3, Volley, and [Apache HTTP Client](https://hc.apache.org/httpcomponents-client-4.3.x/index.html), provides simple Tor integration, makes it easy to configure proxies for HTTP connections and `WebView` instances.

<figure><img src="/files/DuoDi9hEgbZzG5I4smzy" alt=""><figcaption></figcaption></figure>

More specifically this library provides:

* Hardening of TLS protocol support and cipher suites, especially on older\
  versions of Android
* Proxied Connection Support: HTTP and SOCKS proxy connection support for HTTP\
  and HTTPS traffic through specific configuration
* OrbotHelper: a utility class to support application integration with Orbot\
  (Tor for Android). Check if its installed, automatically start it, etc.
* Optional, custom certificate store based on the open Debian root CA trust\
  store, which is built with Mozilla’s CA collection.

IT MUST BE NOTED, that you can use this library without using Orbot/Tor, but obviously we think using strong TLS/SSL connections over Tor is just about the best thing in the world.

[NetCipher](https://guardianproject.info/code/netcipher) has been relatively quiet in recent years, because it kept on working, doing it was doing. Now, we have had some recent discoveries about the guts of Android that mean NetCipher is a lot easier to use on recent Android versions. On top of that, TLSv1.2 now reigns supreme and is basically everywhere, so it is time to turn TLSv1.0 and TLSv1.1 entirely off.

### A single method to enable proxying for the whole app <a href="#a-single-method-to-enable-proxying-for-the-whole-app" id="a-single-method-to-enable-proxying-for-the-whole-app"></a>

As of Android 8.0 (26 aka Oreo), it is now possible to set a `URLStreamHandlerFactory`, which creates `URLConnection` instances with custom configurations. If an app is using the built-in `HttpURLConnection` API for its networking, it is now possible to enable global proxying with a single method call when the app starts: [`NetCipher.useGlobalProxy()`](https://guardianproject.github.io/NetCipher/libnetcipher/info/guardianproject/netcipher/NetCipher.html#useGlobalProxy--). Then the actual proxy configuration can be set dynamically, using things like [`NetCipher.useTor()`](https://guardianproject.github.io/NetCipher/libnetcipher/info/guardianproject/netcipher/NetCipher.html#useTor--) or [`NetCipher.clearProxy()`](https://guardianproject.github.io/NetCipher/libnetcipher/info/guardianproject/netcipher/NetCipher.html#clearProxy--).

The `URL.setURLStreamHandlerFactory()` method is a little odd because it cannot be unset or changed after it has been set. NetCipher handles this by letting the app configure the proxy settings separately, so they can be disabled even though the custom `URLStreamHandlerFactory` is still active. Also, it is possible to use `URL.setURLStreamHandlerFactory` on Android 7.x also, but it leaks DNS, so it is not recommended for privacy proxies. It would still be useful as a failsafe for apps that use [`NetCipher.getHttpURLConnection()`](https://guardianproject.github.io/NetCipher/libnetcipher/info/guardianproject/netcipher/NetCipher.html#getHttpURLConnection-java.lang.String-), in case there are any calls to `URL.openConnection()` added with the right proxy setup. At the very least, the content will be proxied on Android 7.x, even if it leaks DNS.

### Native SOCKS Support <a href="#native-socks-support" id="native-socks-support"></a>

In Android 7.0 (24 aka Nougat), Google switched over to OpenJDK, which brought working SOCKS support to Android. SOCKS is the best protocol for effective proxying, and it is the protocol that Tor itself has always natively supported. Orbot has always provided a separaete HTTP Proxy to support Android, but that has always proven brittle, and was often the source of problems. Since Android 7.0 and above natively support SOCKS, calling `NetCipher.useTor()` will now default to using SOCKS if the device is running Android 7.0 or higher.

### Bye bye TLSv1.0 and TLSv1.1 <a href="#bye-bye-tlsv1-0-and-tlsv1-1" id="bye-bye-tlsv1-0-and-tlsv1-1"></a>

Transport Layer Security (TLS) is the protocol that powers most of the internet these days. It gives HTTPS the S for “Secure”. After many years of slow updates and an increasing number of vulnerabilities, there is finally critical mass to stop using the old, broken versions. TLS version 1.2 is not seriously vulnerable and is supported basically everywhere. TLSv1.2 was finalized in 2008, so this is very far from the bleeding edge. TLSv1.2 is supported all the way back to [Android 4.1](https://developer.android.com/reference/javax/net/ssl/SSLSocket#protocols). TLSv1.0 and TLSv1.1 are due to be officially deprecated by the IETF, the standards body that actually creates the TLS standard. The major browser vendors have all promised to drop them in 2020.

One way to enforce TLSv1.2 support would be to configure the server-side to stop supporting TLSv1.0 and TLSv1.1, like is recommend with SSLv2 and SSLv3. Using NetCipher to do this on the client side means that old app versions and old devices will continue to work. Also, doing it client-side means that all TLS connections will gain this protection regardless of which server the client is connecting to.

The *NetCipher* approach means apps will never use TLS older than v1.2 since they will refuse to connect unless TLSv1.2 is available. The server-side can then safely support TLSv1.0 and TLSv1.1, so older clients and Android devices will still be able to connect, even if they do not support TLSv1.2. It is win-win for everyone.

The one case that will fail entirely is connections to servers that do not support TLSv1.2. If a webserver does not support TLSv1.2, it is really too old to be used safely anyway. Even the oldest supported Red Hat Enterprise Linux release (6) supports TLSv1.2, and that was released in 2010.

### `WebView` Proxying! <a href="#webview-proxying" id="webview-proxying"></a>

[`WebView`](https://developer.android.com/reference/android/webkit/WebView) provides an easy way to show a webpage or build a web app. If you want that page to always go over Tor, that is difficult since `WebView` has no API to configure proxying. NetCipher has a long running collection of hacks that span the Android versions to get proxying working in `WebView`. We have revived those, modernized them, and added a full test suite to confirm whether the proxying is leaking. The good news is that proxying is working pretty well on all but Android 5.x (21 and 22), where it totally fails.

Another new Android API we discovered is [`WebViewClient.shouldInterceptRequest()`](https://developer.android.com/reference/android/webkit/WebViewClient.html#shouldInterceptRequest\(android.webkit.WebView,%20android.webkit.WebResourceRequest\)). This is an official API for manipulating HTTP requests in `WebView`. It is an an easy place to insert custom `HttpURLConnection` instances, like NetCipher needs to configure proxy support and stronger TLS. Using this API means eliminating Java reflection hacks. But it has a large caveat: it only works for *GET* requests. Since the request body is not accessible via this API, it is not possible to implement *POST* or *PUT* requests. One nice approach for the best of both works is to handle *GET* with `WebViewClient.shouldInterceptRequest()`, then *POST* and *PUT* could then be implemented separately using the reflection methods in NetCipher WebView.

### Tests! <a href="#tests" id="tests"></a>

This release also brings with it an extensive, new test suite. These let us confirm that things are working on all the supporting Android versions, while also serving as simple example cases. For example, the tests now confirm which Android releases support `WebView` proxying, based on Cure53’s very useful [HTTPLeaks](https://github.com/cure53/HTTPLeaks).


# TorServices

The new way to use Tor as a separate app

TorServices source code and app install links are available at: <https://guardianproject.info/apps/org.torproject.torservices/>

TorServices is a free proxy app that empowers other apps to use the internet more securely. It acts as a simple Tor “provider” for apps to hide their Internet traffic by encrypting it, then bouncing through a series of computers around the world. Tor is free software and an open network that helps you defend against a form of network surveillance that threatens personal freedom and privacy, confidential business activities and relationships, and state security known as traffic analysis.

You can check for TorServices being installed, and setup callbacks for status broadcasts using NetCipher, exactly as you would with Orbot. Sample code is [available on Gitlab](https://gitlab.com/guardianproject/torservices/-/blob/master/sample/src/main/java/org/torproject/torservices/sample/MainActivity.java?ref_type=heads), with a snippet displayed below

```
OrbotHelper.get(this).addStatusCallback(new StatusCallback() {
            @Override
            public void onEnabled(Intent statusIntent) {
                setProxy();
                webView.loadUrl("https://check.torproject.org/");
            }

            @Override
            public void onStarting() {
                statusTextView.setText("starting....");

            }

            @Override
            public void onStopping() {
                statusTextView.setText("stopping....");

            }

            @Override
            public void onDisabled() {
                statusTextView.setText("disable....");

            }

            @Override
            public void onStatusTimeout() {
                statusTextView.setText("timeout....");

            }

            @Override
            public void onNotYetInstalled() {
                statusTextView.setText("not installed....");

            }
        });

```


# Arti Mobile on Android

Using Tor's new Rust-based runtime in your Android app

[Arti-Mobile-Ex](https://gitlab.com/guardianproject/arti-mobile-ex) is the current project for building and using the Arti (Tor in Rust) project within your mobile app. The repository is available at: <https://gitlab.com/guardianproject/arti-mobile-ex>

#### To build for Android

* install Rust and Android Studio. Make sure you can run an Hello World with both.
* go in the common folder and run `make android`.
* take a coffee, or two.
* open the android folder in Android Studio or use gradle to build your app as usual.

### Sample Project for Android

There is a [sample Android Studio project](https://gitlab.com/guardianproject/arti-mobile-ex/-/tree/main/android/sample?ref_type=heads) that demonstrates how easy it can be to use Arti within your Android app.

Once you have built and imported the Arti library into your project, all that you do to initialize it using default ports, all that you need to do is:

```
Arti.init(this);
```

From there, you can easily proxy any HTTP connection over Arti's built-in SOCKs proxy port

```
Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(proxyHost, proxyPort));

HttpURLConnection connection = null;
URL url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection(proxy);
connection.setRequestMethod("GET");
```

You can also use the ProxyConfig class to enable WebView proxying, as well

```
ProxyConfig proxyConfig = new ProxyConfig.Builder()
           .addProxyRule("127.0.0.1:8118") //http proxy for tor
          .addDirect().build();

ProxyController.getInstance().setProxyOverride(proxyConfig, new Executor() {
            @Override
            public void execute(Runnable command) {
                //do nothing
            }
        }, new Runnable() {
            @Override
            public void run() {

            }
        });

```


# All The Onions on Apples

Summary of ways to integrate Tor on iOS devices

* Tor.framework for iOS: <https://github.com/iCepa/Tor.framework>
* IPtProxy Pluggable Transports: <https://github.com/tladesignz/IPtProxy/>
* IPtProxyUI library: <https://github.com/tladesignz/IPtProxyUI-ios>
* OrbotKit: <https://github.com/guardianproject/OrbotKit>
* TorManager: <https://github.com/tladesignz/TorManager>
* Arti Mobile: <https://gitlab.com/guardianproject/arti-mobile-ex>

{% embed url="<https://www.youtube.com/watch?v=6EGa7AlFOiM>" %}
[Onion Browser](https://onionbrowser.com) for iOS Walkthrough
{% endembed %}


# Tor.Framework for iOS

Using Tor the way Apple intends you to

You can find Tor.Framework at: <https://github.com/iCepa/Tor.framework>

### Example

To run the example project, clone the repo, and run `pod install` from the Example directory first.

### Installation

Install build tools via [Homebrew](https://brew.sh/):

```
brew install automake autoconf libtool gettext
```

Tor is available through [CocoaPods](https://cocoapods.org/). To install it, simply add the following line to your Podfile:

If you use dynamic frameworks, use the root spec:

```
use_frameworks!
pod 'Tor', '~> 408'
```

(or `Tor/GeoIP` - see below.)

If you need to add it as a static library, you will need to add it from a modified podspec:

```
pod 'Tor', :podspec => 'https://raw.githubusercontent.com/iCepa/Tor.framework/pure_pod/TorStatic.podspec'
```

Currently static library support is unstable. You might encounter build issues. Every contribution to fix this is welcome!

(or `Tor/GeoIP` - see below.)

### Usage

Starting an instance of Tor involves using three classes: `TORThread`, `TORConfiguration` and `TORController`.

Here is an example of integrating Tor with `NSURLSession`:

```
TORConfiguration *configuration = [TORConfiguration new];
configuration.ignoreMissingTorrc = YES;
configuration.cookieAuthentication = YES;
configuration.dataDirectory = [NSURL fileURLWithPath:NSTemporaryDirectory()];
configuration.controlSocket = [configuration.dataDirectory URLByAppendingPathComponent:@"control_port"];

TORThread *thread = [[TORThread alloc] initWithConfiguration:configuration];
[thread start];

NSData *cookie = configuration.cookie;
TORController *controller = [[TORController alloc] initWithSocketURL:configuration.controlSocket];

NSError *error;
[controller connect:&error];

if (error) {
    NSLog(@"Error: %@", error);
    return;
}

[controller authenticateWithData:cookie completion:^(BOOL success, NSError *error) {
    if (!success)
        return;

    [controller addObserverForCircuitEstablished:^(BOOL established) {
        if (!established)
            return;

        [controller getSessionConfiguration:^(NSURLSessionConfiguration *configuration) {
            NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
            ...
        }];
    }];
}];
```

#### GeoIP

In your `Podfile` use the subspec `GeoIP` or `StaticGeoIP` instead of the root spec:

```
use_frameworks!
pod 'Tor/GeoIP'
```

or

```
pod 'Tor/GeoIP', :podspec => 'https://raw.githubusercontent.com/iCepa/Tor.framework/pure_pod/TorStatic.podspec'
```

The subspec will create a "GeoIP" bundle and install a run script phase which will download the appropriate GeoIP files.

To use it with Tor, add this to your configuration:

```
TORConfiguration *configuration = [TORConfiguration new];
configuration.geoipFile = NSBundle.geoIpBundle.geoipFile;
configuration.geoip6File = NSBundle.geoIpBundle.geoip6File;
```


# Pluggable Transports for iOS

Lyrebird/Obfs4proxy and Snowflake Pluggable Transports for iOS, MacOS and Android

IPtProxy is the primary reusable library for integrating the latest anti-censorhip capabilities into your mobile app. You can find IPtProxy at <https://gitlab.com/guardianproject/IPtProxy> with the "live" development work also done at <https://github.com/tladesignz/IPtProxy/>

Both Lyrebird/Obfs4proxy and Snowflake Pluggable Transports are written in Go, which is a little annoying to use on iOS and Android. This project encapsulates all the machinations to make it work and provides an easy to install binary including a wrapper around both.

Problems solved in particular are:

* One cannot compile `main` packages with `gomobile`. Both PTs are patched to avoid this.
* Both PTs are gathered under one roof here, since you cannot have two `gomobile` frameworks as dependencies, since there are some common Go runtime functions exported, which would create a name clash.
* Environment variable changes during runtime will not be recognized by `goptlib` when done from within Swift/Objective-C. Therefore, sensible values are hardcoded in the Go wrapper.
* Snowflake and Lyrebird/Obfs4proxy are patched to accept all configuration parameters directly.
* Free ports to be used are automatically found by this library and returned to the consuming app. You can use the initial values for premature configuration, which is just fine in situations, where you can be pretty sure, they're going to be available (typically on iOS). When that's not the case (e.g. multiple instances of your app on a multi-user Android), you should first start the transports and then use the returned ports for configuration of other components (e.g. Tor).


# IPtProxyUI

Tor + Pluggable Transports on iOS and macOS

You can find IPtProxy at: <https://github.com/tladesignz/IPtProxyUI-ios>

IPtProxyUI provides all things necessary to use the Pluggable Transports from the [IPtProxy](https://github.com/tladesignz/IPtProxy) library with Tor, preferrably via [Tor.framework](https://github.com/iCepa/Tor.framework).

It includes all necessary configuration, code to interact with Tor Project's MOAT/rdsys service to update the user's configuration and fetch lesser-known bridges and, of course, a ready-made UI to show to your users which can handle all of the above.

The UI is complete for your users to configure all aspects of the Transports. However, you're not obliged to use it. You can create your own and use the lower-level code only.

Additionally there's a helper class `IpSupport` which can aid in better supporting IPv6-only networks which are common with some mobile network carriers.


# OrbotKit

A library to remote control Orbot iOS

You can find OrbotKit at: <https://github.com/guardianproject/OrbotKit>

OrbotKit provides a straightforward means to interact with Orbot iOS, so you can integrate support for it easily.

* If you use your own Tor, like [OnionShare](https://github.com/OnionShare/onionshare-ios/), watch for Orbot and bypass it, while it is running.
* If you want to make sure, your users are protected by Tor, like [Save](https://github.com/OpenArchive/Save-app-ios/) or [OnionBrowser](https://github.com/OnionBrowser/OnionBrowser/).


# TorManager

The easiest way to integrate Tor and Pluggable Transports into your app.

You can find TorManager at: <https://github.com/tladesignz/TorManager>

This library bundles all building blocks to integrate Tor into your app:

* Tor.framework using
  * C-Tor
  * GeoIP files
* IPtProxyUI using
  * Lyrebird Pluggable Transport
  * Snowflake Pluggable Transport
  * Auto-configuration support via Moat/RdSys services
  * Auto-configuration support for IPv4/IPv6 cappable networks
* OrbotKit to detect and interact with a running Orbot

Plus

* A "smart connect" algorithm to automatically step through the transports to find a connection in hostile environments.
* Provide correct \`WKWebView\` and \`URLSession\` proxy configurations.

<br>


# Arti and Onionmasq on iOS

Currently, Arti on mobile is still quite experimental and not actively maintained.

The features it already has can be tried out on iOS with either using [Arti Mobile Experimental](https://gitlab.com/guardianproject/arti-mobile-ex) directly, or by using it embedded in [Tor.framework](https://github.com/iCepa/Tor.framework), which gives you the advantage of having some helper classes at hand.

There's a [Podspec](https://github.com/iCepa/Tor.framework/blob/pure_pod/Arti.podspec), which supports that.

In your `Podfile:`

```ruby
pod 'Tor/Arti', :podspec => 'https://github.com/iCepa/Tor.framework/blob/pure_pod/Arti.podspec'
```

Said `Podspec` also contains an experimental version of [OnionMasq](https://gitlab.torproject.org/tpo/core/onionmasq), which contains Arti + IP packet routing (so you can use it on a `tun` device or Apple's [Network Extension API](https://developer.apple.com/documentation/networkextension) directly).&#x20;

At some point in the future this will probably replace the C-Tor + IPtProxy + leaf combination, which Orbot iOS currently uses.


# Community Case Studies

Learn about some great open-source mobile apps that integrate Tor on mobile

Below are some short interviews with the teams behind four different apps built outside of the Tor community, that have integrated Tor support to provide extra security and privacy to their user communities.

### Rethink at <https://rethinkdns.com>

> Say hello to a safer Internet.Block malware, spyware, ads, and trackers across all apps with Rethink DNS. Servers in 300+ locations: Experience *Blazing fast* speeds.

**What inspired you to create this app?**

It was a combination of frustration with surveillance economy in tech (where we worked: in BigTech) and internet censorship used to shut down dissent (from where we are: India), particularly from minorities most vulnerable. Rethink wasn't the only idea we wanted to pursue at the time, but fatefully Mozilla funded it with a generous grant in Jul 2020 and we've never looked back since.

**Why did you decide to incorporate Tor integrations?**

From feedback since our very first release on 8 Aug 2020, our userbase had consistently asked us to integrate with Orbot, and because our project is anti-censorship focused, it was really a no-brainer. Nathan & Hans from the Guardian Project were nice to us, so that was added motivation as well.

**How can people best support your work?**

Our development team (of 2) bears the entire cost of the public DNS resolvers that serve 40 billion requests per month. We rely on sponsorship to help keep the lights on as costs have steadily risen.

***

### Mumla - <https://mumla-app.gitlab.io/>

> Mumble is a low latency, high quality voice conference and chat system. Connect to one of the many public Mumble servers, or [run a server](https://wiki.mumble.info/wiki/Murmurguide) for your own community!

**What inspired you to create this app?**

I had a need for a Mumble client on Android at the time, and what I found had some annoying bugs, and was appa rently no longer maintained for several years. I therefore forked that software and named it Mumla (which is Swedish for "mumble").

**Why did you decide to incorporate Tor integrations?**

There was already some support for integrating with Orbot for using a TCP-only protocol connecting over Tor. I polished that functionality and added support for .onion addresses. This was partly motivated by the folks developing Wahay, who contacted me about the feature (see <https://wahay.org/>). Wahay is a Mumble client/server that only works over Tor.\
\
**How can people best support your work?**

The best support for Mumla would be funding that would allow me to prioritize doing work on it over other work that I do for compensation.<br>

***

### Monocles - <https://monocles.de/>

> monocles is a project founded to move to a more secure, ecofriendly, privacy respecting, fair and open source technical and digital life for everyone.&#x20;

**What inspired you to create this app?**

I decided to create monocles chat, monocles browser and the other free and open source monocles apps to help people to protect themselves and move to a more fair and ethically digital life. Also I try to help reducing the resource consumption since the monocles apps and servers need less resources than the common android apps. I don't think it is good when few big companies or countries have too much might or control over too many people because I think that diversity is important.

**Why did you decide to incorporate Tor integrations?**\
I think it is especially in restricted countries essential to have Tor integrated in the apps to protect people from totalitarian systems, from suppression and to guarantee the freedom of expression of individuals. Additionally I think that Tor can be good to use in common and “free” environments too because there are still too many companies and institutions which try to get too much data from people which again could lead to something totalitarian too. Therefore I see Tor as an important project for the freedom and protection of individuals but also for societies.

**How can people best support your work?**\
Currently the most important help would be financial support to the monocles project since it is still privately funded by me, some few payed accounts and little donations but also code or pull requests for the apps would be really helpful. Additionally using the apps and increasing awareness would be support the my work.<br>

***

### WebMon - <https://webmon.dev.akito.ooo/>

> Android app for monitoring web services. Notifies you of any HTTP or Onion destination not being available.

**What inspired you to create this app?**\
I was inspired to develop this app, because I wanted to have the possibility of monitoring some systems I set up as a hobby. I wanted to extend the types of services, which may be monitored, over time, so ideally you can monitor a variety of services. Since FLOSS is very important to me, as I stand behind its values, I wanted to give everyone a chance to use the app in return for feedback, suggestions and other comments, including thank you mails. :)

**Why did you decide to incorporate Tor integrations?**\
I incorporated Tor integrations, because many Tor services I visit are sometimes unavailable, since the backends behind it are not stable enough. With my app, you can always check, whether the particular service is up. Additionally, you can make sure, that your clearnet service is also available on Tor. Just because it runs on the clearnet, is not a guarantee, that it also runs on Tor for whatever reason. Therefore, you need to monitor both endpoints, to be sure, that your service is actually available. Besides all that, I'm a long time user and philosophical supporter of Tor, so integrating Tor support was also a matter of principle to me. Finally, I also learned a lot about how to implement Tor, how it works, etc. I love learning new technologies!

\
**How can people best support your work?**

Time is the most precious resource a human has. So, my work can be best supported by offering to spend time for the sake of delivering expertise in some area. The most obvious one is of course help in terms of development progress, as I don't have time for this project really anymore and barely may release a feature version bump a year. Therefore, if someone likes the project and is able or wants to learn to develop Android applications, I'd be more than happy to help & review pull requests made by the volunteer.

<br>

<br>

<br>


# Developer Story: Arti Integration Journey

A story of a young developer and Tor

For my first official independent assignment at Guardian Project, I have been tasked with fleshing out a sample app to demonstrate how Arti (Tor in Rust) can be integrated into an app.&#x20;

While Arti can be imported as a binary library, the new codebase and build systems makes it easier for anyone to compile and include directly from the source code. As such, like many other developers do for their projects, I built it locally. For this, I had to install the Rust environment with the instructions [here](https://www.rust-lang.org/tools/install). After that, and installing [Android Studio](https://developer.android.com/studio/install?gad_source=1\&gclid=CjwKCAjwp4m0BhBAEiwAsdc4aJZZxVIVQkZdI-HK89uKQw1ClXRhcwpkEL1wk7oZYZwGqES5ZM93XxoCYEoQAvD_BwE\&gclsrc=aw.ds), I got to work building the Arti binary.&#x20;

The first step for that is to clone the Arti Mobile (Experimental) code [repository](https://gitlab.com/guardianproject/tormobile/arti-mobile-ex) on Gitlab, also known as “arti-mobile-ex”. As it will tell you in the readme, from your terminal, you will first need to navigate to the common folder in the repo and run “make android”. This will run the android build in the [Makefile](https://opensource.com/article/18/8/what-how-makefile), which you can find and look through in the common folder. If you are on a Mac, like myself, you will likely get some warnings from your computer about unverified libraries used in the project, which will prevent you from building properly. As a result, you may have to re-run it a couple of times after navigating to System Settings > Privacy and Security and scrolling down and choosing to [allow the packages to be installed](https://support.apple.com/en-tj/guide/mac-help/mh40616/mac) anyways. You may be (reasonably) apprehensive to do so, but in big projects that involve a lot of different packages, there will likely be one or two that come from an “unidentified developer” by Apple. This is usually no cause for panic, and you can always do a bit of research on the package to put your mind at ease. Then, you will need to open Android Studio, and open the folder arti-mobile-ex > android > sample as a project.&#x20;

The sample app, in its current state, has only one functionality. If you press a button in the bottom left corner, it will first attempt to connect to Tor with Arti. If that fails, then it will attempt to connect to Tor directly. If neither of those work, it will show an error message. It will display the connection status, and if you press the refresh button again, it will re-connect.&#x20;

The first task I am taking on is giving the user the option to connect to Tor directly, via Snowflake, or Lyrebird/Obfs4. If you are not sure what any of those are, neither was I! These connection options are all types of [Pluggable Transports](https://www.pluggabletransports.info/): tools that developers use to [disguise](https://support.torproject.org/glossary/pluggable-transports/) their users’ traffic. Many countries in which users might want to connect to the Tor network block direct connections to the Tor network. As such, developers use pluggable transports to make that traffic look like something else.&#x20;

Tor itself mainly uses the “obfsuscating” line of pluggable transports, the most recent version of which is obfs4 (also called Lyrebird). Obfs4, which is built into the Tor Browser, makes Tor traffic look [random](https://tb-manual.torproject.org/circumvention/). [Snowflake](https://snowflake.torproject.org/) is another type of pluggable transport which [functions](https://www.pluggabletransports.info/how-transports/) in a more peer-to-peer way, using many temporary connections.&#x20;

UI-wise, I thought the best way to implement this feature would be through a dropdown menu, which would have to communicate with the App.java. This is because the Arti Proxy had to be run from the context of App.java. After some (slightly arduous) searching, I realized that I could easily just call functions from App.java using (App)getApplication()) like so:

`((App)getApplication()).connectTorDirect();`

So, in my App.java, I created three methods: connectTorDirect(), connectWithLyrebird(), and connectWithSnowflake() that took the necessary arguments needed to start Arti with each of the respective options.&#x20;

Then, going back to my MainActivity, I worked out a UI flow for the app on the whole. First, the user would select the type of PT they wanted, causing the necessary input fields to appear.&#x20;

At the bottom of the screen, I coded up start, stop, and reload buttons. By default, these buttons are all disabled. But once the user selects a valid PT type, the start button becomes enabled. After the user then correctly fills out the input fields, they can click the start button and thus enable the stop and reload buttons. Some time down the line, I added regex to the bridge lines to prevent the user from giving invalid input. In Java, I learned that this can be done using the [Pattern](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html) and [Matcher](https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html) classes.&#x20;

Some XML markup code:

`<Button android:id="@+id/startButton"`

&#x20;  `android:layout_width="90dp"`

&#x20;  `android:layout_height="60dp"`

&#x20;  `android:layout_marginStart="32dp"`

&#x20;  `android:layout_marginEnd="44dp"`

&#x20;  `android:layout_marginBottom="60dp"`

&#x20;  `android:backgroundTint="@color/teal_200"`

&#x20;  `android:text="@string/start"`

&#x20;  `android:textColor="@color/black"`

&#x20;  `android:enabled="false"`

&#x20;  `app:layout_constraintStart_toStartOf="parent"`

&#x20;  `app:layout_constraintBottom_toBottomOf="parent"`

&#x20;  `app:layout_constraintEnd_toStartOf="@+id/stopButton" />`

<br>

`<Button`

&#x20;  `android:id="@+id/stopButton"`

&#x20;  `android:layout_width="90dp"`

&#x20;  `android:layout_height="60dp"`

&#x20;  `android:layout_marginStart="40dp"`

&#x20;  `android:layout_marginBottom="60dp"`

&#x20;  `android:backgroundTint="@android:color/holo_red_light"`

&#x20;  `android:text="@string/stop"`

&#x20;  `android:enabled="false"`

&#x20;  `android:textColor="@color/black"`

&#x20;  `app:layout_constraintBottom_toBottomOf="parent"`

&#x20;  `app:layout_constraintStart_toEndOf="@+id/startButton" />`&#x20;

<br>

The reason why I opted to keep a reload button in there is because I wanted to separate the launching Arti and checking the connection status in the code. This was mainly inspired by the fact that there was already a method in the code that just checked the connection status, so it made more sense to make a separate one that would do the actual launching. So, the start button would call the startArti() and then checkConnectionStatus(), but the reload button would only call checkConnectionStatus().&#x20;

<br>

&#x20; `private void startArti() {`

`//        stopButton.setEnabled(true);`

&#x20;      `textView.setText(R.string.intro_text);`

&#x20;      `switch (selectedOption){`

&#x20;          `case NO_PT:`

&#x20;              `((App)getApplication()).connectTorDirect();`

&#x20;              `break;`

&#x20;          `case OBFS4:`

&#x20;              `List<String> lyreBirdBridgeLines = collectInputs();`

&#x20;              `if (lyreBirdBridgeLines.isEmpty()) break;`

&#x20;              `((App) getApplication()).connectWithLyrebird(Integer.parseInt(obfs4Port.getText().toString()), lyreBirdBridgeLines);`

&#x20;              `break;`

&#x20;          `case SNOWFLAKE:`

&#x20;              `String stunServers = stunServerInput.toString();`

&#x20;              `String target = targetInput.toString();`

&#x20;              `String front = frontInput.toString();`

&#x20;              `List<String> snowflakeBridgesLines = collectInputs();`

&#x20;              `if (snowflakeBridgesLines.isEmpty()) break;`

&#x20;              `((App) getApplication()).connectWithSnowflake(stunServers, target, front, snowflakeBridgesLines);`

&#x20;          `default:`

&#x20;              `break;`

&#x20;      `}`

<br>

&#x20;     `Handler handler = new Handler();`

&#x20;      `handler.postDelayed(new Runnable() {`

&#x20;          `public void run() {`

&#x20;              `checkConnection();`

&#x20;          `}`

&#x20;      `}, 2000);`

&#x20;  }

\ <br>

`private void checkConnection() {`

&#x20;  `fab.setEnabled(false);`

&#x20;  `fabSpin.setDuration(1000*60).rotationBy((float) (1000 * 60) /4).setInterpolator(new LinearInterpolator()).start();`

&#x20;  `connectionStatus.setVisibility(View.VISIBLE);`

&#x20;  `connectionStatus.setText(R.string.performing_request);`

<br>

&#x20;  `new CheckTorConnectionTask(this).execute();`

`}`

<br>

I also implemented a ScrollView to display the log output. Since I had already learned how to make things in the App.java and MainActivity.java interact, this was fairly easy. I also really enjoyed this part because I got to figure out how to make it clearly look like code output. I ended up creating some drawable resources for this, and was quite pleased with the end result. I also made it scroll down automatically as new log output appeared, which was very satisfying. As a finishing touch, I also added a toggle to show and hide it, because I quickly realized that it might get annoying for the user. The difficult bit for the log output was figuring out how to constrain the box depending on which PT was selected, since they all had different numbers of input fields. This was a pain when I first implemented it, but then ended up becoming much simpler when I wrapped those input fields in another view (more on that later).&#x20;

<br>

If the user does everything correctly up until this point, when they press the start button, there will first appear a “processing request” message right below the buttons at the bottom. Then, in accordance with whether and how the user was able to connect to Arti, a message is displayed.&#x20;

<br>

When I went to implement the stop button, I realized that functionality had actually not yet been implemented in the ArtiProxy library! I brought this up with the team, and created an [issue](https://gitlab.com/guardianproject/tormobile/arti-mobile-ex/-/issues/6) to get it implemented. My colleague who was working on it kindly allowed me to watch and occasionally give my input while he dug through the Arti documentation to try and figure out how to do it. Pair programming is something that I am quite familiar with from college courses, having worked with a partner for many a lengthy assignment. It is something that I always enjoyed, and doing it here was no different. I have found that working with someone can be great for really tedious tasks because you can bounce ideas off each other and get through it much more easily. It’s a bit more difficult when it’s remote, but nonetheless a more enjoyable experience than slogging through a large codebase on one’s own.

<br>

While I was waiting for the stop functionality, I also got to work on giving the user a way to add and remove bridge lines in the Arti app. I learned that an average user might want to use even dozens of bridges at a time, so I had to think about what a good way to do it might be UI-wise. I settled on putting my input fields in a ScrollView, along with buttons to add and remove bridge lines. I set a max height for this ScrollView, making it automatically scroll down when the user exceeds that height (just like for the log output). I found that just wrapping the input fields in the ScrollView resulted in an error, since a ScrollView can only have one direct child. As a result, I had to wrap the input fields in a LinearLayout first, which meant I had to do the (frankly bothersome) work of redoing the constraints they had on them. As for the buttons, I thought it would look best to have them at the bottom, by the bridge line input field, each taking up half of the parent view horizontally. In order to place them next to each other horizontally, I had to wrap them in another horizontally-oriented LinearLayout. I also used a property called [weightSum](https://developer.android.com/reference/android/widget/LinearLayout#attr_android:weightSum) to ensure that they would each take up half of the space. While having nested layouts is generally not recommended, I found that for this case it made sense. The nesting was not too deep, and the MainActivity.java code was a lot tidier with the input fields wrapped in that layout. The directly-one-after-another nature of the input field lended itself nicely to the LinearLayout, so it was all for the best.&#x20;

<br>

The nested XML code:

`<ScrollView`

&#x20;  `android:id="@+id/inputScrollView"`

&#x20;  `android:layout_width="match_parent"`

&#x20;  `android:visibility="gone"`

&#x20;  `android:layout_height="0dp"`

&#x20;  `android:layout_marginStart="5dp"`

&#x20;  `android:layout_marginEnd="10dp"`

&#x20;  `android:layout_marginTop="5dp"`

&#x20;  `app:layout_constraintHeight_max="220dp"`

&#x20;  `app:layout_constraintTop_toBottomOf="@id/spinner"`

&#x20;  `app:layout_constraintEnd_toEndOf="parent"`

&#x20;  `app:layout_constraintStart_toStartOf="parent">`

<br>

&#x20; `<LinearLayout`

&#x20;   `android:id="@+id/inputFieldsContainer"`

&#x20;   `android:layout_width="match_parent"`

&#x20;   `android:layout_height="0dp"`

&#x20;   `android:orientation="vertical"`

&#x20;   `tools:layout_editor_absoluteX="0dp">`

<br>

&#x20; `<EditText`

&#x20;       `android:id="@+id/obfs4Port"`

&#x20;       `android:layout_width="match_parent"`

&#x20;       `android:layout_height="wrap_content"`

&#x20;       `android:layout_marginStart="15dp"`

&#x20;       `android:layout_marginEnd="15dp"`

&#x20;       `android:backgroundTint="@color/teal_200"`

&#x20;       `android:ems="10"`

&#x20;       `android:hint="@string/enter_obfs4_port"`

&#x20;       `android:inputType="text"`

&#x20;       `android:visibility="gone"`

&#x20;       `app:layout_constraintEnd_toEndOf="parent"`

&#x20;       `app:layout_constraintStart_toStartOf="parent" />`

…

…

`<LinearLayout`

&#x20;   `android:layout_height="0dp"`

&#x20;   `android:layout_width="match_parent"`

&#x20;   `android:layout_weight="1"`

&#x20;   `android:weightSum="2"`

&#x20;   `android:orientation="horizontal" >`

<br>

&#x20;`<Button`

&#x20;       `android:id="@+id/buttonAdd"`

&#x20;       `android:layout_width="0dp"`

&#x20;       `android:layout_height="match_parent"`

&#x20;       `android:layout_weight="1"`

&#x20;       `android:layout_marginEnd="15dp"`

&#x20;       `android:layout_marginStart="15dp"`

&#x20;       `app:layout_constraintEnd_toEndOf="parent"`

&#x20;       `app:layout_constraintStart_toStartOf="parent"`

&#x20;       `android:text="@string/add_bridge_line"`

&#x20;       `/>`

`…`

`</LinearLayout>`

`</LinearLayout>`

`</ScrollView>`

<br>

\ <br>

At this point, I was beginning to become annoyed with how messy one of my switch statements was becoming–the one that was controlling which views should be visible and which should be “gone” when a particular PT was selected. So, to clean it up, I decided to create a few private methods that would set those visibilities, then I just called them from the switch statement.&#x20;

<br>

private void onSelectionChanged(SelectedPluggableTransport s) {

&#x20;  ConstraintSet constraintSet = new ConstraintSet();

&#x20;  switch (s) {

&#x20;      case NO\_SELECTION:

&#x20;          setDefaultVisibilities();

&#x20;          constraintSet.clone(constraintLayout);

&#x20;          break;

&#x20;      case NO\_PT:

&#x20;          setDirectVisibilities();

&#x20;          constraintSet.clone(constraintLayout);

&#x20;          constraintSet.connect(logLabel.getId(), ConstraintSet.TOP, spinner.getId(), ConstraintSet.BOTTOM);

&#x20;          break;

&#x20;      case OBFS4:

&#x20;          setLyrebirdVisibilities();

&#x20;          constraintSet.clone(constraintLayout);

&#x20;          constraintSet.connect(logLabel.getId(), ConstraintSet.TOP, inputScrollView\.getId(), ConstraintSet.BOTTOM);

&#x20;          break;

&#x20;      case SNOWFLAKE:

&#x20;          setSnowflakeVisibilities();

&#x20;          constraintSet.clone(constraintLayout);

&#x20;          constraintSet.connect(logLabel.getId(), ConstraintSet.TOP, inputScrollView\.getId(), ConstraintSet.BOTTOM);

&#x20;          break;

&#x20;  }

&#x20;  constraintSet.applyTo(constraintLayout);

}

\ <br>

private void setDefaultVisibilities() {

&#x20;  noSelection.setVisibility(View\.VISIBLE);

&#x20;  logScrollView\.setVisibility(View\.GONE);

&#x20;  logLabel.setVisibility(View\.GONE);

&#x20;  inputScrollView\.setVisibility(View\.GONE);

&#x20;  startButton.setEnabled(false);

&#x20;  fab.setEnabled(false);

}

<br>

private void setDirectVisibilities() {

&#x20;  stunServerInput.setVisibility(View\.GONE);

&#x20;  obfs4Port.setVisibility(View\.GONE);

&#x20;  targetInput.setVisibility(View\.GONE);

&#x20;  frontInput.setVisibility(View\.GONE);

&#x20;  bridgeLineInput.setVisibility(View\.GONE);

&#x20;  noSelection.setVisibility(View\.GONE);

&#x20;  logLabel.setVisibility(View\.VISIBLE);

&#x20;  inputScrollView\.setVisibility(View\.GONE);

&#x20;  addBridgeLine.setVisibility(View\.GONE);

&#x20;  startButton.setEnabled(true);

&#x20;  fab.setEnabled(true);

}

<br>

private void setLyrebirdVisibilities() {

&#x20;  bridgeLineInput.setVisibility(View\.VISIBLE);

&#x20;  obfs4Port.setVisibility(View\.VISIBLE);

&#x20;  stunServerInput.setVisibility(View\.GONE);

&#x20;  targetInput.setVisibility(View\.GONE);

&#x20;  frontInput.setVisibility(View\.GONE);

&#x20;  noSelection.setVisibility(View\.GONE);

&#x20;  logLabel.setVisibility(View\.VISIBLE);

&#x20;  inputScrollView\.setVisibility(View\.VISIBLE);

&#x20;  addBridgeLine.setVisibility(View\.VISIBLE);

&#x20;  startButton.setEnabled(true);

&#x20;  fab.setEnabled(true);

}

<br>

private void setSnowflakeVisibilities() {

&#x20;  bridgeLineInput.setVisibility(View\.VISIBLE);

&#x20;  stunServerInput.setVisibility(View\.VISIBLE);

&#x20;  targetInput.setVisibility(View\.VISIBLE);

&#x20;  frontInput.setVisibility(View\.VISIBLE);

&#x20;  noSelection.setVisibility(View\.GONE);

&#x20;  obfs4Port.setVisibility(View\.GONE);

&#x20;  logLabel.setVisibility(View\.VISIBLE);

&#x20;  inputScrollView\.setVisibility(View\.VISIBLE);

&#x20;  addBridgeLine.setVisibility(View\.VISIBLE);

&#x20;  startButton.setEnabled(true);

&#x20;  fab.setEnabled(true);

}

<br>

Also to make my code more readable in general, going off of something the person who worked on the project before me had done, I created an enum called SelectedPluggableTransport to use in my switch statements rather than just the numbers. Thinking through and implementing all these readability and style improvements was one of my favorite parts of the process. Since I knew I was developing for another developer, getting this right felt important.

<br>

In the code, whenever a user added a new input field, it would be added to a List\<EditText> array. Later on, when they went to press the start button, startArti() would call a method named collectInputs(), which would iterate through the EditText array and return an array of their inputs. That would then be passed to the relevant App.java function as the bridge line array.&#x20;

<br>

Overall, the process was quite fun! While I often got stuck and had to re-implement a bunch of stuff a few times, it was really satisfying when I figured out something that worked. I definitely feel more comfortable with Android Studio now, and could implement a basic app with much less trouble now.&#x20;

<br>


# Where to get help

Where to go to ask more questions about Tor and mobile development

{% embed url="<https://www.youtube.com/watch?v=A6tq0dtlWYk>" %}
Yet Another Tor State of the Onion about Mobile Video from 2022!
{% endembed %}

The best place to chat with us live is on the [Matrix network](https://matrix.org/). We are in the [#guardianproject:matrix.org](https://matrix.to/#/#guardianproject:matrix.org) room on Matrix.org. You can also connect to the broader [Tor community on IRC](https://support.torproject.org/get-in-touch/irc-help/).

Tor Project also offers a [Community Forum discussion site](https://forum.torproject.org/), where we often participate and answer questions.

Guardian Project has a mobile specific [Guardian-Dev Discussion List](https://lists.mayfirst.org/mailman/listinfo/guardian-dev) that you can join and post messages to.

Follow us on Mastodon: [@guardianproject@librem.one](https://social.librem.one/@guardianproject)

<figure><img src="https://images.unsplash.com/photo-1519389950473-47ba0277781c?crop=entropy&#x26;cs=srgb&#x26;fm=jpg&#x26;ixid=M3wxOTcwMjR8MHwxfHNlYXJjaHw3fHxoZWxwJTIwZGVza3xlbnwwfHx8fDE3MTUxODg4Mzl8MA&#x26;ixlib=rb-4.0.3&#x26;q=85" alt=""><figcaption></figcaption></figure>


