Base classes, annotations, and utilities for developing native Android plugins that integrate with Capacitor's bridge system, handle permissions, and provide native functionality to web applications.
Base annotation that marks a class as a Capacitor plugin and provides metadata for plugin registration and configuration.
/**
* Base annotation for all Capacitor plugins
* Provides metadata for plugin registration and configuration
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface CapacitorPlugin {
/**
* Custom name for the plugin, otherwise uses the simple class name
* @returns Plugin name string
*/
String name() default "";
/**
* Request codes this plugin uses and responds to, for tying Android events back to the plugin
* NOTE: Legacy option for third party libraries not using AndroidX Activity Results API
* @returns Array of request code integers
*/
int[] requestCodes() default {};
/**
* Permissions this plugin needs, for easy permission requests
* @returns Array of Permission annotations
*/
Permission[] permissions() default {};
}Usage Examples:
@CapacitorPlugin(
name = "MyCustomPlugin",
permissions = {
@Permission(strings = {Manifest.permission.CAMERA}),
@Permission(strings = {Manifest.permission.WRITE_EXTERNAL_STORAGE})
}
)
public class MyCustomPlugin extends Plugin {
// Plugin implementation
}
@CapacitorPlugin(name = "SimplePlugin")
public class SimplePlugin extends Plugin {
@PluginMethod
public void doSomething(PluginCall call) {
call.resolve();
}
}Base class for all Capacitor plugins providing lifecycle management, permission handling, and bridge integration.
/**
* Base class for all Capacitor plugins
* Provides lifecycle management, permission handling, and bridge integration
*/
public class Plugin {
/** Reference to the bridge instance */
protected Bridge bridge;
/** Reference to the hosting activity */
protected AppCompatActivity activity;
/** Android context reference */
protected Context context;
/** Plugin configuration from capacitor.config */
protected JSObject config;
/**
* Called when the plugin is first loaded and registered with the bridge
* Override to perform initialization tasks
*/
public void load();
/**
* Get the bridge instance
* @returns Bridge instance managing this plugin
*/
public Bridge getBridge();
/**
* Get the hosting activity
* @returns AppCompatActivity hosting the plugin
*/
public AppCompatActivity getActivity();
/**
* Get Android context
* @returns Android Context instance
*/
public Context getContext();
/**
* Get plugin configuration from capacitor.config.json
* @returns JSObject with plugin configuration
*/
public JSObject getConfig();
/**
* Handle activity results from Android intents
* @param requestCode - Request code from startActivityForResult
* @param resultCode - Result code from the activity
* @param data - Intent data returned from the activity
*/
public void handleOnActivityResult(int requestCode, int resultCode, Intent data);
/**
* Handle permission request results
* @param requestCode - Request code from permission request
* @param permissions - Array of requested permissions
* @param grantResults - Array of grant results
*/
public void handleRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults);
/**
* Called when the hosting activity is paused
*/
protected void handleOnPause();
/**
* Called when the hosting activity is resumed
*/
protected void handleOnResume();
/**
* Called when the hosting activity is started
*/
protected void handleOnStart();
/**
* Called when the hosting activity is stopped
*/
protected void handleOnStop();
/**
* Called when the hosting activity is destroyed
*/
protected void handleOnDestroy();
}Usage Examples:
@CapacitorPlugin(name = "DeviceInfo")
public class DeviceInfoPlugin extends Plugin {
@Override
public void load() {
// Initialize plugin resources
Log.d("DeviceInfo", "Plugin loaded");
}
@PluginMethod
public void getDeviceInfo(PluginCall call) {
JSObject result = new JSObject();
result.put("model", Build.MODEL);
result.put("manufacturer", Build.MANUFACTURER);
result.put("version", Build.VERSION.RELEASE);
call.resolve(result);
}
@Override
protected void handleOnResume() {
super.handleOnResume();
// Handle app resume
}
}Annotation that marks methods as callable from the JavaScript layer, with configuration for return types and execution behavior.
/**
* Annotation for methods callable from JavaScript
* Configures return type and execution behavior
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface PluginMethod {
/**
* Return type for the method call
* @returns ReturnType enum value
*/
ReturnType returnType() default ReturnType.PROMISE;
}
/**
* Enum defining method return types
*/
public enum ReturnType {
/** Method returns a Promise to JavaScript */
PROMISE,
/** Method uses callback pattern */
CALLBACK
}Usage Examples:
@PluginMethod
public void getData(PluginCall call) {
// Returns a promise by default
JSObject result = new JSObject();
result.put("data", "some value");
call.resolve(result);
}
@PluginMethod(returnType = ReturnType.CALLBACK)
public void startListening(PluginCall call) {
// Uses callback pattern for ongoing events
call.setKeepAlive(true);
// Send periodic updates via call.resolve()
}Classes and annotations for handling Android permissions in plugins.
/**
* Annotation defining required permissions for a plugin
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
/**
* Array of Android permission strings
* @returns String array of permission names
*/
String[] strings() default {};
/**
* Alias name for this permission group
* @returns Permission alias string
*/
String alias() default "";
}
/**
* Enum representing Android permission states
*/
public enum PermissionState {
/** Permission has been granted */
GRANTED,
/** Permission has been denied */
DENIED,
/** Permission requires user prompt */
PROMPT,
/** Permission requires prompt with rationale explanation */
PROMPT_WITH_RATIONALE
}
/**
* Annotation for methods that handle permission callbacks
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface PermissionCallback {
}Usage Examples:
@CapacitorPlugin(
name = "Camera",
permissions = {
@Permission(strings = {Manifest.permission.CAMERA}, alias = "camera"),
@Permission(strings = {Manifest.permission.WRITE_EXTERNAL_STORAGE}, alias = "storage")
}
)
public class CameraPlugin extends Plugin {
@PluginMethod
public void takePicture(PluginCall call) {
if (getPermissionState("camera") != PermissionState.GRANTED) {
requestPermissionForAlias("camera", call, "cameraPermissionCallback");
return;
}
// Take picture logic
doTakePicture(call);
}
@PermissionCallback
private void cameraPermissionCallback(PluginCall call) {
if (getPermissionState("camera") == PermissionState.GRANTED) {
doTakePicture(call);
} else {
call.reject("Camera permission required");
}
}
private void doTakePicture(PluginCall call) {
// Actual camera logic
JSObject result = new JSObject();
result.put("image", "base64ImageData");
call.resolve(result);
}
}Methods and utilities for integrating with Android activities and handling activity results.
/**
* Annotation for methods that handle activity callbacks
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityCallback {
}
/**
* Utility methods for activity integration (available in Plugin base class)
*/
public abstract class Plugin {
/**
* Start an activity for result with plugin call tracking
* @param call - Plugin call to associate with result
* @param intent - Intent to start activity with
* @param callbackName - Name of callback method to invoke with result
*/
protected void startActivityForResult(PluginCall call, Intent intent, String callbackName);
/**
* Request permissions with alias and callback
* @param alias - Permission alias from @Permission annotation
* @param call - Plugin call to associate with permission result
* @param callbackName - Name of callback method for permission result
*/
protected void requestPermissionForAlias(String alias, PluginCall call, String callbackName);
/**
* Request specific permissions
* @param permissions - Array of permission strings to request
* @param call - Plugin call to associate with result
*/
protected void requestPermissions(String[] permissions, PluginCall call);
/**
* Get current state of a permission alias
* @param alias - Permission alias to check
* @returns PermissionState enum value
*/
protected PermissionState getPermissionState(String alias);
/**
* Check if all required permissions are granted
* @returns boolean indicating if all permissions granted
*/
protected boolean hasRequiredPermissions();
}Usage Examples:
@CapacitorPlugin(name = "FilePicker")
public class FilePickerPlugin extends Plugin {
@PluginMethod
public void pickFile(PluginCall call) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(call, intent, "filePickerResult");
}
@ActivityCallback
private void filePickerResult(PluginCall call, ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
if (data != null) {
Uri uri = data.getData();
JSObject jsResult = new JSObject();
jsResult.put("uri", uri.toString());
call.resolve(jsResult);
} else {
call.reject("No file selected");
}
} else {
call.reject("File picker cancelled");
}
}
}