Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Swift to share core code between iOS and Android

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?

like image 316
spierce7 Avatar asked Nov 26 '25 20:11

spierce7


2 Answers

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)

Example: Simple Shared Logger

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.

  1. Under File -> New Project create new Android Class Library and add it to the current solution

  1. In your solution explorer on the left drag your shared project (you can drag from shared project's globe icon) into your android class library references. You then should be able to see your shared project there. You can also delete the source file that Android Class Library has.

  1. Under Fire -> Preferences, go the 4th tab and ensure that you have JDK, JRE and Android Folder discovered by Fire.

  2. Build the solution. The Android Class Library will build .jar file that you can now use from your Android Studio Project.

  3. Navigate to your Android Class Library project directory, and copy from obj/Dubug/Android the .jar file into your Android Project libs folder.

  4. 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.

like image 145
ambientlight Avatar answered Nov 28 '25 08:11

ambientlight


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.

like image 35
mbmc Avatar answered Nov 28 '25 08:11

mbmc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!