Kotlin null pointer exception when trying to get context from Registar in Flutter

1,541

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))
}
Share:
1,541
Derek Hannah
Author by

Derek Hannah

Updated on December 10, 2022

Comments

  • Derek Hannah
    Derek Hannah over 1 year

    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
    Derek Hannah about 5 years
    that was it thanks, I'm just getting back into Kotlin so im rusty haha