Skip to content

Many issues using Kotlin library from plugin #1604

@RobertGardner

Description

@RobertGardner

Environment
Provide version numbers for the following components (information can be retrieved by running tns info in your project folder or by inspecting the package.json of the project):

  • CLI: 6.5.0
  • Cross-platform modules: 6.5.1
  • Android Runtime: 6.5.0
  • iOS Runtime (if applicable): N/A
  • Plugin(s): nativescript-stripe

Describe the bug
I am a primary contributor for the nativescript-stripe plugin and am attempting to upgrade it to the latest Stripe Android SDK. When Stripe updated their Android SDK from v12 to v13 they switched from Java to Kotlin. Code in my plugin that used to run without problem on the Java version now fails on the Kotlin version. This report provides the information I've been able to learn on the problems. I have checked my code that exhibits these problems into the nativescript-stripe repository in a branch named update-android-13-bugs. The files referenced below are in that branch. (I would be ecstatic to learn there's a configuration or versioning problem in my plugin that is responsible for these issues!)

  • When Kotlin fields are annotated with @JvmField or @get: they are not available in NS at runtime. Accessing those fields reports the error: Missing getter method for property. I have found that the fields are exposed with the name componentN(), where N is the integer sequence the fields are declared in the Kotlin file. See, for example, src/stripe.android.ts line 430 where I have modified the code to retrieve those fields using the component methods.

  • When a method is annotated with @JvmStatic, the first time it is called it reports an error: You are trying to set "Companion" which is a final field! Final fields can only be read. The app does not crash (in my case) and if I try executing it again, it succeeds. An example of this is the call to SourceParams.createCardParams() at src/stripe.android.ts line 70.

  • When I implement a Kotlin interface (using the "anonymous Java class" technique described in the NS docs), I get the following error when the SDK attempts to use it:

com.tns.NativeScriptException: Cannot find runtime for instance=com.tns.gen.com.stripe.android.PaymentSessionConfig_ShippingInformationValidator@2f3779c
	at com.tns.Runtime.callJSMethod(Runtime.java:1157)

You can see the code where I create the implementation at src/standard/standard.android.ts line 154.

dts-generator problems:
I use the [dts-generator](https://docs.nativescript.org/core-concepts/android-runtime/metadata/generating-typescript-declarations) to generate typings from the Stripe Android SDK. I have run into the following problems with the typings generated from Kotlin source files. I can generally fix them, but it's quite a pain.

  • Kotlin elements marked internal are generated in the .d.ts file. They shouldn't be. They often cause typescript errors since they frequently use internal-only types.

  • If a class is marked @Parcelize the generator creates a static field named CREATOR. It is of type globalAndroid.os.Parcelable.Creator and does not include its generic type even though Parcelable.Creator is a typed class. It can be fixed by copying the generic type from the static class field.

  • Kotlin classes with companions are generated as follows:

class Foo {
  static Companion: Foo.Companion;
  export module Foo {
    export class Companion {
      public static class: java.lang.Class<Foo.Companion>;
    }
  }
}

This, of course, results in a Duplicate identifier 'Companion' typescript error. I have found I can resolve this by changing the Companion class name from Companion to companion. (You can see an example of this in java!Stripe.d.ts line 2001.) This is an ugly solution but since the class name does not show up in the generated JS code, it works. I can then call the method using Foo.Companion.method(). An example of where I successfully call such a method is the call to fromCode at src/standard/standard.android.ts line 233. (Note that this method, since it was just introduced in the v13 SDK, is a pure Kotlin method, so it is not annotated with @JvmStatic. The createCardParams method mentioned above, however, exists in earlier versions, so it was annotated with @JvmStatic. The call to fromCode has no problem, while the call to createCardParams exhibits the behavior mentioned above.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions