android icon indicating copy to clipboard operation
android copied to clipboard

Many issues using Kotlin library from plugin

Open RobertGardner opened this issue 4 years ago • 8 comments

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.)

RobertGardner avatar Apr 21 '20 23:04 RobertGardner

+1

luke-hawk avatar May 19 '20 16:05 luke-hawk

+1

SmailHammour avatar Jul 01 '20 07:07 SmailHammour

Does anyone know whether this has been fixed in a later version of NS? (we're still on 6)

jerbob92 avatar Nov 25 '21 16:11 jerbob92

I'm facing similar issue, any update?

AdrianoOP avatar Dec 29 '21 13:12 AdrianoOP

@AdrianoOP can you try the @alpha version of the runtime an lmk , thanks.

triniwiz avatar Dec 29 '21 17:12 triniwiz

@triniwiz unfortunately it didn't work, same error. In my case the error is more related to this log message:

JS: ERROR Error: java.lang.Exception: Failed resolving constructor for class 'com.stripe.android.model.CardParams' with 4 parameters. Check the number and type of arguments. JS: Primitive types need to be manually wrapped in their respective Object wrappers. JS: If you are creating an instance of an inner class, make sure to always provide reference to the outer this as the first argument.

AdrianoOP avatar Dec 29 '21 20:12 AdrianoOP

Interesting , please share which version of the lib are you trying this with because this works fine for me here

triniwiz avatar Dec 29 '21 20:12 triniwiz

Yes... This is exactly where it fails... Do you have the snipet of code where you are creating CardParams?

Mine is:

const cardSession = this.sessionInfoService.getUserSession().creditCard; const card: CardParams = new CardParams( cardSession.cardNumber as string, cardSession.expirationMonth as number, cardSession.expirationYear as number, cardSession.cvc as string );

relevant packages installed:

"@nativescript/android": "8.1.1", "@nativescript/ios": "8.1.0", "@nativescript/types": "~8.1.1", "@nativescript/webpack": "~5.0.0", "@typescript-eslint/parser": "5.3.0", "typescript": "~4.3.5"

"@nativescript/angular": "^12.2.0", "@nativescript/core": "~8.1.1", "@nativescript/firebase": "^11.1.3", "@triniwiz/nativescript-stripe": "^7.0.1",

AdrianoOP avatar Dec 29 '21 21:12 AdrianoOP