2

I'm trying to create a Flutter Plugin that uses a native Android sdk

I'm able to compile the .aar libraries of the sdk and use them in the project but the sdk requires me to get the context of the main activity

here is the error im getting

E/MethodChannel#mychart_plugin(16277): Failed to handle method call
E/MethodChannel#mychart_plugin(16277): kotlin.KotlinNullPointerException
E/MethodChannel#mychart_plugin(16277):  at org.ccf.flutter.plugin.mychart_plugin.MychartPlugin.getContext(MychartPlugin.kt:79)
E/MethodChannel#mychart_plugin(16277):  at epic.mychart.android.library.api.authentication.WPAPIAuthentication$1.getContext(WPAPIAuthentication.java:564)
E/MethodChannel#mychart_plugin(16277):  at epic.mychart.android.library.prelogin.AuthenticationService.libraryLogin(AuthenticationService.java:461)
E/MethodChannel#mychart_plugin(16277):  at epic.mychart.android.library.api.authentication.WPAPIAuthentication.login(WPAPIAuthentication.java:411)
E/MethodChannel#mychart_plugin(16277):  at org.ccf.flutter.plugin.mychart_plugin.MychartPlugin.onMethodCall(MychartPlugin.kt:42)
E/MethodChannel#mychart_plugin(16277):  at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:201)
E/MethodChannel#mychart_plugin(16277):  at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:88)
E/MethodChannel#mychart_plugin(16277):  at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:219)
E/MethodChannel#mychart_plugin(16277):  at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#mychart_plugin(16277):  at android.os.MessageQueue.next(MessageQueue.java:325)
E/MethodChannel#mychart_plugin(16277):  at android.os.Looper.loop(Looper.java:142)
E/MethodChannel#mychart_plugin(16277):  at android.app.ActivityThread.main(ActivityThread.java:6541)
E/MethodChannel#mychart_plugin(16277):  at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#mychart_plugin(16277):  at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
E/MethodChannel#mychart_plugin(16277):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

here is my code for getting the context

class MychartPlugin: MethodCallHandler, WPAPIAuthentication.IWPOnLoginListener {
private var registrar: PluginRegistry.Registrar? = null
private val LOGIN_REQUEST_CODE = 9876

fun MychartPlugin(registrar: PluginRegistry.Registrar) {
  this.registrar = registrar
}
companion object {
  @JvmStatic
  fun registerWith(registrar: Registrar) {
    val channel = MethodChannel(registrar.messenger(), "mychart_plugin")
    channel.setMethodCallHandler(MychartPlugin())
  }
}

override fun onMethodCall(call: MethodCall, result: Result) {
  if (call.method == "getPlatformVersion") {
    result.success("Android ${android.os.Build.VERSION.RELEASE}")
  } else if (call.method == "MyChartSdkLogin") {
  WPAPIAuthentication.login(this, "TURKJ123", "TurkJ123", LOGIN_REQUEST_CODE)
    result.success("called MyChartSdkLogin")
  }  else {
    result.notImplemented()
  }
}


override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
  // super.onActivityResult(requestCode, resultCode, data)
  if (requestCode == LOGIN_REQUEST_CODE) {
    if (resultCode == Activity.RESULT_OK) {
      // login successful
      Log.i("LoginFragment", "OK")

    } else {
      // login failed
      val result = WPAPIAuthentication.getLoginResult(data)
      Log.i("LoginFragment", result.toString())
      val errorMessage = result.getErrorMessage(getContext())
      if (!errorMessage.isEmpty()) {
        Toast.makeText(getContext(), errorMessage, Toast.LENGTH_LONG).show()
      }
    }
  }
}

override fun startActivityForResult(p0: Intent, p1: Int) {
  // super.startActivityForResult(p0, p1)
}

override fun getSupportFragmentManager(): FragmentManager {
  val act = registrar!!.activity() as FragmentActivity
  return act.getSupportFragmentManager()
}

override fun getContext(): Context {
  val cxt = registrar!!.context()
  return cxt
}

}

notice the override getContext() method that im overriding from the sdk, I think this context call to the registar is where my KotlinNullPointerException is coming from

Derek Hannah
  • 537
  • 7
  • 23

1 Answers1

1

In getContext you have registrar!!. And registrar is a nullable field which you initialize to null and can only set in a method which you never call. Note that fun MychartPlugin isn't a constructor, you'd call it as e.g.

val plugin = MychartPlugin()
plugin.MychartPlugin(registrar)

But it doesn't seem like there is any reason to make registrar nullable or mutable in the first place. You can change to

class MychartPlugin(private val registrar: Registrar): ...

and

fun registerWith(registrar: Registrar) {
  val channel = MethodChannel(registrar.messenger(), "mychart_plugin")
  channel.setMethodCallHandler(MychartPlugin(registrar))
}
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487