diff --git a/build.gradle.kts b/build.gradle.kts index 286a1a3..598166e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { alias(libs.plugins.androidLibrary).apply(false) alias(libs.plugins.kotlinMultiplatform).apply(false) alias(libs.plugins.vanniktech.mavenPublish).apply(false) + alias(libs.plugins.kotlin.android) apply false } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 076c71a..272773f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,13 @@ mavenPublish = "0.29.0" #Coroutines kotlin-coroutines = "1.9.0" +kotlinVersion = "1.9.0" +coreKtx = "1.15.0" +junit = "4.13.2" +junitVersion = "1.2.1" +espressoCore = "3.6.1" +appcompat = "1.7.0" +material = "1.12.0" [libraries] kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } @@ -16,8 +23,15 @@ nexus-publish = { module = "io.github.gradle-nexus.publish-plugin:io.github.grad #Coroutines kotlin-coroutines = {module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines"} kotlin-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "kotlin-coroutines" } +core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } [plugins] androidLibrary = { id = "com.android.library", version.ref = "agp" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } -vanniktech-mavenPublish = {id = "com.vanniktech.maven.publish", version.ref = "mavenPublish"} \ No newline at end of file +vanniktech-mavenPublish = {id = "com.vanniktech.maven.publish", version.ref = "mavenPublish"} +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" } \ No newline at end of file diff --git a/nativelib/.gitignore b/nativelib/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/nativelib/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/nativelib/build.gradle.kts b/nativelib/build.gradle.kts new file mode 100644 index 0000000..c016ba7 --- /dev/null +++ b/nativelib/build.gradle.kts @@ -0,0 +1,54 @@ +plugins { + alias(libs.plugins.androidLibrary) + alias(libs.plugins.kotlin.android) +} + +android { + namespace = "more.math.nativelib" + compileSdk = 35 + + defaultConfig { + minSdk = 22 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + externalNativeBuild { + cmake { + cppFlags("") + } + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + externalNativeBuild { + cmake { + path("src/main/cpp/CMakeLists.txt") + version = "3.22.1" + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { + + implementation(libs.core.ktx) + implementation(libs.appcompat) + implementation(libs.material) + testImplementation(libs.junit) + androidTestImplementation(libs.ext.junit) + androidTestImplementation(libs.espresso.core) +} \ No newline at end of file diff --git a/nativelib/consumer-rules.pro b/nativelib/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/nativelib/proguard-rules.pro b/nativelib/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/nativelib/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/nativelib/src/androidTest/java/more/math/TestNativeLib.kt b/nativelib/src/androidTest/java/more/math/TestNativeLib.kt new file mode 100644 index 0000000..a473572 --- /dev/null +++ b/nativelib/src/androidTest/java/more/math/TestNativeLib.kt @@ -0,0 +1,15 @@ +package more.math + +import more.math.nativelib.NativeLib +import org.junit.Test +import org.junit.Assert.* + +class TestNativeLib { + @Test + fun testInitString() { + val lib = NativeLib().apply { init() } + val expected = "Hello from C++" + val actual = lib.stringFromJNI() + assertEquals(expected, actual) + } +} \ No newline at end of file diff --git a/nativelib/src/main/cpp/CMakeLists.txt b/nativelib/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..4c5eb6f --- /dev/null +++ b/nativelib/src/main/cpp/CMakeLists.txt @@ -0,0 +1,37 @@ +# For more information about using CMake with Android Studio, read the +# documentation: https://d.android.com/studio/projects/add-native-code.html. +# For more examples on how to use CMake, see https://github.com/android/ndk-samples. + +# Sets the minimum CMake version required for this project. +cmake_minimum_required(VERSION 3.22.1) + +# Declares the project name. The project name can be accessed via ${ PROJECT_NAME}, +# Since this is the top level CMakeLists.txt, the project name is also accessible +# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level +# build script scope). +project("nativelib") + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. +# +# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define +# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME} +# is preferred for the same purpose. +# +# In order to load a library into your app from Java/Kotlin, you must call +# System.loadLibrary() and pass the name of the library defined here; +# for GameActivity/NativeActivity derived applications, the same library name must be +# used in the AndroidManifest.xml file. +add_library(${CMAKE_PROJECT_NAME} SHARED + # List C/C++ source files with relative paths to this CMakeLists.txt. + nativelib.cpp) + +# Specifies libraries CMake should link to your target library. You +# can link libraries from various origins, such as libraries defined in this +# build script, prebuilt third-party libraries, or Android system libraries. +target_link_libraries(${CMAKE_PROJECT_NAME} + # List libraries link to the target library + android + log) \ No newline at end of file diff --git a/nativelib/src/main/cpp/nativelib.cpp b/nativelib/src/main/cpp/nativelib.cpp new file mode 100644 index 0000000..2c50686 --- /dev/null +++ b/nativelib/src/main/cpp/nativelib.cpp @@ -0,0 +1,11 @@ +#include +#include + +extern "C" +JNIEXPORT jstring JNICALL +Java_more_math_nativelib_NativeLib_stringFromJNI( + JNIEnv* env, + jobject thiz) { + std::string hello = "Hello from C++"; + return env->NewStringUTF(hello.c_str()); +} \ No newline at end of file diff --git a/nativelib/src/main/java/more/math/nativelib/NativeLib.kt b/nativelib/src/main/java/more/math/nativelib/NativeLib.kt new file mode 100644 index 0000000..9425580 --- /dev/null +++ b/nativelib/src/main/java/more/math/nativelib/NativeLib.kt @@ -0,0 +1,9 @@ +package more.math.nativelib + +class NativeLib { + external fun stringFromJNI(): String + + fun init() { + System.loadLibrary("nativelib") + } +} \ No newline at end of file diff --git a/nativelib/src/test/java/more/plumsoftware/nativelib/TestNativeLib.kt b/nativelib/src/test/java/more/plumsoftware/nativelib/TestNativeLib.kt new file mode 100644 index 0000000..b995845 --- /dev/null +++ b/nativelib/src/test/java/more/plumsoftware/nativelib/TestNativeLib.kt @@ -0,0 +1,15 @@ +package more.plumsoftware.nativelib + +import more.math.nativelib.NativeLib +import org.junit.Test +import org.junit.Assert.* + +class TestNativeLib { + @Test + fun testInitString() { + val lib = NativeLib().apply { init() } + val expected = "Hello from C++" + val actual = lib.stringFromJNI() + assertEquals(expected, actual) + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 6334017..d6379ac 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,3 +15,4 @@ dependencyResolutionManagement { rootProject.name = "more-math" include(":library") +include(":nativelib")