5

Saying that I've spent around 32 hours would be an understatement. I've been trying to enable Kotlin in a React Native project powered by Expo SDK 44.

I've been trying everything that I could find over the Internet, but it always ends up with an error in the Gradle Phase in EAS (Running it with eas build --profile development --platform android) .

Here are my configurations:

I'm omitting code for brevity. If you need more context, let me know

app\android\build.gradle:

buildscript {
    ext {
        buildToolsVersion = "30.0.2"
        minSdkVersion = 21
        compileSdkVersion = 31
        targetSdkVersion = 31
        kotlinVersion = "1.4.11"
    }
    repositories {
        google()
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:4.1.0")
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
       
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
apply plugin: "kotlin-android"
apply plugin: "kotlin-android-extensions"

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    //noinspection GradleDynamicVersion
    implementation "com.facebook.react:react-native:+"  // From node_modules
    implementation project(':react-native-plaid-link-sdk')

    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3'
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3'
    implementation 'androidx.core:core-ktx:1.1.0'
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"

// Other comed omitted
}

Here's my package.json

{
    "name": "@pana/app",
    "version": "22.0220",
    "private": true,
    "scripts": {
        "start": "expo start --dev-client",
        "android": "expo run:android",
        "ios": "expo run:ios",
        "eject": "expo eject",
        "extract": "lingui extract",
        "compile": "lingui compile",
        "lint": "eslint src/** --ext .ts,.tsx",
        "lint:fix": "yarn lint --fix",
        "test": "jest",
        "graphql:generate": "graphql-codegen --config codegen.yml",
        "build": ""
    },
    "dependencies": {
        "@apollo/client": "^3.5.10",
        "@apollo/link-context": "^2.0.0-beta.3",
        "@expo/react-native-action-sheet": "^3.13.0",
        "@intercom/intercom-react-native": "^3.0.0",
        "@lingui/react": "^3.13.2",
        "@onfido/react-native-sdk": "^5.1.0",
        "@react-native-async-storage/async-storage": "~1.15.0",
        "@react-native-community/datetimepicker": "4.0.0",
        "@react-navigation/bottom-tabs": "^6.3.1",
        "@react-navigation/native": "^6.0.8",
        "@react-navigation/stack": "^6.1.1",
        "@reduxjs/toolkit": "^1.8.0",
        "@segment/analytics-react-native": "^2.1.12",
        "@segment/sovran-react-native": "^0.2.6",
        "@sentry/react-native": "^3.2.13",
        "axios": "^0.25.0",
        "dayjs": "^1.10.8",
        "expo": "~44.0.0",
        "expo-application": "~4.0.1",
        "expo-auth-session": "~3.5.0",
        "expo-cellular": "~4.1.0",
        "expo-clipboard": "~2.1.0",
        "expo-constants": "~13.0.1",
        "expo-crypto": "~10.1.1",
        "expo-dev-client": "~0.8.5",
        "expo-device": "~4.1.0",
        "expo-document-picker": "~10.1.3",
        "expo-image-loader": "~3.1.0",
        "expo-image-picker": "~12.0.2",
        "expo-linear-gradient": "~11.0.3",
        "expo-local-authentication": "~12.1.0",
        "expo-random": "~12.1.1",
        "expo-secure-store": "~11.1.0",
        "expo-splash-screen": "~0.14.1",
        "expo-status-bar": "~1.2.0",
        "expo-updates": "~0.11.7",
        "make-plural": "^7.1.0",
        "react": "17.0.1",
        "react-dom": "17.0.1",
        "react-native": "0.64.3",
        "react-native-animated-progress": "^1.0.2",
        "react-native-country-picker-modal": "^2.0.0",
        "react-native-dotenv": "^3.3.1",
        "react-native-gesture-handler": "~2.1.0",
        "react-native-keyboard-aware-scroll-view": "^0.9.5",
        "react-native-phone-number-input": "^2.1.0",
        "react-native-plaid-link-sdk": "^7.4.0",
        "react-native-safe-area-context": "3.3.2",
        "react-native-screens": "~3.10.1",
        "react-native-shimmer-placeholder": "^2.0.8",
        "react-native-svg": "12.1.1",
        "react-native-uuid": "^2.0.1",
        "react-native-web": "0.17.1",
        "react-native-webview": "11.15.0",
        "react-redux": "^7.2.6",
        "semver-compare": "^1.0.0",
        "sentry-expo": "^4.0.0",
        "styled-components": "5.2.0",
        "styled-system": "^5.1.5",
        "validate.js": "^0.13.1"
    },
    "devDependencies": {
        "@babel/core": "^7.12.9",
        "@graphql-codegen/cli": "2.6.2",
        "@graphql-codegen/typescript": "2.4.8",
        "@graphql-codegen/typescript-operations": "2.3.5",
        "@graphql-codegen/typescript-react-apollo": "3.2.11",
        "@lingui/cli": "^3.13.2",
        "@lingui/macro": "^3.13.2",
        "@react-native-community/eslint-config": "^3.0.1",
        "@types/jest": "^27.4.0",
        "@types/react": "~17.0.21",
        "@types/react-native": "~0.64.12",
        "@types/react-native-animated-progress": "^1.0.0",
        "@types/react-native-dotenv": "^0.2.0",
        "@types/react-redux": "^7.1.23",
        "@types/semver-compare": "^1.0.1",
        "@types/styled-components": "^5.1.24",
        "@types/styled-components-react-native": "5.1.0",
        "@types/styled-system": "^5.1.15",
        "@typescript-eslint/eslint-plugin": "^5.10.2",
        "@typescript-eslint/parser": "^5.10.2",
        "eslint": "^8.8.0",
        "eslint-config-airbnb": "^19.0.4",
        "eslint-config-prettier": "^8.3.0",
        "eslint-import-resolver-typescript": "^2.5.0",
        "eslint-plugin-flowtype": "^8.0.3",
        "eslint-plugin-import": "^2.25.4",
        "eslint-plugin-jest": "^26.1.0",
        "eslint-plugin-jsx-a11y": "^6.5.1",
        "eslint-plugin-prettier": "^4.0.0",
        "eslint-plugin-react": "^7.28.0",
        "eslint-plugin-react-hooks": "^4.3.0",
        "graphql": "^16.3.0",
        "install-peers": "^1.0.3",
        "jest": "^27.5.0",
        "prettier": "^2.5.1",
        "react-native-config": "^1.4.5",
        "react-native-svg-transformer": "^1.0.0",
        "remote-redux-devtools": "^0.5.16",
        "ts-jest": "^27.1.3",
        "typescript": "~4.3.5"
    },
    "jest": {
        "preset": "react-native",
        "moduleFileExtensions": [
            "ts",
            "tsx",
            "js",
            "jsx",
            "json",
            "node"
        ]
    },
    "resolutions": {
        "react-devtools-core": "4.14.0",
        "@types/react": "17.0.21",
        "@types/react-dom": "17.0.01"
    }
}

Here's my folder structure:

folder structure of the application

Here's MyAppPackage.kt (android\app\src\main\java\com\pana\MyAppPackage.kt)

package com.pana // replace your-app-name with your app’s name

import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager

class MyAppPackage : ReactPackage {

    override fun createViewManagers(
        reactContext: ReactApplicationContext
    ): MutableList<ViewManager<View, ReactShadowNode<*>>> = mutableListOf()

    override fun createNativeModules(
        reactContext: ReactApplicationContext
    ): MutableList<NativeModule> = listOf(CalendarModule(reactContext)).toMutableList()


}

Here are some of the SO resources that I've resarched:

Here are some othe resources that I've looked into:

Here are some of the errors and fixes that I've tried:

1 - Minimal Incrementing the project to barebones Kotlin

I've tried minimally incrementing my current project (Note that I had to set the compileSdkVersion and targetSdkVersion to 31 for an Intercom package, and that is building successfully). I've followed this video,the official React Native Docs, and the Add Kotlin to an existing app with Android Studio (Manual Approach).

a. (android/build.gradle) Added (Inside buildscript.ext) kotlin_version = '1.4.10' b. (android/build.gradle) Added (Inside dependencies) classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" c. (android/app/build.gradle) Added (at the top of the file) apply plugin: "kotlin-android"

Tried to compile:

[stderr] Note: Recompile with -Xlint:deprecation for details.
> Task :app:compileDebugKotlin FAILED w: Runtime JAR files in the classpath should have the same version. These files were found in the classpath:
    /home/expo/.gradle/caches/transforms-3/f47aaec93b5ce8275ab670559bc858c7/transformed/jetified-kotlin-stdlib-jdk8-1.5.31.jar (version 1.5)
    /home/expo/.gradle/caches/transforms-3/e30ac7ea6364b484c3bc3c923afeabd2/transformed/jetified-kotlin-stdlib-jdk7-1.5.31.jar (version 1.5)
    /home/expo/.gradle/caches/transforms-3/d9723caca13068e43e601371da49b5b2/transformed/jetified-kotlin-stdlib-1.6.10.jar (version 1.6)
    /home/expo/.gradle/caches/transforms-3/c5966235c8aa66a583bf2afcd9edd1b7/transformed/jetified-kotlin-stdlib-common-1.6.10.jar (version 1.6) w: Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath [stderr] e: /home/expo/.gradle/caches/transforms-3/c5966235c8aa66a583bf2afcd9edd1b7/transformed/jetified-kotlin-stdlib-common-1.6.10.jar!/META-INF/kotlin-stdlib-common.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.6.0, expected version is 1.4.0.

2 - Pushing Kotlin to Version 1.6.10

Seeing this, led me to some research and suggested to push the Kotlin version to 1.6.10:

Task :expo-dev-launcher:compileDebugKotlin
[stderr] Compilation with Kotlin compile daemon was not successful
[stderr] java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
[stderr]    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
[stderr]    java.io.InvalidClassException: org.jetbrains.kotlin.incremental.IncrementalModuleInfo; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 0
[stderr]    at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:391)
[stderr]    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
[stderr]    at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
[stderr]    at java.base/java.security.AccessController.doPrivileged(Native Method)
[stderr]    at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
[stderr]    at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
[stderr]    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
[stderr]    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
[stderr]    at java.base/java.security.AccessController.doPrivileged(Native Method)
[stderr]    at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
[stderr]    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[stderr]    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[stderr]    at java.base/java.lang.Thread.run(Thread.java:829)
[stderr]    at java.rmi/sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:303)
[stderr]    at java.rmi/sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:279)
[stderr]    at java.rmi/sun.rmi.server.UnicastRef.invoke(UnicastRef.java:164)

This lead me to update to run expo upgrade and expo doctor to see if any of the updates would work. This opened Pandora's box. Upgrading to expo SDK 45 came with its own issues (apparently I have some conflicting packages that throw the following errors):

[stderr] Note: /home/expo/workingdir/build/app/node_modules/@sentry/react-native/android/src/main/java/io/sentry/react/RNSentryModule.java uses or overrides a deprecated API.
[stderr] Note: Recompile with -Xlint:deprecation for details.
> Task :app:compileDebugJavaWithJavac FAILED
[stderr] /home/expo/workingdir/build/app/android/app/src/main/java/app/pana/MainApplication.java:6: error: package android.app does not exist
[stderr] import android.app.Application;
[stderr]                   ^
[stderr] /home/expo/workingdir/build/app/android/app/src/main/java/app/pana/MainApplication.java:7: error: package android.content does not exist
[stderr] import android.content.Context;
[stderr]                       ^
[stderr] /home/expo/workingdir/build/app/android/app/src/main/java/app/pana/MainApplication.java:8: error: package android.content.res does not exist
[stderr] import android.content.res.Configuration;
[stderr]                           ^
[stderr] /home/expo/workingdir/build/app/android/app/src/main/java/app/pana/MainApplication.java:10: error: package android.webkit does not exist
[stderr] import android.webkit.WebView;

There were other builds that failed with the expo-dev-client. I'm also aware of a bug in the SDK 45 that you will have problems with Hermes enabled. We're using JSC.

3 - A bunch of other things

Just to prevent this question from becoming longer, here are other things that I've tried:

a. Changing the distributionUrl in the gradle-wrapper.properties to a more recent gradle version.

b. Updating, and mathcing the org.jetbrains.kotlin:kotlin-gradle-plugin (in android/build.gradle), org.jetbrains.kotlin:kotlin-stdlib-jdk7 (changed it to jdk8 and nothing), org.jetbrains.kotlinx:kotlinx-coroutines-core, org.jetbrains.kotlinx:kotlinx-coroutines-android, androidx.core:core-ktx with the corresponding kotlin versions.

c. Added these implementations inside a debugImplementation statement.

d. Researched React Native versions corresponding with Kotlin (Don't know if Version 0.64 which is Expo's SDK 44 supports Kotlin 1.6.10).

e. Checked for syntax errors using Android Studio.

f. Ran gradlew clean.

g. And other things...

Does anyone know anything? There doesn't seem to be anything reported in the Expo GitHub.

Jose A
  • 10,053
  • 11
  • 75
  • 108
  • As this question remains unanswered, I'm going to be trying to implement it in Java instead. – Jose A May 11 '22 at 16:37

1 Answers1

0

The following packagingOptions seems to help mitigate some of the issues

// android/app/build.gradle
android {
    // This fixes a bug when 
    // https://github.com/facebook/react-native/issues/33120
    packagingOptions {
        jniLibs.useLegacyPackaging = true
    }
Jose A
  • 10,053
  • 11
  • 75
  • 108