
Ask HN: Best language to share code between an Android and iOS app? - mevorah
Hello app developers of HN!<p>My team owns an Android (Kotlin) and iOS (Swift) app. The app is responsible for processing data, submitting to ML models, and then displaying results in a UI. We chose to do a lot of that processing in a shared Rust component. What we have found is a high overhead of bridging Kotlin&#x2F;Swift to Rust. Some core logic has also seeped into our bridging code resulting in some duplication (exactly what we were trying to avoid).<p>With that, those of you who have found yourselves in similar situations, which language would you choose to be shared between your Android and iOS app (if any)?
======
toast0
Since no one else has said it, I'll be the voice of reason.

Share your design specs only, and let each platform team write the
implementation in the language that they think best.

Yes, you'll have two teams spending time on doing the same thing. However,
you'll get important benefits.

Each team will be able to implement appropriately for their platform. While
iPhones and Android phones are rather similar in terms of capability, the
interaction models have a lot of differences, and forcing a common component
often results in non-native feeling apps. Users will be at best confused, and
at worst insulted by this.

Additionally, when you have two teams working on similar problems, they can
help each other. Training on this interaction with things known to be pretty
much the same helps people realize they can do it with things that aren't
obvious. Meeting on a regular basis to discuss things that worked/didn't on
the various platforms will help them all.

~~~
fizx
This is a UI-centric take.

There are lots of internals that could/should be shared between apps. Recently
relevant examples: a customized WebRTC stack, a websocket client with extra
authentication and delivery rules.

FWIW, my take on this has been to embrace Conway's law: if you have enough
shared work to form a team around it, then break off a c++/whatever library
and a team to maintain it. But if the hope is just to save 200LOC here and
there, just bite the bullet and write it twice.

Big thanks to whoever pointed out Kotlin Native: seems interesting enough to
poke around with.

~~~
aaronbrethorst
This is exactly what Dropbox has just abandoned.
[https://blogs.dropbox.com/tech/2019/08/the-not-so-hidden-
cos...](https://blogs.dropbox.com/tech/2019/08/the-not-so-hidden-cost-of-
sharing-code-between-ios-and-android/)

~~~
Game_Ender
In this case they lost there C++ team, so following Conways law they went back
to separate code based.

Also the open source C++ ecosystem has advanced quite a bit since when they
did there project. You would be able to spend much more time on the problem
domain, and zero time on writing a JSON library for example.

------
pjmlp
C++.

It is part of both SDKs, you have direct support for mixed mode debugging on
the IDEs.

No need of extra tooling.

On Android JNI is always going to be a pain, but at least with C++ Studio
gives you an hand on accessing JNI APIs.

~~~
ww520
I would say use C. Interfacing C with Java is simple JNI. Interfacing C with
Swift is very simple, too.

~~~
pjmlp
C is also very simple to add security exploits to your app.

I would never advise C unless the platform is lacking of a C++ compiler.

Just use extern "C" at the boundaries.

~~~
rkachowski
What vulnerabilities does C introduce that C++ doesn't?

~~~
millstone
For example it is easier to avoid buffer overflows with std::string than with
C-style strings.

~~~
scarface74
It’s also easier to avoid buffer overflows in C by using the “n” variants of C
string library functions.

~~~
xmprt
Why subject yourself to that risk when you can just use C++ and make
everyone's lives easier? Is there a benefit to using C?

~~~
scarface74
What “risk” is there in an overflow from using strncmp, strncpy, etc?

C++ still isn’t as easy to interop with other languages as C and the low level
APIs built into operating systems are not going to use C++/STL and you still
end up converting to standard C strings and arrays.

~~~
naniwaduni
strncpy notoriously doesn't necessarily 0-terminate.

(It also always pads the full length with zeroes if necessary, so it's almost
never what you actually want to do.)

The C standard library is full of these footguns.

I won't say C++ doesn't have its bad parts, and I certainly wouldn't say that
it's impossible to avoid the bad parts of C (some would), but you probably
aren't going to manage.

~~~
scarface74
If all of your string manipulation is working with the knowledge of the
maximum size, how is that any different than the standard Pascal or BSTR
string handling where the size of the string can be found in the first two
bytes of the string?

The typical error case with C is something like

    
    
      char *a = “abcd”; //5 bytes
      char *b = “efgh”;
    
      char c[8];
      strcpy(c,a);
      strcat(c,b); //buffer overflow by 1 byte. 
    

If you used the “n” equivalents, c would have 8 bytes and every other function
would know to stop 8 bytes - assuming you always pass in a size parameter.

~~~
naniwaduni
It's not. But plenty of other standard C functions like to use 0-terminated
strings without explicit lengths, including most of the system interfaces, and
others make it awkward to pass in the length that you're actually tracking.
You only need to call one of those with an unterminated string and it doesn't
even matter whether _your_ code knows the string's length.

You could say that just means you have to be very careful whenever you pass a
pointer to a string around without also passing in its length, but that's a
lot of places.

------
skinnyasianboi
I have great success using Kotlin Multiplatform to share code between iOS and
Android. Have a look at my Android Jetpack Compose and iOS SwiftUI project
sharing the common logic for a game
[https://github.com/SimonSchubert/Braincup](https://github.com/SimonSchubert/Braincup)

~~~
skinnyasianboi
It's worth to mention that it also supports native Linux, Windows and macOS
buildings. Plus web via JavaScript and server via jvm.

~~~
victor106
This is really cool. Care to share some resources from which others can learn
to get started?

~~~
soulnothing
This is the official docs

[https://kotlinlang.org/docs/reference/multiplatform.html](https://kotlinlang.org/docs/reference/multiplatform.html)

I've also done multi platform recently.

I've taken a contract first approach. Swagger / openapi for rest clients.
Outside of that I use vertx which has bindings for almost every platform. With
those two I can account for interoperability across all platforms.

Big hitches

* No ts.d defintions at this time. But: [https://github.com/vojtechhabarta/typescript-generator](https://github.com/vojtechhabarta/typescript-generator)

* Dukat for automatic typescript definition importing (beta) [https://github.com/Kotlin/dukat](https://github.com/Kotlin/dukat)

* I've not done LLVM iOS. But I've read of some generic issues.

They are improving dependency management to handle multi platform. I can't
find a link but it was on their blog

------
me551ah
Just use JavaScript.

Javascriptcore is a lightweight way to execute JavaScript on iOS and you can
use V8 context or duktape on Android. This way you can also update code in
your app without an app store update.

~~~
auggierose
which is not allowed on iOS ...

Edit: Sorry for being unclear, was only referring to the updating JS on the
fly and circumventing App Store part. Obviously (facepalm) ... ️

~~~
jaredsohn
Which part isn't allowed? A project I worked on did this a few years ago.

~~~
mcraiha
I think there is some confusion around this. You can use Javascript with iOS
if you use Webkit + JavaScript Core, and ship all your features in the binary
that your app uses.

2.5.2 "Apps should be self-contained in their bundles, and may not read or
write data outside the designated container area, nor may they download,
install, or execute code which introduces or changes features or functionality
of the app, including other apps."

and

4.7 " your app must use WebKit and JavaScript Core to run third-party software
and should not attempt to extend or expose native platform APIs to third-party
software"

------
kerryritter
I'm surprised no one has pointed out the value of Ionic Framework
([https://www.ionicframework.com](https://www.ionicframework.com)). I'm a
huge, huge proponent of this. TypeScript is a great language (in my opinion),
UI code-sharing is inherent, and Capacitor
([https://capacitor.ionicframework.com/](https://capacitor.ionicframework.com/))
is great for all the native work you need to do. Worth noting you can do this
in Angular, React, Vue, or pure JS.

This won't suit your needs for processing-heavy apps (though can WebWorkers
help), but will work well for many apps ([https://csform.com/top-10-apps-
built-with-ionic-framework/](https://csform.com/top-10-apps-built-with-ionic-
framework/) for a "top 10" list for examples).

I noticed after submitting that you mentioned machine-learning. Any reason you
can't offload that to a web API and take the load off the client?

------
mightybyte
So I'm sure lots of people will think that this definitely doesn't qualify as
"Best language to share code...", but Haskell has stuff for getting web,
desktop, iOS, and Android out of one code base. It's called Obelisk
([https://github.com/obsidiansystems/obelisk](https://github.com/obsidiansystems/obelisk))
and it's actually getting to be a pretty good development experience.

~~~
malux85
I love hacker news. This is the comment I came here for.

Just use this : A language that is (at best) fringe on the platform you are
using. Here's a toolset nobody has ever heard of. Now build your mission
critical bit of infrastructure on this house of cards, wait for the toolset
maintainers to be outpaced and under-resourced by underlying OS/platform
changes and then have to rewrite the whole thing which if it doesn't kill your
startup, will certainly massively impact its resources.

Go! (THIS IS A JOKE)

~~~
dimator
Well, developers are the kind of people that love to be contrarian, so it
shouldn't be that surprising. Half the fun (in my mind) is doing something no
one else is doing. Being novel. It's probably unwise in a business sense, but
if everyone was being wise all the time, there wouldn't be much fun in
software development.

~~~
whateveracct
You're not obligated to be a brutal capitalist as an engineer. It's okay to
make decisions that are suboptimal (but still passable) for your employer but
highly aligned with your own career interests.

If you always optimize for whichever company is employing you currently,
you're doing yourself a disservice and essentially "leaving money on the
table" :)

------
_31
Good thread previously here on HN about code sharing between iOS and Android:
[https://news.ycombinator.com/item?id=20695806](https://news.ycombinator.com/item?id=20695806)

------
novocaine
We're using kotlin native, after considering rust for a bit. It's been working
great, we've had it in production for about six months.

Main advantages are

* kotlin is a nice language with good type support

* has good swift bindings out of the box

* also compiles to js and cpp so we can use it in our Web product as well

~~~
crummy
What's the debugging experience like?

------
lewisjoe
We use JavaScript for sharing code between devices(iOS & Android), browser as
well as the server. Surprisingly, we haven't faced any of the problems, that
Dropbox claims to have faced ([https://blogs.dropbox.com/tech/2019/08/the-not-
so-hidden-cos...](https://blogs.dropbox.com/tech/2019/08/the-not-so-hidden-
cost-of-sharing-code-between-ios-and-android/)).

Pros:

1\. Sharing native APIs with JS runtime and vice versa, was well supported &
trivial to implement.

2\. Easy to find skill-set.

3\. We can run the same code in browsers as well.

Cons:

1\. The app will be slightly heavier in Android (as V8 has to be bundled with
the app. iOS allows using native JsCore runtime.)

2\. The shared code runs slower (Obvious, because dynamic language).

~~~
panpanna
> as V8 has to be bundled with the app.

Cant you make use of Webview somehow? It has the benefit of being updated from
the market if a security issue is found.

------
W0lf
I did one cross iOS/Android platform project using Kotlin/Native with its MPP
plugin with reasonable success. However, this was 6 months ago and the
JetBrains people surely haven‘t stopped moving forward.

------
JaggerJo
F# with Xamarin.Android + Xamarin.Ios

~~~
tluyben2
Or the more common choice C#.

------
nfriedly
FullStory is using Rust for our shared code, however the other sides are
different: Java & Objective-C. It seems to be working pretty well for us so
far.

Our requirements are probably a bit different than yours, though, because
we're shipping a tool for app developers rather than the app itself. In
particular, Objective-C was chosen over Swift because we didn't want to risk
potential conflicts if our customers were using a different version of Swift
and/or have to bundle a Swift runtime for older iOS versions.

------
njsubedi
I'm not completely sure about your requirement, but as a game developer who
uses Unity everyday, I would recommend it. Core graphics and UI components are
available out of the box, and sometimes even when we need an app(nothing like
a game) that need to access native APIs of the platform, we use Unity. It used
C# as the default language, and platform-specific core logic can be separated
within the code, using #directives so it's pretty straightforward.[edit: typo]

------
zwetan
ActionScript 3.0

with the Adobe AIR runtime you will be able to publish to iOS, Android,
Windows and macOS, see "Adobe AIR" [0]

ActionScript is something similar to TypeScript

you will have access to the whole Flash stack and more, see "Building Adobe
AIR Applications" [1]

with ActionScript Native Extension (ANE) you will be able to add your native
code with an easy to use AS3 interface, see "Extending Adobe AIR" [2] and
"Using native extensions for Adobe AIR" [3]

Note, the latest Adobe AIR SDK are now maintained by Harman [4]

[0]
[https://www.adobe.com/products/air.html](https://www.adobe.com/products/air.html)

[1]
[https://help.adobe.com/en_US/air/build/index.html](https://help.adobe.com/en_US/air/build/index.html)

[2] [https://www.adobe.com/devnet/air/articles/extending-
air.html](https://www.adobe.com/devnet/air/articles/extending-air.html)

[3]
[https://help.adobe.com/en_US/air/build/WS597e5dadb9cc1e0253f...](https://help.adobe.com/en_US/air/build/WS597e5dadb9cc1e0253f7d2fc1311b491071-8000.html)

[4] [https://airsdk.harman.com/](https://airsdk.harman.com/)

------
shanth
Dart+flutter?

~~~
mgleason_3
This would definitely be my choice - for almost anything except certain types
of game development.

Flutter makes cross platform life so much easier - why do anything else?

------
karmakaze
One way would be to host a script engine and run the script language, e.g.
JavaScript. Another would be to create your own grammar and simultaneously
translate to Kotlin and Swift. You could even use a strict subset of either
Kotlin or Swift then you'd only have to deal with one translator.

------
tpetry
Another concept would be using Haxe Lang: You wrote shared logic in haxe which
will be transpiled to c++ and java (and many more languages).

------
zelly
C++ is first-class in Android via NDK. You can write directly to your app's
memory from a C++ library without having go through FFI. I'm pretty sure it's
the same for iOS but through a C ABI.

~~~
saagarjha
I wouldn't call C++ through the NDK "first class", especially compared to
Objective-C++ on iOS.

------
masterwok
Xamarin iOS and Xamarin Android using C#

------
stockkid
In Go, there is an official, experimental project called gomobile [0] that
allows one to generate a Java or Objective C binding to be used in mobile
projects based on Go source code.

It comes with some restrictions and is still deemed experimental. But it could
be a viable choice in the days to come.

[0] [https://github.com/golang/mobile](https://github.com/golang/mobile)

~~~
eliasnaur
Gomobile bridges Java and ObjectiveC/Swift to Go, and probably entails the
same overhead the author is trying to avoid.

Shameless plug: If you like Go and immediate mode UIs in particular, Gio[0]
runs the same Go code across desktop and mobile alike. No bridging or native
code required.

If you like a more mature framework and don't mind Dart, I think Flutter is an
attractive toolkit. I started Gio wanting to write a Flutter clone in Go
before going for the immediate mode design.

[0] [https://gioui.org](https://gioui.org)

------
arcticbull
You should share design specs between client teams and allow each of them to
implement them within the parameters of what's expected on each platform.
Don't force them to have the _exact_ same UI at the cost of platform-specific
idioms. It hurts customers on both platforms to take that approach.

Your business logic should be, to the maximum extent, implemented once on the
server. Your client implementations should simply display what the server has
computed, once. Caching it is fine, rendering it locally is fine for the most
part, and you get a clean, well-fitted, elegant UI for it.

Any limited amounts of business logic that must be correct and truthful should
be implemented as a Rust (or if you insist, a limited, well-defined subset of
C++) library with C linkages and idiomatic wrappers for iOS and Android. If
this can be shared with the server and/or web front-end (via emscripten for
instance), it should be. It's usually painful to do this, but there's usually
only a small part of your codebase that should fall under this section.

------
mister_hn
If you really want to optimize and share code across platforms, you should
really go for C++.

Make your core logic in C++ and write bridges for Kotlin and Swift, where only
the UI logic is involved. C++ has the better ecosystem so far and the very
modern standard (C++17) let you write robust code. There are also so many
tools that help you catch errors and typos, plus thousands of libraries
available.

------
jamil7
I'm not an expert but you could consider sharing Swift (or Kotlin) code
between platforms. Nim ([https://nim-lang.org](https://nim-lang.org)) could
also be explored.

~~~
saagarjha
You can't really share that between platforms.

~~~
jamil7
Ah shame, I remember reading about targeting iOS at least with nim but didn't
look to closely into it.

------
mojuba
Something just crossed my mind while reading the question, that Swift could be
a good candidate. Turns out there are compatibility layers that are based on
Swift:

[https://www.scade.io](https://www.scade.io)

[https://academy.realm.io/posts/swift-on-
android/](https://academy.realm.io/posts/swift-on-android/)

[https://blog.readdle.com/why-we-use-swift-for-android-
db449f...](https://blog.readdle.com/why-we-use-swift-for-android-db449feeacaf)

------
santa_boy
I have a similar use case where the crux of my business is really data /
analytics centric. The user experience is pretty much limited to _mostly_
information consumption with a few click events (favorites, like, dislike,
delete and the occasional standard input forms).

I'm leaning towards using
[Meteor]([https://www.meteor.com/](https://www.meteor.com/)) to share code
between mobile apps and web apps.

Using cordova shells is pretty neat for business applications. Would be
interested in thoughts.

------
cpeterso
Here's a Mozilla blog post about rewriting Firefox's Sync client code in Rust
so the same code can be used on desktop, Android, and iOS. The FFI between the
shared Rust code and C++, Java, and Swift app front ends is a little hairy but
well encapsulated, generated code.

[https://hacks.mozilla.org/2019/04/crossing-the-rust-ffi-
fron...](https://hacks.mozilla.org/2019/04/crossing-the-rust-ffi-frontier-
with-protocol-buffers/)

------
pier25
I'm looking at solving a similar problem but for desktop.

I would like to avoid C++ and so far the best candidate seems to be Nim. It
transpiles to C which then can run in pretty much any platform.

------
omonien
I do a lot of consulting for clients who use Embarcadero's Delphi to create
native iOS and Android apps from a single source base. Delphi is a commercial
product, that comes with its price tag and there is, of course, a learning
curve, but once you know the processes you can create great multi-platform
mobile apps, with way less effort than having one team on Xcode and the other
on Android Studio.

------
fmxexpress
RAD Studio let's you build cross platform apps targeting Android, iOS, macOS,
Windows, Linux, and HTML5 with a single codebase and single UI. Choose either
Object Pascal or C++.

I prefer the Object Pascal side but the C++ side is also powerful because it
solves some of the problems that the Dropbox team talked about in their "The
(not so) hidden cost of sharing code between iOS and Android" article.

------
shams93
I use c++ rather than rust because as much as I would love to use the best
language its just not so well supported on mobile compared to c/c++. I'm not
sure how well flutter ffi does using rust compared to more mainstream
approaches its possible that flutter ffi is more friendly to rust than
jni/kotlin.

------
pcstl
Kotlin can generate both JVM bytecode and iOS binaries. I've successfully
shared code between iOS and Android projects using Kotlin before. The overhead
is quite low, and, all in all, I was quite satisfied with the results.

However, a lot of the tooling around this is experimental, so you might want
to tread carefully here.

------
enjoiful
Surprised no one has mentioned NativeScript yet. I've used it, admittedly only
for investigation purposes, but was super impressed.

[https://www.nativescript.org/](https://www.nativescript.org/)

------
rsecora
I have 22 years of shipping products on time with Delphi. The latest versions
do a wonderful job compiling to android, iOS, macapp or Windows.

Delphi is not cheap, but in my case the time to market, and tight release
dates make it worth.

www.embarcadero.com/products

------
cerberusss
Have you seen this answer on Stack Overflow?
[https://stackoverflow.com/a/5234868](https://stackoverflow.com/a/5234868)

------
earenndil
D allows you to export an obj-c api. This won't help much on the android side,
but would definitely help with talking to swift on the ios side.

------
gagabity
There is a google tool that converts Java to Objective C, it should be easy to
find.

------
StreamBright
I would say React Native. For the things you are doing it works perfectly.

------
gok
C.

~~~
tonyedgecombe
Yes.

------
timwaagh
Xamarin (C#) and Cordova (JavaScript) are the usual suspects for such
multiplatform endeavours. You should not use three languages in production if
one is enough.

~~~
arcticbull
There's very limited appetite for introducing JavaScript on any client
platforms. Your iOS app has to introduce a garbage collector, bridging, and
yet another language that nobody on your team knows. Android has to spin up a
_second_ garbage collector.

C# has all the same problems for core logic, and is all fine and good but you
can't really get a native enough interface out of it.

------
aaronbrethorst
English

