Custom Native Android Code
With Capacitor, you are encouraged to write Java or Kotlin code to implement the native features your app needs.
There may not be a Capacitor plugin for everything--and that's okay! It is possible to write WebView-accessible native code right in your app.
WebView-Accessible Native Code
The easiest way to communicate between JavaScript and native code is to build a custom Capacitor plugin that is local to your app.
EchoPlugin.java
First, create a EchoPlugin.java
file by opening Android Studio, expanding the app module and the java folder, right-clicking on your app's Java package, selecting New -> Java Class from the context menu, and creating the file.
Copy the following Java code into EchoPlugin.java
:
package com.example.myapp;
import com.getcapacitor.JSObject;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginCall;
import com.getcapacitor.PluginMethod;
import com.getcapacitor.annotation.CapacitorPlugin;
@CapacitorPlugin(name = "Echo")
public class EchoPlugin extends Plugin {
@PluginMethod()
public void echo(PluginCall call) {
String value = call.getString("value");
JSObject ret = new JSObject();
ret.put("value", value);
call.resolve(ret);
}
}
Register the Plugin
We must register custom plugins on both Android and web so that Capacitor can bridge between Java and JavaScript.
MainActivity.java
In your app's MainActivity.java
, use registerPlugin()
or registerPlugins()
to register your custom plugin(s).
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
+ registerPlugin(EchoPlugin.class);
super.onCreate(savedInstanceState);
}
}
JavaScript
In JS, we use registerPlugin()
from @capacitor/core
to create an object which is linked to our Java plugin.
import { registerPlugin } from '@capacitor/core';
const Echo = registerPlugin('Echo');
export default Echo;
The first parameter to
registerPlugin()
is the plugin name, which must match thename
attribute of our@CapacitorPlugin
annotation inEchoPlugin.java
.
TypeScript
We can define types on our linked object by defining an interface and using it in the call to registerPlugin()
.
import { registerPlugin } from '@capacitor/core';
+export interface EchoPlugin {
+ echo(options: { value: string }): Promise<{ value: string }>;
+}
-const Echo = registerPlugin('Echo');
+const Echo = registerPlugin<EchoPlugin>('Echo');
export default Echo;
The generic parameter of registerPlugin()
is what defines the structure of the linked object. You can use registerPlugin<any>('Echo')
to ignore types if you need to. No judgment. โค๏ธ
Use the Plugin
Use the exported Echo
object to call your plugin methods. The following snippet will call into Java on Android and print the result:
import Echo from '../path/to/echo-plugin';
const { value } = await Echo.echo({ value: 'Hello World!' });
console.log('Response from native:', value);