Options for porting a swift codebase (app) to android

After working for about 2 years on an iOS app using swift, my team and i is considering starting the development of the android version.
I had hopes in the "swift world domination" goal, but it seems that it's not there yet. So here's my question :
What are the various options people are actually using / recommanding today for porting an iOS app to android ?

I'm not considering porting the "UI" part of the app anyway (i think a good UI needs to be custom to a platform), so my concern is more about the business logic / data core of the app :

From my quick survey on the internet here are the options i personnaly see :

  • Try to compile it to ARM, and try to have the binary run over existing libraries / framework that exist on android. I have no idea how big of a task it is (how much of foundation actually runs on android ? i don't even know)

  • Use code generation project to automatically translate the maximum amount of swift code to kotlin automatically (such as gryphon), and "fill in" the missing parts.

  • Redevelop it using a cross platform tool (such as kotlin multiplatform, or go with gomobile), reusing the design, and use that version for android. The long term goal being to stop developing the core in swift at all.

  • Redevelop it using a language that really is aimed at maximum portability from the start, either because it's its goal (rust), or because it compiles to C, which runs everywhere (such as nim or haxe).

  • Redevelop everythiing in kotlin, and keep two completely separate codebases, sharing only design papers. That would be the last option, of course.

What's your advice ?

Premature optimisation of code reuse is evil. When in Rome do as Romans do. I'd recommend the last option of your list, i.e. Redevelop in Kotlin. And do it in Jetpack Compose (regardless of whether you use SwiftUI or not - if not that would be another carrot to do so). That's the only way to get a true first class platform experience (hopefully that's what you want). Just imagine this situation in reverse, if you had an app for Android and wanted to do a Swift app - how would you feel about any options on that list other than the last one? Sharing design patterns is fine, just don't overdo it, same reasons.

2 Likes

Actually, the reverse scenario would mean that i would have developped my app in kotlin already, so Kotlin Multiplatform would absolutely be my first choice.
Once again, i'm not talking about UI, just the data part.

Have you tried Readdle's Swift Android toolchain?

They announced it in 2018, and the toolchain appears to be maintained (last commit was August, which brought it up to Swift 5.4, and they have PRs from just a few days ago), so it appears they've been using it for a long time. They also have some sample applications, which should help get you started.

I'd at least give that a try before exploring other options.

From the little documentation that exists about running Swift on Android, it seems like it's going to be a lot of work to run Swift on Android. If you do pull that off and publish to the Google Play Store, that would be amazing!

"Data part" is what I am talking about. E.g. this is the data part of my app:

class Model: ObservableObject {
    @Published var state: AppState
}

Where AppState is a struct with bunch of fields, including optionals, enums with associated values, etc.

Cross-platform-ability is overrated, don't do that (including tools like Flutter or Kotlin Multiplatform or Qt or whatever else). You will waste more time overall than you think you will save by code reuse. Been there, seen that. And that's IMHO of course.

2 Likes

I had a look on that project some time ago and hoped that their work would be integrated into the official swift project since.
I'll definite look it up, but i must say using two different swift toolchain (one for ios, another for android) seems like a recipe for disaster..

I'm not sure why you'd think that; they of course are both versions of the open-source compiler with some patches applied (Apple does not maintain 2 entirely separate compilers, nor did Readdle build their own entirely separate compiler). And it at least appears not have been a disaster for them, else they would not be maintaining it 3.5 years later.

But I don't have first-hand experience of using it, so perhaps somebody who has will be able to reassure you.

And as for cross-platform code? It certainly does exist. No doubt the web browser you're using to view this very page has excellent support for multiple platforms (and very few pieces of software are as complex or as critical as a modern web browser). The notion that you need to rewrite everything "just because" is one I don't think is supported by the evidence.

1 Like

Yes, thanks, i tried to contact people involved with readdle to know a bit more from first hand.

About cross-platform code i think you're replying to another person in the thread, i definitely think it's feasible and a good idea in general whenever possible.

Basically all of the main Foundation module. The only shortcoming is that it does not internally communicate with Java/Kotlin. Therefore localization, ā€œstandardā€ file locations and so on are only aware of Androidā€™s Linux underpinnings and not the system settings by which native applications operate. Those bits of Foundation still ā€œworkā€, but not necessarily the way an Android developer is accustomed to.

I do not work directly with UI applications on Android, but I do deal with many library packages that support it. They all have CI set up to use the official, standard toolchain to compile against this Android SDK to ensure source compatibility, but clients can just as easily use SDKs obtained from other places. The Swift projectā€™s source code supports Android, it just does not provide any SDK preā€compiled as a convenient download yet, because it needs to be adapted to how the developerā€™s NDK is setā€up.

While FoundationNetworking and FoundationXML are theoretically operable, many SDKs do not include them, due to their dependency on libraries that are part of Android, but not part of its API. Using them is more complicated because bundling the dependencies risks double loading issues, but using the system ones risks version mismatches.

Thanks a LOT for your comment. I'll definitely have a look at your setup. Are you able to tell a bit more about your use case ? what kind of swift library package do you work with on Android ? How large, what's the business context, what kind of OS feature do they access, etc..

I'm really looking for as much information as i can before i go down this road. I'm ready to explore and try bleeding edge stuffs, but it is a commercial project so i can't afford to take too much risk. Knowing that it is a proven viable option at least for some use cases would be reassuring.

It's not "rewrite it just because". I am talking from personal sometimes painful experience of working on 2 [Android + iOS] crossplatform projects and 2-3 other crossplatform projects that didn't involve android. In all those cases the costs we paid for crossplatform-ability over the years (maintainability, debugging, troubleshooting, cost of hiring personnel with relevant skills or repurposing existing personnel, extra communication overhead between teams, etc, etc) drafted the costs of native solutions that we finally were settling upon afterwards. The extra peculiarity on Android was NDK/JNI which I would rather stay away from whenever possible. YMMV.

1 Like

What you're describing is a scenario that i've always been worried about as well. That's why i'm also wondering about the "code translation" part (using gryphon or other), where obviously platform neutral code could be "shared" (with swift being the reference implementation), while always keeping a "native-looking" kotlin codebase.

Looking at gryphon, my concern is that it uses custom collection classes to prevent side-effects between swift value-based collection vs jvm reference-based collections. It would make the code pretty awkward. But other than that the language are so similar that i really feel it could be a viable approach.

1 Like

I don't know which of your five options is best- probably depends on your app and what APIs you need to exercise- but it would be easy to try the first option of cross-compiling for Android with my SDK that @SDGGiesbrecht mentioned. I have instructions on building and testing your Swift packages for Android with the official package manager, and a CI on github Actions that you can look at for concrete examples.

2 Likes