How to create a Java library that can be used in other non-MOE Xcode projects

There are multiple facets to this question:

  1. We don’t have a special “MOE library project” that is the cross-platform equivalent of Android AAR. However, you can build cross-platform JAR projects, that you can pull in as a dependency into your Android and your MOE project.
  2. Using this cross-platform Java library in a non-MOE Xcode project is not possible: you will need some changes to the Xcode project to call into the Java build process, to link with the MOE framework, and also add the special linker flags to link in the compiled Java code.
  3. However, one of the main goals of MOE 1.3 was to make the above process as painless as possible. In my opinion MOE 1.3 is less intrusive on an Xcode project than CocoaPods.

To add MOE 1.3 (and your Java library) to an Xcode project, you have to follow these steps:

  1. Create a new MOE project (e.g. with your Java IDE’s New MOE Project)
  2. Replace the generated Xcode project in the MOE project with your existing project. If your project uses Xcode workspaces, you will need to adjust the build.gradle file accordingly, in particular set the following values:
moe {
     xcode {
         project 'path/to/main.xcodeproj'
         mainTarget '<Main Target>'
         testTarget '<Test Target>'
         // New values added
         workspace 'path/to/xcworkspace'
         mainScheme '<Main Scheme Name>'
         testScheme '<Test Scheme Name>'
     }
}
  1. Open the adjusted MOE project in your Java IDE and run the Multi-OS Engine Actions > Inject/Refresh Xcode Project Settings action to add the MOE specific changes to the your Xcode project. This is the equivalent of pod install. (In case of using a workspace with multiple projects this must be the main project e.g. the one where you ran pod install).
  2. You need to initialize MOE VM on application startup. You should replace the usual UIApplicationMain() call in your main method with a call to moevm() (see the Xcode project that is generated by MOE).
  3. You need to add the MOE.Main.Class property to your App’s Info.plist. This property contains a fully qualified Java class name that has a static main() method. This main method will be called by moevm() after the VM startup is complete.
  4. You can keep this main class very simple, e.g. just call UIApplicationMain with the name of your UIApplicationDelegate class implemented in ObjC or Swift:
   public class Main {
      public static void main(String[] args) {
          UIKit.UIApplicationMain(0, null, null, "YourAppDelegateWrittenInObjC");
      }
  }
  1. Add your common library to your build.gradle as a dependency. Also add the appropriate rules in proguard.append.cfg so your library is not thrown out by ProGuard.

At this point you can just click Run in Xcode and it will correctly build your project (including the Java library) and run it. Your common Java code will be in your app, but now you need to expose it somehow to Objective-C / Swift.

There are different strategies on how to do this. We created a few sample projects for the different options. These samples were created for an older version of MOE, and we have not yet got around to including them in the official samples, but you can check them out here. The concept is pretty much the same with the current MOE as well.

Once this process is done, you can commit the code to Git, and a team member can check it out, and use it as a native Xcode project. He will only need to have the JDK installed, but everything else (Gradle, MOE SDK) will be downloaded automatically. He can work from Xcode on the ObjC / Swift code, and does not need to touch a Java IDE (if he does not want to :slight_smile: ).

A few notes about possible future improvement to this process:

  1. The process is pretty straightforward up to setting up the Java main class that can then redirect the control to the native UIApplicationDelegate. We considered adding a separate entry point called moevm_init() that initializes the VM, but does not call the main method, and returns. Then, one could call the usual UIApplicationMain without creating a dummy Main Java class.
  2. MOE 1.3 also includes limited Objective-C stub generation support from Java code. It is used for generating Outlet and Action stubs for use with Storyboards, but the concept could be extended to work like the @objc annotation in Swift for any Java class. We would then package the necessary Nat/J annotations in a separate jar, that would not have any iOS dependencies, so it would be safe to include in a standard Android project.

Hope this helps.