Top
Best
New

Posted by rekireki 1 day ago

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!

162 points | 81 commentspage 2
bbkane 1 day ago||
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.

zwnow 1 day ago||
Does this support native components like camera access and stuff like that? I've learned with most libs like this I never have access to the android internals (Flutter as an example) and I'll always have to fallback to writing Kotlin components with broadcast channels or whatever.
pjmlp 19 hours ago||
That will always be the case, some folks cannot get over that Android userspace is Java/Koltin, and the NDK use cases are officially real time audio, 3D rendering, writing native methods, reuse of existing C and C++ libraries and nothing else.

Everything outside those use cases is gated behind JNI calls, and Google has no plans to ever change it.

Naturally many with GNU/Linux mindset, and because Android runs on the Linux kernel, try to work around these restrictions, however Google isn't going to move an inch to make it easier.

rekireki 1 day ago||
It doesn't, and I had to write some Java to support clipboard.
zwnow 1 day ago||
I see, still a really cool project! Is accessing the internals simply not possible or just really hard to pull off programmatically? I am wondering about that because I never found anything in the android space to enable that without resorting to Kotlin/Java components.
nicoburns 1 day ago|||
You can call into to the JVM via FFI (e.g. using the jni crate in Rust), but it's not very nice. And most of the abstractions people have written thus far seem to be primarily (or solely) targeting the "Java calls into native code" use case rather than the "native code calls into Java" use case.

I'd love to see something better here. I suspect it's possible.

rekireki 20 hours ago|||
It's limited to what NativeActivity / GameActivity can provide. And as @nicoburns mentioned, you'll have to use FFI if you want to access some Android functionality. But it doesn't always go smooth. For example, all my attempts to fix issues with software keyboard didn't work.
RicoElectrico 1 day ago||
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.
nicoburns 1 day ago||
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 19 hours ago||
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 1 day ago|||
I don’t understand the question. Why would rust be confined to real-time applications?
amelius 21 hours ago||
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 1 hour ago||
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.
0x3f 18 hours ago|||
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.
IshKebab 1 day ago||
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 22 hours ago||
> 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 21 hours ago||
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.

jbfdrt7t 1 day ago||
[flagged]
jemmyw 1 day ago||
> 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 1 day ago||
Perhaps you could refrain from slandering Rust proponents without any evidence.
nubinetwork 1 day ago|
Just in time for google to block sideloading and blocking new apps unless you pay them 6 figures...