Android studio create kotlin library

Create and publish a multiplatform library – tutorial

In this tutorial, you will learn how to create a multiplatform library for JVM, JS, and Native platforms, write common tests for all platforms, and publish the library to a local Maven repository.

This library converts raw data – strings and byte arrays – to the Base64 format. It can be used on Kotlin/JVM, Kotlin/JS, and any available Kotlin/Native platform.

You will use different ways to implement the conversion to the Base64 format on different platforms:

For Kotlin/Native – your own implementation.

You will also test your code using common tests, and then publish the library to your local Maven repository.

Set up the environment

You can complete this tutorial on any operating system. Download and install the latest version of IntelliJ IDEA with the latest Kotlin plugin.

Create a project

In IntelliJ IDEA, select File | New | Project.

In the left-hand panel, select Kotlin.

Enter a project name, then in the Multiplatform section select Library as the project template.

Select the Gradle DSL – Kotlin or Groovy.

Specify the JDK, which is required for developing Kotlin projects.

Click Next, and then click Finish.

The wizard will create a sample multiplatform library with the following structure:

Write cross-platform code

Define the classes and interfaces you are going to implement in the common code.

In the commonMain/kotlin directory, create the org.jetbrains.base64 package.

Create the Base64.kt file in the new package.

Define the Base64Encoder interface that converts bytes to the Base64 format:

Define the Base64Factory object to provide an instance of the Base64Encoder interface to the common code:

The factory object is marked with the expect keyword in the cross-platform code. For each platform, you should provide an actual implementation of the Base64Factory object with the platform-specific encoder. Learn more about platform-specific implementations.

Provide platform-specific implementations

Now you will create the actual implementations of the Base64Factory object for each platform:

In the jvmMain/kotlin directory, create the org.jetbrains.base64 package.

Create the Base64.kt file in the new package.

Provide a simple implementation of the Base64Factory object that delegates to the java.util.Base64 class:

IDEA inspections help create actual implementations for an expect declaration.

Pretty simple, right? You’ve provided a platform-specific implementation by using a straightforward delegation to a third-party implementation.

The JS implementation will be very similar to the JVM one.

In the jsMain/kotlin directory, create the org.jetbrains.base64 package.

Create the Base64.kt file in the new package.

Provide a simple implementation of the Base64Factory object that delegates to the btoa() function.

Native

Unfortunately, there is no third-party implementation available for all Kotlin/Native targets, so you need to write it yourself.

In the nativeMain/kotlin directory, create the org.jetbrains.base64 package.

Create the Base64.kt file in the new package.

Provide your own implementation for the Base64Factory object:

Test your library

Now when you have actual implementations of the Base64Factory object for all platforms, it’s time to test your multiplatform library.

To save time on testing, you can write common tests that will be executed on all platforms instead of testing each platform separately.

Prerequisites

Before writing tests, add the encodeToString method with the default implementation to the Base64Encoder interface, which is defined in commonMain/kotlin/org/jetbrains/base64/Base64.kt . This implementation converts byte arrays to strings, which are much easier to test.

You can also provide a more efficient implementation of this method for a specific platform, for example, for JVM in jvmMain/kotlin/org/jetbrains/base64/Base64.kt :

One of the benefits of a multiplatform library is having a default implementation with optional platform-specific overrides.

Write common tests

Now you have a string-based API that you can cover with basic tests.

In the commonTest/kotlin directory, create the org.jetbrains.base64 package.

Create the Base64Test.kt file in the new package.

Add tests to this file:

In the Terminal, execute the check Gradle task:

You can also run the check Gradle task by double-clicking it in the list of Gradle tasks.

The tests will run on all platforms (JVM, JS, and Native).

Читайте также:  Индикатор загрузки процессора андроид

Add platform-specific tests

You can also add tests that will be run only for a specific platform. For example, you can add UTF-16 tests on JVM. Just follow the same steps as for common tests, but create the Base64Test file in jvmTest/kotlin/org/jetbrains/base64 :

This test will automatically run on the JVM platform in addition to the common tests.

Publish your library to the local Maven repository

Your multiplatform library is ready for publishing so that you can use it in other projects.

To publish your library, use the maven-publish Gradle plugin.

In the build.gradle(.kts) file, apply the maven-publish plugin and specify the group and version of your library:

In the Terminal, run the publishToMavenLocal Gradle task to publish your library to your local Maven repository:

You can also run the publishToMavenLocal Gradle task by double-clicking it in the list of Gradle tasks.

Your library will be published to the local Maven repository.

Add a dependency on the published library

Now you can add your library to other multiplatform projects as a dependency.

Add the mavenLocal() repository and add a dependency on your library to the build.gradle(.kts) file.

Summary

In this tutorial, you:

Created a multiplatform library with platform-specific implementations.

Wrote common tests that are executed on all platforms.

Published your library to the local Maven repository.

Источник

Walkthrough: Bind an Android Kotlin library

We’re currently investigating custom binding usage on the Xamarin platform. Please take this survey to inform future development efforts.

Xamarin enables mobile developers to create cross-platform native mobile apps using Visual Studio and C#. You can use the Android platform SDK components out of the box but in many cases you also want to use third-party SDKs written for that platform and Xamarin allows you to do it via bindings. In order to incorporate a third-party Android framework into your Xamarin.Android application, you need to create a Xamarin.Android binding for it before you can use it in your applications.

The Android platform, along with its native languages and tooling, are constantly evolving, including the recent introduction of the Kotlin language, which is set eventually to replace Java. There are a number of 3d party SDKs, which have already been migrated from Java to Kotlin and it presents us with new challenges. Even though the Kotlin binding process is similar to Java, it requires additional steps and configuration settings to successfully build and run as part of a Xamarin.Android application.

The goal of this document is to outline a high-level approach for addressing this scenario and provide a detailed step-by-step guide with a simple example.

Background

Kotlin was released in February 2016 and was positioned as an alternative to the standard Java compiler into Android Studio by 2017. Later in 2019, Google announced that the Kotlin programming language would became its preferred language for Android app developers. The high-level binding approach is similar to the binding process of regular Java libraries with a few important Kotlin specific steps.

Prerequisites

In order to complete this walkthrough, you will need:

Build a native library

The first step is to build a native Kotlin library using Android Studio. The library is usually provided by a third-party developer or available at the Google’s Maven repository and other remote repositories. As an example, in this tutorial a binding for the Bubble Picker Kotlin Library is created:

Download the source code from GitHub for the library and unpack it to a local folder Bubble-Picker.

Launch the Android Studio and select Open an existing Android Studio project menu option choosing the Bubble-Picker local folder:

Verify that the Android Studio is up to date including Gradle. The source code can be successfully built on Android Studio v3.5.3, Gradle v5.4.1. Instructions on how to update Gradle to the latest Gradle version could be found here.

Verify that required Android SDK is installed. The source code requires Android SDK v25. Open Tools > SDK Manager menu option to install SDK components.

Update and synchronize the main build.gradle configuration file located at the root of the project folder:

Set the Kotlin version to 1.3.10

Register default Google’s Maven repository so the support library dependency could be resolved:

Once the configuration file is updated, it’s out of sync and Gradle shows the Sync Now button, press it and wait for the synchronization process to be completed:

Читайте также:  Не ловит сеть у андроида

Gradle’s dependency cache may be corrupt, this sometimes occurs after a network connection timeout. Redownload dependencies and sync project (requires network).

The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem. Stop Gradle build processes (requires restart). In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

Your project may be using a third-party plugin, which is not compatible with the other plugins in the project or the version of Gradle requested by the project.

Open the Gradle menu on the right, navigate to the bubblepicker > Tasks menu, execute the build task by double tapping on it, and wait for the build process to complete:

Open the root folder files browser and navigate to the build folder: Bubble-Picker -> bubblepicker -> build -> outputs -> aar, save the bubblepicker-release.aar file as bubblepicker-v1.0.aar, this file will be used later in the binding process:

The AAR file is an Android archive, which contains the compiled Kotlin source code and assets, required by Android to run an application using this SDK.

Prepare metadata

The second step is to prepare the metadata transformation file, which is used by Xamarin.Android to generate respective C# classes. A Xamarin.Android Binding Project will discover all native classes and members from a given Android archive subsequently generating an XML file with the appropriate metadata. The manually created metadata transformation file is then applied to the previously generated baseline to create the final XML definition file used to generate the C# code.

The metadata usesВ XPathВ syntax and is used by the Bindings Generator to influence the creation of the binding assembly. The Java Binding Metadata article provides more information on transformations, which could be applied:

Create an empty Metadata.xml file:

Define xml transformations:

The native Kotlin library has two dependencies, which you don’t want to expose to C# world, define two transformations to ignore them completely. Important to say, the native members won’t be stripped from the resulting binary, only C# classes won’t be generated. Java Decompiler can be used to identify the dependencies. Run the tool and open the AAR file created earlier, as a result the structure of the Android archive will be shown, reflecting all dependencies, values, resources, manifest, and classes:

The transformations to skip processing these packages are defined using XPath instructions:

The native BubblePicker class has two methods getBackgroundColor and setBackgroundColor and the following transformation will change it into a C# BackgroundColor property:

Unsigned types UInt, UShort, ULong, UByte require special handling. For these types Kotlin changes method names and parameters types automatically, which is reflected in the generated code:

This code is compiled into the following Java byte code:

Moreover, related types such as UIntArray, UShortArray, ULongArray, UByteArray are also affected by Kotlin. The method name is changed to include an additional suffix and parameters are changed to an array of elements of signed versions of the same types. In the example below a parameter of type UIntArray is converted automatically into int[] and the method name is changed from fooUIntArrayMethod to fooUIntArrayMethod—ajY-9A . The latter is discovered by Xamarin.Android tools and generated as a valid method name:

This code is compiled into the following Java byte code:

In order to give it a meaningful name, the following metadata can be added to the Metadata.xml, which will update the name back to originally defined in the Kotlin code:

In the BubblePicker sample, there are no members using unsigned types thus no additional changes are required.

Kotlin members with generic parameters by default transformed into parameters of Java. Lang.Object type. For example, a Kotlin method has a generic parameter :

Once a Xamarin.Android binding is generated, the method is exposed to C# as below:

Java and Kotlin generics are not supported by Xamarin.Android bindings, thus a generalized C# method to access the generic API is created. As a work-around you can create a wrapper Kotlin library and expose required APIs in a strong-typed manner without generics. Alternatively, you can create helpers on C# side to address the issue in the same way via strong-typed APIs.

By transforming the metadata, any changes could be applied to the generated binding. The Binding Java Library article explains in details how the metadata is generated and processed.

Читайте также:  Уведомления приходят без звука андроид почему

Build a binding library

The next step is to create a Xamarin.Android binding project using the Visual Studio binding template, add required metadata, native references and then build the project to produce a consumable library:

Open Visual Studio for Mac and create a new Xamarin.Android Binding Library project, give it a name, in this case testBubblePicker.Binding and complete the wizard. The Xamarin.Android binding template is located by the following path: Android > Library > Binding Library:

In the Transformations folder there are three main transformation files:

  • Metadata.xml – Allows changes to be made to the final API, such as changing the namespace of the generated binding.
  • EnumFields.xml – Contains the mapping between Java int constants and C# enums.
  • EnumMethods.xml – Allows changing method parameters and return types from Java int constants to C# enums.

Keep empty the EnumFields.xml and EnumMethods.xml files and update the Metadata.xml to define your transformations.

Replace the existing Transformations/Metadata.xml file with the Metadata.xml file created at the previous step. In the properties window, verify that the file Build Action is set to TransformationFile:

Add the bubblepicker-v1.0.aar file you built in Step 1 to the binding project as a native reference. To add native library references, open finder and navigate to the folder with the Android archive. Drag and drop the archive into the Jars folder in Solution Explorer. Alternatively, you can use the Add context menu option on the Jars folder and choose Existing Files…. Choose to copy the file to the directory for the purposes of this walkthrough. Be sure to verify that the Build Action is set to LibraryProjectZip:

Add a reference to the Xamarin.Kotlin.StdLib NuGet package. This package is a binding for Kotlin Standard Library. Without this package, the binding will only work if the Kotlin library doesn’t use any Kotlin specific types, otherwise all these members will not be exposed to C# and any app that tries to consume the binding will crash at runtime.

Due to a limitation of the Xamarin.Android, binding tools only a single Android archive (AAR) can be added per binding project. If multiple AAR files need to be included, then multiple Xamarin.Android projects are required, one per each AAR. If this were the case for this walkthrough, then the previous four actions of this step would have to be repeated for each archive. As an alternative option, it is possible to manually merge multiple Android archives as a single archive and as a result you could use a single Xamarin.Android binding project.

The final action is to build the library and make don’t have any compilation errors. In case of compilation errors, they can be addressed and handled using the Metadata.xml file, which you created earlier by adding xml transformation metadata, which will add, remove, or rename library members.

Consume the binding library

The final step is to consume the Xamarin.Android binding library in a Xamarin.Android application. Create a new Xamarin.Android project, add reference to the binding library and render Bubble Picker UI:

Create Xamarin.Android project. Use the Android > App > Android App as a starting point and select Latest and Greatest as you Target Platforms option to avoid compatibility issues. All the following steps target this project:

Add a project reference to the binding project or add a reference the DLL created previously:

Add a reference to the Xamarin.Kotlin.StdLib NuGet package, that you added to the Xamarin.Android binding project earlier. It adds support to any Kotlin specific types that need handing in runtime. Without this package the app can be compiled but will crash at runtime:

Add the BubblePicker control to the Android layout for MainActivity . Open testBubblePicker/Resources/layout/content_main.xml file and append the BubblePicker control node as the last element of the root RelativeLayout control:

Update the source code of the app and add the initialization logic to the MainActivity , which activates the Bubble Picker SDK:

BubblePickerAdapter and BubblePickerListener are two classes to be created from scratch, which handle the bubbles data and control interaction:

Run the app, which should render the Bubble Picker UI:

The sample requires additional code to render elements style and handle interactions but the BubblePicker control has been successfully created and activated.

Источник

Оцените статью