Capacitor: android:TypeError: Cannot read property 'echo' of undefined

Created on 14 Jan 2019  路  12Comments  路  Source: ionic-team/capacitor

I am start developing a Native Capacitor Plugins for android platform unfortunately when i build & run my Plugin it's work perfect in web implementation but in android i got a this Error .

https://github.com/rahadur/capacitor-admob

Logcat Error

E/Capacitor/Plugin/Console: ERROR TypeError: Cannot read property 'echo' of undefined
V/Capacitor: callback: -1, pluginId: Console, methodName: log, methodData: {"level":"error","message":"ERROR CONTEXT [object Object]"}
E/Capacitor/Plugin/Console: ERROR CONTEXT [object Object]

definations.ts

declare global {
  interface PluginRegistry {
    DemoPlugin?: PluginType;
  }
}

export interface PluginType{
  echo(options: { value: string }): Promise<{value: string}>;

  other({options: any}): Promise<{response: boolean}>;

}

DemoPlugin.java

@NativePlugin()
public class DemoPlugin extends Plugin {

    @PluginMethod()
    public void echo(PluginCall call) {
        String value = call.getString("value");

        JSObject ret = new JSObject();
        ret.put("value", value);
        call.success(ret);
    }

    @PluginMethod()
    public void other(PluginCall call) {
        //String appId = call.getString("appId");

        call.success(new JSObject().put("response", true));
    }
}

MainActivity.java

public class MainActivity extends BridgeActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>(){{
            add(DemoPlugin.class);
        }});
    }
}

As you can see i already implement Java side method and also Export to Capacitor in MainActivity

Ionic

Ionic:                                                                                            

   ionic (Ionic CLI)             : 4.6.0 (C:\Users\Rahadur\AppData\Roaming\npm\node_modules\ionic)
   Ionic Framework               : @ionic/angular 4.0.0-rc.1                                      
   @angular-devkit/build-angular : 0.11.4                                                         
   @angular-devkit/schematics    : 7.1.4                                                          
   @angular/cli                  : 7.1.4                                                          
   @ionic/angular-toolkit        : 1.2.2                                                          

System:                                                                                           

   NodeJS : v10.5.0 (C:\Program Files\nodejs\node.exe)                                            
   npm    : 6.5.0                                                                                 
   OS     : Windows 10                                                                            

Most helpful comment

OK it was total user error - in the plugin.ts, I'd called it "LocationControllerPlugin", and in the Java code, the class was named "LoggerController".

It might be nice if it stated in the documentation that the name must be identical between the Java and the definition in the plugin.ts - I had, perhaps, assumed wrongly that the bit of the name that mattered was the name of the plugin in the plugin registry, whereas in reality, it is the name of the interface in the typescript which needs to match.

Thanks both for your help!

All 12 comments

I'm seeing exactly the same error - did you manage to resolve this @rahadur ?

Open your Ionic Capacitor project in Android Studio inside app folder open MainActivity.java file and register your Plugin. Check below code.

NOTE: You have to register your Plugin inside a Capacitor Project not in Capacitor Plugins.

```java
// Other imports...
import com.example.myapp.EchoPlugin;

public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Initializes the Bridge
this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
  // Additional plugins you've installed go here
  // Ex: add(TotallyAwesomePlugin.class);
  add(EchoPlugin.class);
}});

}
}

Closing as the problem was the missing add.
It's documented here https://capacitor.ionicframework.com/docs/plugins/android

I already have that line @rahadur - was there anything else you had to do to register it in Android land? I've just done a full rebuild of the android app to test this and still seeing the following on the logcat output:

V/Capacitor: callback: -1, pluginId: Console, methodName: log, methodData: {"level":"error","message":"ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'customCall' of undefined\nTypeError: Cannot read property 'customCall' of undefined
E/Capacitor/Plugin/Console: ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'customCall' of undefined
    TypeError: Cannot read property 'customCall' of undefined

From the web version, this works as intended, so the typescript side is solid.

I've followed the documentation to the letter but I'm still getting the same error, so I think there's something missing from the documentation or I've made some sort of misunderstanding in transcribing it.

Can you post the ts or js code to use your code?

@mrsheepuk please check your definition.ts file there must have a property called customCall() and your must implement this method in Java code.

Generally this error said that customCall() is not implemented.

One more thing you must import your plugin package in your project

import { Plugins } from '@capacitor/core'
import {} from 'yourplugins'  // although there is nothing to import must import your plugin package

...
ngOnInit(){ 
    // call your plugin method 
    Plugins.YourPlugin.customCall().then(result => {
      console.log(result);
});
}

If it's possible please share a demo project that can help us to understand your problem.

Here's the key bits of the code, so far it's a very simple example as I just wanted to prove the end-to-end flow before going into the effort of implementing anything more complex.

In the Java class LoggerController.java I have this:

package net.sheeptrack.app;

import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;

public class LoggerController extends Plugin {
    @PluginMethod()
    public void customCall(PluginCall call) {
        String message = call.getString("message");
        JSObject ret = new JSObject();
        ret.put("message", "chicken");
        call.success(ret);
        notifyListeners("chicken", new JSObject());
    }
}

... and in my MainActivity.java I have this:

package net.sheeptrack.app;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import java.util.ArrayList;

public class MainActivity extends BridgeActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Initializes the Bridge
    this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
      add(LoggerController.class);
    }});
  }
}

In a file named 'plugin.ts' in the root "app" folder of my ionic project, I have this:

declare global {
  interface PluginRegistry {
    LocationController?: LocationControllerPlugin;
  }
}

export interface LocationControllerPlugin {
  customCall(options: { message: string }): Promise<{message: string}>;
}

And in the typescript service I'm calling it from, I have this:

import { Injectable } from '@angular/core';
import '../plugins';
import { Plugins } from '@capacitor/core';
const { LocationController } = Plugins;


@Injectable({
  providedIn: 'root'
})
export class MapService {
  constructor() { }

  async horse() {
    let resp = await LocationController.customCall({ message: "Chicken" });
    console.log(resp.message);
    return resp.message;
  }
}

Hopefully I'm missing something obvious here! Thanks for looking.

The plugin class is missing the @NativePlugin() annotation

That's an embarrassing omission, thanks @jcesarmobile - I've added it but, unfortunately, still seeing the same result - E/Capacitor/Plugin/Console: ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'customCall' of undefined.

I don't want to waste any more of your time - thanks so much for the help so far, I'll open a question on Stack Overflow to find help with this - my only intention in replying to this issue was to find out if there was an obvious problem that had been cleared up, but it looks like it's something else.

OK it was total user error - in the plugin.ts, I'd called it "LocationControllerPlugin", and in the Java code, the class was named "LoggerController".

It might be nice if it stated in the documentation that the name must be identical between the Java and the definition in the plugin.ts - I had, perhaps, assumed wrongly that the bit of the name that mattered was the name of the plugin in the plugin registry, whereas in reality, it is the name of the interface in the typescript which needs to match.

Thanks both for your help!

OK it was total user error - in the plugin.ts, I'd called it "LocationControllerPlugin", and in the Java code, the class was named "LoggerController".

It might be nice if it stated in the documentation that the name must be identical between the Java and the definition in the plugin.ts - I had, perhaps, assumed wrongly that the bit of the name that mattered was the name of the plugin in the plugin registry, whereas in reality, it is the name of the interface in the typescript which needs to match.

Thanks both for your help!

Thanks for sharing your solution, because I had the same issue and without you it would've taken me more time to get it straight.

Thanks for sharing your solution, because I had the same issue and without you it would've taken me more time to get it straight.

You're welcome @martin-braun - this was a while ago now but I still remember how long I spent trying different things until I realised this, so I'm glad that someone else has benefitted from it!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexcroox picture alexcroox  路  3Comments

nicobytes picture nicobytes  路  3Comments

peterpeterparker picture peterpeterparker  路  3Comments

danielsogl picture danielsogl  路  3Comments

MatanYadaev picture MatanYadaev  路  3Comments