or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

bridge-runtime.mdbuiltin-plugins.mdconfig-utilities.mddata-exchange.mdindex.mdplugin-calls.mdplugin-development.md
tile.json

plugin-development.mddocs/

Plugin Development Framework

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.

Capabilities

@CapacitorPlugin Annotation

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();
    }
}

Plugin Base Class

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
    }
}

@PluginMethod Annotation

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()
}

Permission Handling

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);
    }
}

Activity Integration

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");
        }
    }
}