Top
Best
New

Posted by rekireki 12/22/2025

Build Android apps using Rust and Iced(github.com)
Some time ago I decided to try building an Android app using Rust. After a few weeks I got it working. There was a new iced release recently, so I've just updated the example to new iced and wgpu. I'd like to share my experience to attract more attention to Rust on Android.

First things, I want to thank all the people who work on the foundational crates and tools such as: - https://github.com/rust-mobile/android-activity - https://github.com/jni-rs/jni-rs - https://github.com/gfx-rs/wgpu - https://github.com/rust-windowing/winit - and many others

When I started I had to learn what tools and examples already exist. Luckily, there's a good set of examples using both NativeActivity and GameActivity: https://github.com/rust-mobile/rust-android-examples

The basic approach is that we take android-activity, winit and wgpu and that's it. On top of that you can find a few egui examples in the rust-android-examples repo.

Alright, so after I've got the basic examples running, I wanted to combine them with iced. Iced is a crossplatform gui library focusing on desktop and web. The mobile support is explicitly a non-goal, as far as I can tell at the moment of writing. Yet, there's an issue where some people posted their experiments. That's how I knew it was possible: https://github.com/iced-rs/iced/issues/302

There's a way to integrate iced in wgpu applications, so called integration example: https://github.com/iced-rs/iced/tree/0.14.0/examples/integra...

Above I mentioned that using winit and wgpu in combination with android-activity is enough to build the app. Putting together 1 + 1 I got 2: let's use iced integration example with android-activity. It was quite easy to compile with almost no errors. First issue I encountered is that there was no text rendered. I solved this by loading fonts the way it was shown here: https://github.com/pop-os/cosmic-text/issues/243#issue-21899...

Then I patched a few widgets to add touch support. And that's it. My role here was to take all the prior work and combine it together in a way that there's a working example.

Some other ways of building Android apps using Rust: - xilem has an explicit goal to support mobile https://github.com/linebender/xilem - egui supports mobile https://github.com/emilk/egui - game engines such as Fyrox and Bevy support mobile: - https://github.com/FyroxEngine/Fyrox - https://github.com/bevyengine/bevy - pretty much anything built on top of winit and wgpu

All of the above is related to building native apps using either NativeActivity or GameActivity. I'm leaving webview out of scope of current post.

What about iOS? As far as I know it should be similar or maybe simpler compared to Android. I haven't built it yet, but the next time I have a sizeable amount of free time, I'll try to make it work. The plan is the same: pick winit, wgpu, iced integration example, mix it together until it works. It'll require the same trick to load fonts, and maybe something else, but no visible blockers as of now.

Once again, thanks to all the people who made it possible and I wish you have a great time building mobile apps with Rust!

173 points | 85 commentspage 2
madduci 12/22/2025|
I would like to get a benchmark of this against an app made with C++/Qt
bbkane 12/22/2025||
Super impressive, can you link to this post in that issue?

I'd like to try iced, but switched to egui on the official Android support.

RicoElectrico 12/22/2025||
Not downplaying your project but a general related question. What's the deal with writing non-real-time application software in Rust? The stuff it puts you through doesn't seem to be worth the effort. C++ is barely usable for the job either.
IshKebab 12/22/2025||
It turns out it is worth the effort. Once you have got past the "fighting the borrow checker" (which isn't nearly as bad as it used to be thanks to improvements to its abilities), you get some significant benefits:

* Strong ML-style type system that vastly reduces the chance of bugs (and hence the time spent writing tests and debugging).

* The borrow checker really wants you to have an ownership tree which it turns out is a really good way to avoid spaghetti code. It's like a no-spaghetti enforcer. It's not perfect of course and sometimes you do need non-tree ownership but overall it tends to make programs more reliable, again reducing debugging and test-writing time.

So it's more effort to write the code to the point that it will compile/run at all. But once you've done that you're usually basically done.

Some other languages have these properties (especially FP languages), but they come with a whole load of other baggage and much smaller ecosystems.

discreteevent 12/22/2025||
> So it's more effort to write the code to the point that it will compile/run at all. But once you've done that you're usually basically done.

Not if I don't know what I'm doing because it's something new. The way I'm learning how to do it is by building it. So I want to build it quickly so that I can get in more feedback loops as I learn. Also I want to learn by example, so I actually want to get runtime errors, not type system errors. Later when I do know what I am doing then, sure, I want to encode as much as I can in my types. But before that .. Don't get in my way!

IshKebab 12/22/2025||
Yeah it is a fair point that runtime errors are sometimes easier to understand than compile time errors. They're still a much worse option of course - for the many reasons that have been already discussed - but maybe compile-time errors could be improved by providing an example of the kind of runtime error you could get if you didn't fix it (and it hypothetically was dynamically typed). Perhaps that would be easier to understand for some people or some errors.

There's a (Curry-Howard) analogue here with formal verification and counter-examples.

nicoburns 12/22/2025|||
A lot of complex GUIs are written in C++ (or are thinish wrappers around an underlying toolkit that is C++). This is often for performabce and/or resource consumption reasons. UIs may not have hard realtime requirements, but they are expected to consistently run smoothly at 60fps+. And dealong with multiple screen sizes, vector graphics, univode text,r etc can involve a lot of computation.

Rust gives you the same performance as C++ with much nicer language to work with.

pjmlp 12/22/2025||
Used to be written in C++, and usually trace back to the 1990's when C++ GUI frameworks used to rule.

Nowadays most are written in managed languages, and only hot paths are written in C++.

There is hardly anyone still writing new GUI applications on macOS, Windows in pure C++, even Qt nowadays pushes for a mix of QML, Python and C++.

adastra22 12/22/2025|||
I don’t understand the question. Why would rust be confined to real-time applications?
amelius 12/22/2025||
No the question is why you would use a systems language that necessarily lacks certain ergonomics such as automated garbage collection, for writing GUIs.

That makes no sense to me either, to be honest.

adastra22 12/23/2025||
Why is automatic garbage collection necessary for UI? I’ve been writing UI apps for 25 years without using a garbage collector. In any case, the borrow checker often (though not always) obviates the need for garbage collection at all.
octopoc 12/23/2025||
This is a good summary of the problem with rust I think:

> Pretty much all UI can be modeled as a tree–or more abstractly as a graph. A tree is a natural way to model UI: it makes it easy to compose different components together to build something that is visually complicated. It’s also been one of most common ways to model UI programming since at least the existence of HTML, if not earlier.

> UI in Rust is difficult because it's hard to share data across this component tree without inheritance. Additionally, in a normal UI framework there are all sorts of spots where you need to mutate the element tree, but because of Rust’s mutability rules, this "alter the tree however you want" approach doesn't work.[1]

[1] https://www.warp.dev/blog/why-is-building-a-ui-in-rust-so-ha...

adastra22 12/24/2025||
If I’m being charitable that is an oversimplification, and I suppose I should be charitable at Christmas. But the Scrooge in me is screaming that this analysis is deeply flawed.

Rust makes ownership and mutability explicit. Concurrent editing is very dangerous no matter what stack you are using. Rust just doesn’t let you get away with being a cowboy and choosing YOLO as your concurrency model.

Shared mutable state isn’t any harder in Rust than other languages. In fact, writing correct, bug-free and performant code is easier in Rust than almost any other language in common use, because the tooling is there. It’s just that the other compilers let you ship buggy code without complaining.

To the specific example, there are ways of sharing mutable state, or encapsulating changes throughout a UI tree. I’ve written a UI framework in Rust that does this. It is difficult to get right. But this is true of ANY language - the difficulty is intrinsic to the data type, if you actually care about doing it correctly.

That difficulty does not need to be exposed to the user. There are plenty of Rust UI libraries that take react-like lambda updaters, for example.

I still fail to see the connection to garbage collectors.

0x3f 12/22/2025||
End-to-end types and a single(-ish) binary simplifies a lot of things. Plus you can always just .clone() and .unwrap() if you want to be lazy/prototype something.
jbfdrt7t 12/22/2025||
[flagged]
jemmyw 12/22/2025||
> René did have to ban an angry troll, whom he mentions in a YouTube comment as one possible perpetrator. Others think someone from the Rust (programming language, not video game) development community was responsible due to how critical René has been of that project, but those claims are entirely unsubstantiated.

So what do we think is more likely here? Jumping the gun due to your own dislike of some groups it seems.

winstonewert 12/22/2025||
Perhaps you could refrain from slandering Rust proponents without any evidence.
nubinetwork 12/22/2025|
Just in time for google to block sideloading and blocking new apps unless you pay them 6 figures...