What I want: To share non-UI code between Android and iOS using Swift.
The Problem: Android has NDK support that allows you to run C and C++ code (not Objective C) using the Java Native Interface (JNI). I'm a Java programmer and don't quite understand the ins and outs of compiling C code. What are the general steps I would need to go through in order to be able to access a swift method through the JNI?
Instead of JNI, you can do it with RemObjects Silver. The swift code you write there is not compiled with Apple's Swift toolchain, instead they have their own compiler toolchain called Elements, so Element's Swift which is also known as Silver has some differences with Apple's swift. It has been extended so that it blends nicely into Java and .NET world. You can read more about it here - Silver Language Extentions.
You can use elements from Visual Studio or from their own OS X IDE called Fire. Let me demonstrate on a very simple example with Fire. (Download Elements)
1. Open Fire and Create a New Project. In Project template, choose Shared Project. (the choice of the platform doesn't matter)

2. Under File -> New File create a new empty source file with Code File template. Let's call it logger. (make sure the language selected is swift)
3. Replace the contents of that file with:
#if COOPER
import java.util
#elseif ECHOES
import System.Collections.Generic
import System.Linq
import System.Text
#elseif NOUGAT
import Foundation
#elseif !ELEMENTS
#endif
public class Logger {
public class func logIt(stuff: String){
#if NOUGAT
NSLog("\(stuff)")
#elseif ECHOES
Console.WriteLine("\(stuff)")
#elseif COOPER
System.out.println("\(stuff)")
#elseif !ELEMENTS
print("\(stuff)")
#endif
}
}
This is the most simple example of a logger abstraction that works for each platform. With preprocessor directives you specify the code that will be compiled to each specific platform.
NOUGAT stands for Cocoa
ECHOES stands for .NET
COOPER stands for Java
You can also use !ELEMENTS to indicate the code that you will conditionally compile with other toolchains, for example if you want to build the code with Apple's Swift.


Under Fire -> Preferences, go the 4th tab and ensure that you have JDK, JRE and Android Folder discovered by Fire.
Build the solution. The Android Class Library will build .jar file that you can now use from your Android Studio Project.
Navigate to your Android Class Library project directory, and copy from obj/Dubug/Android the .jar file into your Android Project libs folder.
In Android studio, right click on .jar file and press on Add as Library. Then make sure your build.gradle has compile files('libs/swiftcommons.android.jar') in its dependencies.
This is how Logger will look when decompiled.
package swiftcommons.android;
public class Logger {
public static void logIt(String stuff) {
if(stuff == null) {
throw new IllegalArgumentException("stuff");
} else {
System.out.println(String.format("%s", new Object[]{stuff}));
}
}
public Logger() {
}
}
So now you can call your Logger from your code:
import swiftcommons.android.Logger;
//.....
Logger.logIt("It works..");
Also as a good strategy I will recommend you writing your shared codebase that will compile with Apple's swift toolchain (#IF !ELEMENTS) and Elements for Android. (#IF COOPER). Elements also provide you SwiftBaseLibrary and utilities library called Sugar that you can utilize when compiling with Elements.
You need to export your Swift library as a .so, then you'll have to write a wrapper (JNI) to interact between the Java layer and the library. For the wrapper part, install the NDK.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With