<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mikhail Isaev</title>
    <description>The latest articles on Forem by Mikhail Isaev (@imike).</description>
    <link>https://forem.com/imike</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1058615%2Fd687dc0c-b4c8-4af4-8dc8-86cb48b7df6b.jpeg</url>
      <title>Forem: Mikhail Isaev</title>
      <link>https://forem.com/imike</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/imike"/>
    <language>en</language>
    <item>
      <title>Swift on Android: JNIKit 2.11.0: Automatic Memory &amp; 2D Arrays</title>
      <dc:creator>Mikhail Isaev</dc:creator>
      <pubDate>Mon, 27 Oct 2025 02:27:59 +0000</pubDate>
      <link>https://forem.com/imike/swift-on-android-jnikit-2110-automatic-memory-2d-arrays-31k4</link>
      <guid>https://forem.com/imike/swift-on-android-jnikit-2110-automatic-memory-2d-arrays-31k4</guid>
      <description>&lt;p&gt;The ecosystem for Swift on Android just got a significant upgrade with the release of JNIKit 2.11.0. This library simplifies JNI interaction, and this latest version focuses on two major pain points: robust memory management and expanded data structure support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic Memory Control
&lt;/h3&gt;

&lt;p&gt;The days of manually managing JNI references are over.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;JObject&lt;/code&gt; now automatically deletes its underlying &lt;code&gt;jobject&lt;/code&gt; on &lt;code&gt;deinit&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;This logic has been extended to &lt;code&gt;JClass&lt;/code&gt;, &lt;code&gt;JClassLoader&lt;/code&gt;, and &lt;code&gt;JObjectArray&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Takeaway&lt;/strong&gt;: You can now rely entirely on Swift's &lt;code&gt;deinit&lt;/code&gt; for memory management. No more manual deletion or worrying about reference leaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note for Upgraders:&lt;/strong&gt; This is a breaking change if you previously handled memory manually. Also, the internal method &lt;code&gt;env.callObjectMethodPure&lt;/code&gt; has been updated—check the release notes if you use it directly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1D &amp;amp; 2D Array Support
&lt;/h3&gt;

&lt;p&gt;Working with Java arrays is now more Swift-like than ever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1D Arrays&lt;/strong&gt; (e.g., &lt;code&gt;[Int8]&lt;/code&gt;, &lt;code&gt;[Float]&lt;/code&gt;, &lt;code&gt;[Double]&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy initialization from a Swift Array: &lt;code&gt;JIntArray([1, 2, 3])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Efficient iteration to avoid copying large arrays:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;intArray&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;New: 2D Array Support!&lt;/strong&gt; 🎉 (e.g., &lt;code&gt;[[Int32]]&lt;/code&gt;, &lt;code&gt;[[Double]]&lt;/code&gt;)&lt;br&gt;
This is crucial for many Android APIs (like &lt;code&gt;ColorStateList&lt;/code&gt;).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initialize directly from a nested Swift array: &lt;code&gt;JIntArray2D([[1, 2, 3], [4, 5, 6]])&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Iterate or convert back to a Swift array with ease.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Passing arrays to Java methods is now trivial:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// No need to manually create wrapper objects&lt;/span&gt;
&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callVoidMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"send1DArray"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callVoidMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"send2DArray"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enhanced Debugging
&lt;/h3&gt;

&lt;p&gt;Logging for global reference creation/deletion has been greatly improved, making it easier to trace memory issues during development.&lt;/p&gt;

&lt;h4&gt;
  
  
  Links:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/swifdroid/jni-kit/releases/tag/2.11.0" rel="noopener noreferrer"&gt;Full Release Notes on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Try it easily: You can experiment with Swift on Android in a pre-configured environment using the &lt;a href="https://dev.to/swiftstream/the-swift-android-setup-i-always-wanted-285d"&gt;Swift Stream IDE&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find JNIKit useful, giving it a star &lt;a href="https://github.com/swifdroid/jni-kit" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt; helps others discover it and supports the project!&lt;/p&gt;

&lt;p&gt;I'm happy to answer any questions and hear about your experiences using Swift for Android.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>android</category>
      <category>opensource</category>
      <category>jni</category>
    </item>
    <item>
      <title>The Swift Android Setup I Always Wanted</title>
      <dc:creator>Mikhail Isaev</dc:creator>
      <pubDate>Fri, 12 Sep 2025 01:25:14 +0000</pubDate>
      <link>https://forem.com/swiftstream/the-swift-android-setup-i-always-wanted-285d</link>
      <guid>https://forem.com/swiftstream/the-swift-android-setup-i-always-wanted-285d</guid>
      <description>&lt;p&gt;Hi guys, imike here!!!&lt;/p&gt;

&lt;p&gt;Swift 6's game-changing Android NDK support finally let me ship &lt;a href="https://github.com/swifdroid/jni-kit" rel="noopener noreferrer"&gt;JNIKit&lt;/a&gt;, the convenient tool I've been building for the &lt;a href="https://github.com/swifdroid" rel="noopener noreferrer"&gt;SwifDroid&lt;/a&gt; project since the Swift 5 days! The biggest hurdle is now gone: we can simply &lt;code&gt;import Android&lt;/code&gt; instead of wrestling with manual header imports. While the final step, official binary production, is still handled by &lt;a href="https://github.com/finagolfin" rel="noopener noreferrer"&gt;finagolfin&lt;/a&gt;'s fantastic &lt;a href="https://github.com/finagolfin/swift-android-sdk" rel="noopener noreferrer"&gt;swift-android-sdk&lt;/a&gt; (which Swift Stream uses), the Swift project is already planning to make it the official SDK.&lt;/p&gt;

&lt;p&gt;Today, I want to show you how to write your first real native Swift code for Android. It's going to be an interesting journey, so grab a cup of tea and let's begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Need:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt; with &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers" rel="noopener noreferrer"&gt;Dev Containers extension&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://swift.stream" rel="noopener noreferrer"&gt;Swift Stream IDE&lt;/a&gt; extension for VSCode&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Optionally, have Android Studio installed to test your library with a real Android app later.&lt;/p&gt;

&lt;p&gt;Your operating system doesn't matter as long as it can run Docker and VSCode.&lt;/p&gt;

&lt;p&gt;Once you have Docker installed, open VSCode.&lt;/p&gt;

&lt;p&gt;First, make sure you have the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers" rel="noopener noreferrer"&gt;Dev Containers extension&lt;/a&gt; installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmswg07uco6e8mfdx7nea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmswg07uco6e8mfdx7nea.png" alt="VSCode with DevContainers extension installed" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, ensure the &lt;a href="https://marketplace.visualstudio.com/items?itemName=swiftstream.swiftstream" rel="noopener noreferrer"&gt;Swift Stream IDE&lt;/a&gt; extension is also installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmeh55j48s1s9547ysj5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmeh55j48s1s9547ysj5g.png" alt=" " width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you don't have these extensions yet, just search for them in the marketplace and hit &lt;code&gt;Install&lt;/code&gt; (your Captain Obvious 😄)&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a New Project
&lt;/h2&gt;

&lt;p&gt;On the left sidebar in VSCode, click the Swift Stream icon (the bird).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa00n0d6nbbj8xa6hih4v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa00n0d6nbbj8xa6hih4v.png" alt=" " width="770" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...and hit &lt;code&gt;Start New Project&lt;/code&gt; 😏&lt;/p&gt;

&lt;p&gt;Now, enter your project name, for example, &lt;code&gt;MyFirstAndroidLib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F544c5c2bfuh1l8vihx58.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F544c5c2bfuh1l8vihx58.gif" alt=" " width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see that the new project will be created in your home folder by default. You can choose a different folder by clicking the three-dots button.&lt;/p&gt;

&lt;p&gt;The next step is to choose the project type. For us, it's &lt;code&gt;Android -&amp;gt; Library&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11rm2norbs80ora8z2kp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11rm2norbs80ora8z2kp.gif" alt=" " width="760" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;code&gt;Create Project&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, enter the Java namespace for your library. This is usually your domain name in reverse (e.g., &lt;code&gt;com.example.mylib&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zsiee98z6uhf2xd4ln1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zsiee98z6uhf2xd4ln1.png" alt=" " width="800" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After entering the namespace, hit Enter to move to the next step, where you'll choose the &lt;code&gt;Android Min SDK Version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbe9hly9r0vltiomymb4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbe9hly9r0vltiomymb4.png" alt=" " width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd recommend choosing &lt;strong&gt;24&lt;/strong&gt; or &lt;strong&gt;29&lt;/strong&gt;, depending on your needs. Hit &lt;code&gt;Enter&lt;/code&gt; again to choose the &lt;code&gt;Android Compile SDK Version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u5kgte9wd9d3uzgkzca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7u5kgte9wd9d3uzgkzca.png" alt=" " width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As of today, &lt;strong&gt;35&lt;/strong&gt; is a good choice. Hit &lt;code&gt;Enter&lt;/code&gt; one more time to start the project creation process.&lt;/p&gt;

&lt;p&gt;At this point, VSCode will create a folder with all the project files and begin downloading the Docker image with a ready-to-use Android development environment.&lt;/p&gt;

&lt;p&gt;Once the image is downloaded, it will start the container and open a new VSCode window with your project inside it. The container will then download the Swift toolchain, Swift for Android SDK, Gradle, Android NDK, and Android SDK. These tools are cached on shared Docker volumes, so your next project will be created in seconds. However, this first launch might take some time, so please be patient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F099navssga0fz4aeok89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F099navssga0fz4aeok89.png" alt=" " width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you're all set! Ready to write some code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Preambula
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is JNI
&lt;/h3&gt;

&lt;p&gt;The Java Native Interface (JNI) is a bridge that lets native code talk to the Java Virtual Machine. Here’s the deal: if you're writing Java code, you use the Android SDK. But if you're using a language like Swift or C++ that doesn't compile to Java Bytecode, you need the Android NDK to communicate with Java through JNI.&lt;/p&gt;

&lt;p&gt;Using JNI, you can do pretty much anything you can do in Java, the real challenge is doing it in a way that isn't a total headache.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is JNIKit
&lt;/h3&gt;

&lt;p&gt;This is where JNIKit comes in! To feel comfortable and stay productive, we need a convenient layer that wraps those low-level, C-style JNI calls into something much more elegant and Swifty. That’s exactly what JNIKit is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;p&gt;At its heart, it's a pure Swift Package Manager project. The key dependencies are &lt;code&gt;JNIKit&lt;/code&gt;, and &lt;code&gt;AndroidLogging&lt;/code&gt; with &lt;code&gt;swift-log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Your Swift code lives in &lt;code&gt;Sources/&amp;lt;target_name&amp;gt;/Library.swift&lt;/code&gt; by default.&lt;/p&gt;

&lt;p&gt;The Android library (a Gradle project) is in the &lt;code&gt;Library&lt;/code&gt; folder. This folder will be automatically generated after your first Swift build. Alternatively, you can create it manually from the Swift Stream sidebar panel.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Swift Code
&lt;/h3&gt;

&lt;p&gt;Everything starts with an &lt;code&gt;initialize&lt;/code&gt; method. This method is exposed to the Java/Kotlin side and must be called before any other native methods.&lt;/p&gt;

&lt;p&gt;The following code shows how to use &lt;code&gt;@_cdecl&lt;/code&gt; to expose this method for JNI.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;@_cdecl&lt;/code&gt; naming convention is critical, as it follows the JNI pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;Java_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;package&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;package&lt;/code&gt; is the fully qualified package name with underscores instead of dots&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;class&lt;/code&gt; is the class name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;method&lt;/code&gt; is the method name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The method's arguments also follow JNI convention. The first two are required and are passed automatically by the JNI:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;envPointer&lt;/code&gt;: This never changes. It's a pointer to the JNI environment, your main interface for interacting with the JVM.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clazzRef&lt;/code&gt; or &lt;code&gt;thizRef&lt;/code&gt;: You get &lt;code&gt;clazzRef&lt;/code&gt; if the Java method is static (like in our case, where the method is inside a Kotlin &lt;code&gt;object&lt;/code&gt;). You get &lt;code&gt;thizRef&lt;/code&gt; if it's an instance method. The first is a pointer to a class; the second is a pointer to an instance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Any arguments after these represent the parameters of the Java/Kotlin method itself. In our case, the method has one extra argument: a &lt;code&gt;caller&lt;/code&gt; object. We pass this from the app to provide context. This &lt;code&gt;caller&lt;/code&gt; instance is necessary to cache the app's class loader (more on that later). Note: if we had &lt;code&gt;thizRef&lt;/code&gt; instead of &lt;code&gt;clazzRef&lt;/code&gt;, we might not need to pass this extra &lt;code&gt;caller&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Java_to_dev_myandroidlib_myfirstandroidproject_SwiftInterface_initialize"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;JNIEnv&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;clazzRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;callerRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Activate Android logger&lt;/span&gt;
    &lt;span class="kt"&gt;LoggingSystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bootstrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;AndroidLogHandler&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;taggedBySource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Initialize JVM&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;jvm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;envPointer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jvm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kt"&gt;JNIKit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;with&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jvm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// ALSO: class loader cache example&lt;/span&gt;
    &lt;span class="c1"&gt;// ALSO: `toString` example&lt;/span&gt;
    &lt;span class="c1"&gt;// ALSO: `Task` example&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The method body shows we first bootstrap the Swift logging system with the Android logger (this only needs to be done once).&lt;/p&gt;

&lt;p&gt;After that, we can use the logger anywhere, simply like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"🐦‍🔥 SWIFT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🚀 Hello World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we initialize the connection to the JVM. At this point, we're good to go!&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Loader and Cache
&lt;/h4&gt;

&lt;p&gt;Here's a common gotcha: by default, when you try to find a Java class via JNI, it uses a system class loader. This system loader (surprise, surprise!) can't see dynamically loaded classes from your app, meaning it misses your own classes and any Gradle dependencies.&lt;/p&gt;

&lt;p&gt;The solution? We need to get the application's class loader, which is available from any Java object via &lt;code&gt;.getClass().getClassLoader()&lt;/code&gt;. The best practice is to grab this class loader once during initialization, create a global reference to it, store it in JNIKit's cache, and use it everywhere. It remains valid for the entire app lifecycle.&lt;/p&gt;

&lt;p&gt;Here’s how to cache it in the &lt;code&gt;initialize&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Access current environment&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;localEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Convert caller's local ref into global ref&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;callerBox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callerRef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// Defer block to clean up local references&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Release local ref to caller object&lt;/span&gt;
    &lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteLocalRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callerRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Initialize `JObject` from boxed global reference to the caller object&lt;/span&gt;
&lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;callerObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callerBox&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Cache the class loader from the caller object&lt;/span&gt;
&lt;span class="c1"&gt;// it is important to load non-system classes later&lt;/span&gt;
&lt;span class="c1"&gt;// e.g. your own Java/Kotlin classes&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;classLoader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callerObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getClassLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;JNICache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shared&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setClassLoader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;classLoader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🚀 class loader cached successfully"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: You would use &lt;code&gt;thizRef&lt;/code&gt; instead of &lt;code&gt;callerRef&lt;/code&gt; if your native method was an instance method.&lt;/p&gt;

&lt;h4&gt;
  
  
  Can I use Java's &lt;code&gt;toString()&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Yup, of course! It's a crucial Java method, and JNIKit makes using it as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🚀 caller description: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;someObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Environment on Another Thread
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;JNIEnv&lt;/code&gt; is tied to the current thread. This environment is the bridge that does all the magic, transferring calls to and from the JVM.&lt;/p&gt;

&lt;p&gt;If you switch threads (e.g., in a &lt;code&gt;Task&lt;/code&gt;), you must attach a JNI environment to that new thread. JNIKit provides a simple method for this: &lt;code&gt;JEnv.current()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kt"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Access current environment in this thread&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🚀 new env: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Print JNI version into LogCat&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🚀 jni version: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVersionString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How the Code Looks on the Other Side
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Java
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SwiftInterface&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;loadLibrary&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyFirstAndroidProject"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;SwiftInterface&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;native&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;caller&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Kotlin
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;SwiftInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;init&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadLibrary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyFirstAndroidProject"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swift Stream generates the Kotlin files for you, so we'll stick with that. We'll see more JNI examples in a bit 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Swift Project
&lt;/h2&gt;

&lt;p&gt;Alright, time to build! Switch to the &lt;code&gt;Swift Stream&lt;/code&gt; tab on the left sidebar and hit &lt;code&gt;Project -&amp;gt; Build&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4u2nq4hnrkkfs8i9dzj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4u2nq4hnrkkfs8i9dzj.png" alt=" " width="668" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll be prompted to choose a &lt;code&gt;Debug&lt;/code&gt; or &lt;code&gt;Release&lt;/code&gt; scheme.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcslq71lb8n2e1owm3wpc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcslq71lb8n2e1owm3wpc.png" alt=" " width="500" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's go with &lt;code&gt;Debug&lt;/code&gt; for now. The building process will begin.&lt;/p&gt;

&lt;p&gt;In Swift Stream, you can choose the &lt;code&gt;Log Level&lt;/code&gt; to control how much detail you see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Normal&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detailed&lt;/strong&gt; (This is the default)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verbose&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unbearable&lt;/strong&gt; (For when you really need to see everything)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the default Detailed level, you'll see an output similar to this during the build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;🏗️ Started building debug
💁‍♂️ it will try to build each phase
🔦 Resolving Swift dependencies &lt;span class="k"&gt;for &lt;/span&gt;native
🔦 Resolved &lt;span class="k"&gt;in &lt;/span&gt;772ms
🔦 Resolving Swift dependencies &lt;span class="k"&gt;for &lt;/span&gt;droid
🔦 Resolved &lt;span class="k"&gt;in &lt;/span&gt;2s918ms
🧱 Building &lt;span class="sb"&gt;`&lt;/span&gt;MyFirstAndroidProject&lt;span class="sb"&gt;`&lt;/span&gt; swift target &lt;span class="k"&gt;for &lt;/span&gt;arm64-v8a
🧱 Built &lt;span class="sb"&gt;`&lt;/span&gt;MyFirstAndroidProject&lt;span class="sb"&gt;`&lt;/span&gt; swift target &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;.droid&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;10s184ms
🧱 Building &lt;span class="sb"&gt;`&lt;/span&gt;MyFirstAndroidProject&lt;span class="sb"&gt;`&lt;/span&gt; swift target &lt;span class="k"&gt;for &lt;/span&gt;armeabi-v7a
🧱 Built &lt;span class="sb"&gt;`&lt;/span&gt;MyFirstAndroidProject&lt;span class="sb"&gt;`&lt;/span&gt; swift target &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;.droid&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;7s202ms
🧱 Building &lt;span class="sb"&gt;`&lt;/span&gt;MyFirstAndroidProject&lt;span class="sb"&gt;`&lt;/span&gt; swift target &lt;span class="k"&gt;for &lt;/span&gt;x86_64
🧱 Built &lt;span class="sb"&gt;`&lt;/span&gt;MyFirstAndroidProject&lt;span class="sb"&gt;`&lt;/span&gt; swift target &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="sb"&gt;`&lt;/span&gt;.droid&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;in &lt;/span&gt;7s135ms
🧱 Preparing gradle wrapper
🧱 Prepared gradle wrapper &lt;span class="k"&gt;in &lt;/span&gt;1m50s
✅ Build Succeeded &lt;span class="k"&gt;in &lt;/span&gt;2m20s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the initial Swift compilation itself was pretty fast, about &lt;strong&gt;~30 seconds&lt;/strong&gt; total for all three architecture targets (arm64-v8a, armeabi-v7a, and x86_64). The bulk of the time (1m50s) was spent on the initial &lt;code&gt;gradle wrapper&lt;/code&gt; setup, which is a one-time cost.&lt;/p&gt;

&lt;p&gt;The great news is that &lt;strong&gt;subsequent builds will be super fast&lt;/strong&gt;, taking only about 3 seconds for all three targets! This is because everything gets cached.&lt;/p&gt;

&lt;p&gt;This build command also automatically generates the Java Library Gradle project for you. It's now ready to use in the &lt;code&gt;Library&lt;/code&gt; folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Java/Kotlin Project
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Source Code
&lt;/h4&gt;

&lt;p&gt;Swift Stream generates the initial boilerplate code for your library, which you'll then maintain and extend.&lt;/p&gt;

&lt;p&gt;Here’s a sample of the generated Kotlin interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;android.util.Log&lt;/span&gt;

&lt;span class="kd"&gt;object&lt;/span&gt; &lt;span class="nc"&gt;SwiftInterface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;init&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadLibrary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyFirstAndroidProject"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caller&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendIntArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IntArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchAsyncData&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Gradle Files
&lt;/h4&gt;

&lt;p&gt;Swift Stream IDE automatically manages your Gradle project. It generates Java packages based on your Swift targets from &lt;code&gt;Package.swift&lt;/code&gt; and keeps all the Gradle files in sync.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Library/settings.gradle.kts&lt;/code&gt;, it manages the list of included targets within special comment tags:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="c1"&gt;// managed by swiftstreamide: includes-begin&lt;/span&gt;
&lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":myfirstandroidproject"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// managed by swiftstreamide: includes-end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In each &lt;code&gt;Library/&amp;lt;target&amp;gt;/build.gradle.kts&lt;/code&gt; file, it automatically manages dependencies based on the imports in your Swift code and the Swift version you're using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:core:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// managed by swiftstreamide: so-dependencies-begin&lt;/span&gt;
&lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:foundation:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:foundationessentials:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:i18n:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// managed by swiftstreamide: so-dependencies-end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, these dependencies are fetched automatically from the SwifDroid &lt;code&gt;runtime-libs&lt;/code&gt; JitPack repository, which is maintained for each supported Swift version. This means no manual copying of &lt;code&gt;.so&lt;/code&gt; files from the Android SDK bundle!&lt;/p&gt;

&lt;p&gt;But if you need more control, you can take over manually, still without the hassle of manual file copying. The Swift Stream IDE uses a configuration file (&lt;code&gt;.vscode/android-stream.json&lt;/code&gt;) where you can set the &lt;code&gt;soMode&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"soMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Packed"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;"Packed"&lt;/code&gt; (the default) means Gradle imports everything from JitPack. You can switch to &lt;code&gt;"PickedManually"&lt;/code&gt; to specify only the &lt;code&gt;.so&lt;/code&gt; files you actually need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"soMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PickedManually"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"schemes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MyFirstAndroidProject Debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"soFiles"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"libandroid.so"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"libc.so"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"libm.so"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This config file is also where you control other key project settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"packageName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"to.dev.myandroidlib"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"compileSDK"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"minSDK"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"javaVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can even pass custom arguments directly to the Swift compiler for fine-grained control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"schemes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MyFirstAndroidProject Debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"swiftArgs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Assemble with Gradle
&lt;/h4&gt;

&lt;p&gt;Finally, to build the distributable Android library files (&lt;code&gt;.aar&lt;/code&gt;), just hit &lt;code&gt;Java Library Project -&amp;gt; Assemble&lt;/code&gt; in the Swift Stream sidebar.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmxr93j1k024jz4m8rrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbmxr93j1k024jz4m8rrs.png" alt=" " width="684" height="112"&gt;&lt;/a&gt;&lt;br&gt;
This command runs either &lt;code&gt;gradlew assembleDebug&lt;/code&gt; or &lt;code&gt;gradlew assembleRelease&lt;/code&gt; in the background, packaging everything up for distribution.&lt;/p&gt;
&lt;h2&gt;
  
  
  Add This Library to Your Android Project (Locally)
&lt;/h2&gt;

&lt;p&gt;Now for the fun part, let's use this library in a real Android app! Open your existing project or create a new one in Android Studio.&lt;/p&gt;

&lt;p&gt;Once your project is open, the first step is to add JitPack as a repository. Navigate to your &lt;code&gt;settings.gradle.kts&lt;/code&gt; file and make sure it includes the JitPack repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencyResolutionManagement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;repositoriesMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;RepositoriesMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;FAIL_ON_PROJECT_REPOS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;repositories&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;google&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;maven&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://jitpack.io"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;mavenCentral&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you need to add the dependencies to your app module's &lt;code&gt;build.gradle.kts&lt;/code&gt; file (&lt;code&gt;app/build.gradle.kts&lt;/code&gt;). You must include both the &lt;code&gt;.aar&lt;/code&gt; file and all the necessary runtime libraries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nf"&gt;dependencies&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;files&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"libs/myfirstandroidproject-debug.aar"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:core:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:foundation:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:foundationessentials:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;implementation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.github.swifdroid.runtime-libs:i18n:6.1.3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// the rest of dependencies&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: You have to manually list these dependencies because Android can't automatically pick them up from inside the &lt;code&gt;.aar&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Getting the .AAR File
&lt;/h4&gt;

&lt;p&gt;Now, grab your freshly built library file! You'll find the &lt;code&gt;.aar&lt;/code&gt; file in your Swift Stream project at this path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Library/myfirstandroidproject/build/outputs/aar/myfirstandroidproject-debug.aar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy this file. Then, in your Android Studio project, navigate to your app module's directory (e.g., &lt;code&gt;app/&lt;/code&gt;) and create a folder named &lt;code&gt;libs&lt;/code&gt; right next to the &lt;code&gt;build.gradle.kts&lt;/code&gt; file. Paste the &lt;code&gt;.aar&lt;/code&gt; file into this new &lt;code&gt;libs&lt;/code&gt; folder.&lt;/p&gt;

&lt;h4&gt;
  
  
  Let the Magic Begin! 🚀
&lt;/h4&gt;

&lt;p&gt;You're all set! Now, somewhere in your app, typically in your &lt;code&gt;Application&lt;/code&gt; class or the &lt;code&gt;onCreate&lt;/code&gt; of your main activity, initialize the Swift code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;SwiftInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sync your Gradle project, build it, and run it on a device or emulator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The moment of truth&lt;/strong&gt;: Open LogCat and filter for "SWIFT". You should see our glorious message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; I  &lt;span class="o"&gt;[&lt;/span&gt;🐦‍🔥 SWIFT] 🚀 Hello World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yaaay! Your Swift code is now running on Android.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Development Loop
&lt;/h4&gt;

&lt;p&gt;When you make changes to your Swift code, here’s your quick update cycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In Swift Stream, hit &lt;code&gt;Project -&amp;gt; Build&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then, hit &lt;code&gt;Java Library Project -&amp;gt; Assemble&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy the new &lt;code&gt;.aar&lt;/code&gt; file from the &lt;code&gt;outputs/aar&lt;/code&gt; folder into your Android project's &lt;code&gt;app/libs&lt;/code&gt; folder, replacing the old one.&lt;/li&gt;
&lt;li&gt;Rebuild and run your Android app!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it! You're now a cross-platform Swift developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  JNI Examples
&lt;/h2&gt;

&lt;p&gt;Now for the most exciting part, the code! Let's talk about how to communicate between Swift and Java/Kotlin. We'll stick with Kotlin, as it's the standard for Android development today.&lt;/p&gt;

&lt;p&gt;We'll cover a few simple but common scenarios in this article and dive into more complex ones next time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Crucial&lt;/strong&gt;: Don't forget to call &lt;code&gt;SwiftInterface.initialize(this)&lt;/code&gt; before any other native calls!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Sending an &lt;code&gt;Int&lt;/code&gt; from Kotlin to Swift
&lt;/h4&gt;

&lt;p&gt;Let's start simple. Declare a method in &lt;code&gt;SwiftInterface.kt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Swift side, implement it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Java_to_dev_myandroidlib_myfirstandroidproject_SwiftInterface_sendInt"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;sendInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;JNIEnv&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;clazzRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jint&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"🐦‍🔥 SWIFT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"#️⃣ sendInt: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it from your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;SwiftInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check LogCat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; I  [🐦‍🔥 SWIFT] #️⃣ sendInt: 123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Too easy, right? :)&lt;/p&gt;

&lt;h4&gt;
  
  
  Sending an &lt;code&gt;IntArray&lt;/code&gt; from Kotlin to Swift
&lt;/h4&gt;

&lt;p&gt;Declare the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendIntArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;IntArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Swift side, handle the array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Java_to_dev_myandroidlib_myfirstandroidproject_SwiftInterface_sendIntArray"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;sendIntArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;JNIEnv&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;clazzRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;arrayRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jintArray&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create lightweight logger object&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"🐦‍🔥 SWIFT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Access current environment&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;localEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Defer block to clean up local references&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Release local ref to array object&lt;/span&gt;
        &lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteLocalRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrayRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Get array length&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🔢 sendIntArray 1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getArrayLength&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrayRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🔢 sendIntArray 2 length: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Get array elements&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;swiftArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="nv"&gt;repeating&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getIntArrayRegion&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrayRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;swiftArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Now you can use `swiftArray` as a regular Swift array&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"🔢 sendIntArray 3 swiftArray: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;swiftArray&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it from your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;SwiftInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendIntArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;intArrayOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check LogCat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; I  [🐦‍🔥 SWIFT] 🔢 sendIntArray: 1
 I  [🐦‍🔥 SWIFT] 🔢 sendIntArray: 2 length: 3
 I  [🐦‍🔥 SWIFT] 🔢 sendIntArray: 3 swiftArray: [7, 6, 5]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Sending a &lt;code&gt;String&lt;/code&gt; from Kotlin to Swift
&lt;/h4&gt;

&lt;p&gt;Declare the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Swift side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Java_to_dev_myandroidlib_myfirstandroidproject_SwiftInterface_sendString"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;sendString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;JNIEnv&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;clazzRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;strRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create lightweight logger object&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"🐦‍🔥 SWIFT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Access current environment&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;localEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Defer block to clean up local references&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Release local ref to string object&lt;/span&gt;
        &lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteLocalRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Wrap JNI string reference into `JString` and get Swift string&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"✍️ sendString 1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strRef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"✍️ sendString 1.1 exit: unable to unwrap jstring"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Now you can use `string` as a regular Swift string&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"✍️ sendString 2: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it from your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;SwiftInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"With love from Java"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check LogCat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; I  [🐦‍🔥 SWIFT] ✍️ sendString 1
 I  [🐦‍🔥 SWIFT] ✍️ sendString 2: With love from Java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Sending a &lt;code&gt;Date&lt;/code&gt; Object from Kotlin to Swift
&lt;/h4&gt;

&lt;p&gt;Declare the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;sendDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Swift side:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Java_to_dev_myandroidlib_myfirstandroidproject_SwiftInterface_sendDate"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;sendDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;JNIEnv&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;clazzRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dateRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create lightweight logger object&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"🐦‍🔥 SWIFT"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Access current environment&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;localEnv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Defer block to clean up local references&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Release local ref to date object&lt;/span&gt;
        &lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deleteLocalRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dateRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Wrap JNI date reference into `JObjectBox`&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"📅 sendDate 1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dateRef&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;localEnv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"📅 sendDate 1.1 exit: unable to box Date object"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Initialize `JObject` from boxed global reference to the date&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"📅 sendDate 2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;dateObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"📅 sendDate 2.1 exit: unable to unwrap Date object"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Call `getTime` method to get milliseconds since epoch&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"📅 sendDate 3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;milliseconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dateObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callLongMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"getTime"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"📅 sendDate 3.1 exit: getTime returned nil, maybe wrong method"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Now you can use `milliseconds` as a regular Swift Int64 value&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"📅 sendDate 4: &lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="n"&gt;milliseconds&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it from your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;SwiftInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendDate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check LogCat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; I  [🐦‍🔥 SWIFT] 📅 sendDate 1
 I  [🐦‍🔥 SWIFT] 📅 sendDate 2
 I  [🐦‍🔥 SWIFT] 📅 sendDate 3
 I  [🐦‍🔥 SWIFT] 📅 sendDate 4: 1757533833096
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Receiving a String from Swift in Kotlin
&lt;/h4&gt;

&lt;p&gt;Declare a method that returns a value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Swift side, return a string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Java_to_dev_myandroidlib_myfirstandroidproject_SwiftInterface_ping"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;ping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;envPointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;JNIEnv&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;clazzRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Wrap Swift string into `JSString` and return its JNI reference&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"🏓 Pong from Swift!"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it from your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;i&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"HELLO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Pinging: ${SwiftInterface.ping()}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check LogCat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; I  Pinging: 🏓 Pong from Swift!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Executing Async/Await Swift Code from Kotlin
&lt;/h4&gt;

&lt;p&gt;Declare the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;fetchAsyncData&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to know that the &lt;code&gt;@_cdecl&lt;/code&gt; attribute doesn't work with the async operator. That's why we're using a &lt;code&gt;semaphore&lt;/code&gt; here to execute our Swift code in a way that feels asynchronous. This approach is totally fine, but only for &lt;code&gt;non-UI&lt;/code&gt; code. If you try this on the main thread, you'll face a complete and total deadlock, so just don't do it. I'll show you how to deal with UI in the next articles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
&lt;span class="kd"&gt;@_cdecl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Java_to_dev_myandroidlib_myfirstandroidproject_SwiftInterface_fetchAsyncData"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;fetchAsyncData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;JNIEnv&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;jobject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;jstring&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Create semaphore to wait for async task&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;semaphore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;DispatchSemaphore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Create result variable&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
    &lt;span class="c1"&gt;// Start async task&lt;/span&gt;
    &lt;span class="kt"&gt;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Simulate async operation&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="kt"&gt;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;nanoseconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5_000_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 5 seconds&lt;/span&gt;
        &lt;span class="c1"&gt;// Set result&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Async data fetched successfully!"&lt;/span&gt;
        &lt;span class="c1"&gt;// Release semaphore&lt;/span&gt;
        &lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Wait for async task to complete by blocking current thread&lt;/span&gt;
    &lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if result is available&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Wrap Swift string into `JSString` and return its JNI reference&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reference&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;#endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call it from your app (off the main thread!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="nc"&gt;CoroutineScope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Dispatchers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;launch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;i&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ASYNC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Swift async call started"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SwiftInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchAsyncData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;i&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ASYNC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Swift returned: $result"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Handle error&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;i&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ASYNC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Swift async call finished"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check LogCat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; I  Swift async call started
 I  Swift returned: Async data fetched successfully!
 I  Swift async call finished
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Wrapping Java Classes in Swift
&lt;/h4&gt;

&lt;p&gt;To use Java classes Swiftly, we need wrappers. Let's create one for &lt;code&gt;java/util/Date&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;JDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;JObjectable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Sendable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;/// The JNI class name&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;className&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;JClassName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"java/util/Date"&lt;/span&gt;

    &lt;span class="c1"&gt;/// JNI global reference object wrapper, it contains class metadata as well.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;JObject&lt;/span&gt;

    &lt;span class="c1"&gt;/// Initializer for when you already have a `JObject` reference.&lt;/span&gt;
    &lt;span class="c1"&gt;/// &lt;/span&gt;
    &lt;span class="c1"&gt;/// This is useful when you receive a `Date` object from Java code.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;object&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;JObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;/// Allocates a `Date` object and initializes it so that it represents the time&lt;/span&gt;
    &lt;span class="c1"&gt;/// at which it was allocated, measured to the nearest millisecond.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
        &lt;span class="k"&gt;guard&lt;/span&gt;
            &lt;span class="c1"&gt;// Access current environment&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="c1"&gt;// It finds the `java.util.Date` class and loads it directly or from the cache&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;clazz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;className&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="c1"&gt;// Call to create a new instance of `java.util.Date` and get a global reference to it&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Store the object to access it from methods&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;
        &lt;span class="cp"&gt;#else&lt;/span&gt;
        &lt;span class="c1"&gt;// For non-Android platforms, return nil&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
        &lt;span class="cp"&gt;#endif&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;/// Allocates a `Date` object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.&lt;/span&gt;
    &lt;span class="c1"&gt;/// &lt;/span&gt;
    &lt;span class="c1"&gt;/// - Parameter milliseconds: The number of milliseconds since January 1, 1970, 00:00:00 GMT.&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;milliseconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cp"&gt;#if os(Android)&lt;/span&gt;
        &lt;span class="k"&gt;guard&lt;/span&gt;
            &lt;span class="c1"&gt;// Access current environment&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JEnv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="c1"&gt;// It finds the `java.util.Date` class and loads it directly or from the cache&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;clazz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;JClass&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;className&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="c1"&gt;// Call to create a new instance of `java.util.Date`&lt;/span&gt;
            &lt;span class="c1"&gt;// with `milliseconds` parameter and get a global reference to it&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;global&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clazz&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;milliseconds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// Store the object to access it from methods&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;global&lt;/span&gt;
        &lt;span class="cp"&gt;#else&lt;/span&gt;
        &lt;span class="c1"&gt;// For non-Android platforms, return nil&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
        &lt;span class="cp"&gt;#endif&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This right here is the absolute bare minimum you need to get this class working. It lets you initialize a &lt;code&gt;java.util.Date&lt;/code&gt; from scratch or wrap an incoming &lt;code&gt;JObject&lt;/code&gt; that's already the right class.&lt;/p&gt;

&lt;p&gt;Alright, the skeleton is built. Now we need to give it some muscles, let's write down the class methods!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// Returns the day of the week represented by this date.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;day&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Convenience call to `java.util.Date.getDay()`&lt;/span&gt;
    &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callIntMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"getDay"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get the idea! Now, go ahead and do the exact same thing for the &lt;code&gt;getHours&lt;/code&gt;, &lt;code&gt;getMinutes&lt;/code&gt;, &lt;code&gt;getSeconds&lt;/code&gt;, and &lt;code&gt;getTime&lt;/code&gt; methods. It's just more of the same pattern!&lt;/p&gt;

&lt;p&gt;Now for something a bit more interesting: a more complex method that takes another &lt;code&gt;JDate&lt;/code&gt; as a parameter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// Tests if this date is before the specified date.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;JDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Convenience call to `java.util.Date.before(Date date)`&lt;/span&gt;
    &lt;span class="c1"&gt;// which passes another `Date` object as a parameter&lt;/span&gt;
    &lt;span class="c1"&gt;// and returns a boolean result&lt;/span&gt;
    &lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callBoolMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"before"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;as&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;JDate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;className&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, you guessed it, do the same thing one more time for the &lt;code&gt;after&lt;/code&gt; method. It's practically identical to &lt;code&gt;before&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, to cover the absolute minimum and make this class actually useful, let's add a super convenient method that converts our Java &lt;code&gt;JDate&lt;/code&gt; into a native Swift &lt;code&gt;Date&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// Converts this java `Date` object to a Swift `Date`.&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Get milliseconds since epoch using `getTime` method&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Convert milliseconds to seconds and create a Swift `Date` object&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;timeIntervalSince1970&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;TimeInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1000.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have a basic understanding of how Swift works with Java/Kotlin via JNI! I hope you've successfully compiled and tested this with your Android project.&lt;/p&gt;

&lt;p&gt;That's all for today, folks!&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;even more deep dives and advanced features&lt;/strong&gt;, check out the comprehensive &lt;a href="http://github.com/swifdroid/jni-kit" rel="noopener noreferrer"&gt;JNIKit README on GitHub&lt;/a&gt;. It's packed with details!&lt;/p&gt;

&lt;p&gt;Find me in Swift Stream &lt;a href="https://discord.com/invite/Wh3n86ttRB" rel="noopener noreferrer"&gt;Discord community&lt;/a&gt;, join and don't hesitate to ask questions!&lt;/p&gt;

&lt;p&gt;Hit subscribe so you don't miss the next article! We'll definitely talk about library distribution via JitPack, dive into more complex JNI cases, and the... UI!&lt;/p&gt;

&lt;p&gt;Stay tuned!&lt;/p&gt;

</description>
      <category>swift</category>
      <category>android</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Systemd for the Swift app</title>
      <dc:creator>Mikhail Isaev</dc:creator>
      <pubDate>Sat, 12 Oct 2024 21:57:21 +0000</pubDate>
      <link>https://forem.com/imike/systemd-for-the-swift-app-g9c</link>
      <guid>https://forem.com/imike/systemd-for-the-swift-app-g9c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post is for server-side Swift developers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All apps on a server need to be launched under some watchdog daemon. You might already be using &lt;code&gt;supervisord&lt;/code&gt; or &lt;code&gt;systemd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This article will show you how to simplify your life with &lt;code&gt;systemd&lt;/code&gt; by integrating it directly into your app.&lt;/p&gt;

&lt;p&gt;First, let's look at how we usually work with &lt;code&gt;systemd&lt;/code&gt; and the steps needed to set up a service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pure &lt;code&gt;systemd&lt;/code&gt;
&lt;/h2&gt;

&lt;h4&gt;
  
  
  Setting Up
&lt;/h4&gt;

&lt;p&gt;Create a unit configuration file manually by searching for examples online and saving it in the &lt;code&gt;/etc/systemd/system&lt;/code&gt; folder.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Not so easy, right? Most people give up somewhere around here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Management
&lt;/h4&gt;

&lt;p&gt;You have to remember a few simple commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl start   myapp.service
          restart myapp.service
          stop    myapp.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;But also the name you gave your service 🙉&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Don't forget to start your app after creating the unit configuration file.&lt;/p&gt;

&lt;h4&gt;
  
  
  If You Want to Remove the Service
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl stop myapp.service
systemctl start clean --all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Not too hard to remember, but still...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Logs
&lt;/h4&gt;

&lt;p&gt;This is where most people get lost, because logs can either be stored in some &lt;code&gt;.log&lt;/code&gt; files somewhere in the system, or you have to use &lt;code&gt;journalctl&lt;/code&gt; commands like these:&lt;/p&gt;

&lt;h5&gt;
  
  
  For live logs:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;journalctl -u myapp -f
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  For the last few log lines:
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;journalctl -u myapp -n 100 --no-pager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I believe it's a bit hard to remember, and I often use the &lt;code&gt;up-arrow&lt;/code&gt; in the console to find the right command from history.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🍰 The Swift Plugin Way
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/MihaelIsaev/SwiftSystemd" rel="noopener noreferrer"&gt;SwiftSystemd&lt;/a&gt;&lt;/strong&gt; to the rescue!&lt;/p&gt;

&lt;p&gt;It provides a simple way to handle all the above without headaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡️ Installation
&lt;/h3&gt;

&lt;p&gt;Open your app's &lt;code&gt;Package.swift&lt;/code&gt; and add just one line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/MihaelIsaev/SwiftSystemd.git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, you're ready to go!&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Setting Up
&lt;/h3&gt;

&lt;p&gt;Let's see how to create a proper unit configuration file for &lt;code&gt;systemd&lt;/code&gt;. In the folder with your app, just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will prompt you with a few questions in the console, and then you're done.&lt;/p&gt;

&lt;p&gt;Or you can specify the answers in advance like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd install -c release -t App -u mike
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where&lt;br&gt;
&lt;code&gt;-c&lt;/code&gt; or &lt;code&gt;--config&lt;/code&gt;  is for configuration: &lt;code&gt;release&lt;/code&gt; or &lt;code&gt;debug&lt;/code&gt;&lt;br&gt;
&lt;code&gt;-t&lt;/code&gt; or &lt;code&gt;--target&lt;/code&gt;  is for Executable target name&lt;br&gt;
&lt;code&gt;-u&lt;/code&gt; or &lt;code&gt;--user&lt;/code&gt;    is for user under which the service will run&lt;/p&gt;

&lt;p&gt;This command generates the following unit config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description="AppName"
After=network.target

[Service]
User={user}
EnvironmentFile=/path/to/AppName/.env
WorkingDirectory=/path/to/AppName
TimeoutStopSec=2

Restart=always

ExecStart=/path/to/AppName/.build/{config}/{target}

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;That's it! You've set up your app the right way in just two simple steps, and it's already running.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  📋 Logs
&lt;/h3&gt;

&lt;p&gt;One of the most essential tasks is watching logs, and it's as easy as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This displays live logs of your app via &lt;code&gt;journalctl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd logs --limit 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows the last &lt;code&gt;100&lt;/code&gt; lines from your app's log via &lt;code&gt;journalctl&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Easy to remember!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🎛️ Management
&lt;/h3&gt;

&lt;p&gt;You can check the app's status by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or manage the app state with the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd start    # starts the app
                  stop     # stops the app
                  restart  # restart the app
                  disable  # temporarily disables the app
                  enable   # re-enables the app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also send a &lt;code&gt;kill&lt;/code&gt; signal to the app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd kill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧹 Cleaning Up
&lt;/h3&gt;

&lt;p&gt;If you no longer need the service, you can remove it easily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;swift run systemd uninstall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This deletes the &lt;code&gt;systemd&lt;/code&gt; configuration file and stops the service if it's still active.&lt;/p&gt;

&lt;h1&gt;
  
  
  👏 Conclusion
&lt;/h1&gt;

&lt;p&gt;I believe you can now throw away all your &lt;code&gt;systemctl&lt;/code&gt; and &lt;code&gt;journalctl&lt;/code&gt; notes, just like I did!&lt;/p&gt;

&lt;p&gt;❤️ Feel free to contribute!&lt;/p&gt;

</description>
      <category>swift</category>
      <category>vapor</category>
      <category>linux</category>
      <category>systemctl</category>
    </item>
  </channel>
</rss>
