CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ionic-native

Native plugin wrappers for Cordova and Ionic with TypeScript, ES6+, Promise and Observable support

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

device-sensors.mddocs/

Device Sensors

Access to device sensors including accelerometer, gyroscope, compass, battery status, vibration, and other hardware sensors for motion detection and device state monitoring.

Capabilities

Accelerometer (Device Motion)

Monitor device acceleration and movement for gesture recognition, orientation detection, and motion-based interactions.

/**
 * Acceleration data interface
 */
interface Acceleration {
  /** Acceleration along the x-axis in m/s² */
  x: number;
  /** Acceleration along the y-axis in m/s² */
  y: number;
  /** Acceleration along the z-axis in m/s² */
  z: number;
  /** Timestamp when acceleration was captured */
  timestamp: number;
}

/**
 * Accelerometer configuration options
 */
interface AccelerometerOptions {
  /** Update frequency in milliseconds (default: 10000) */
  frequency?: number;
}

/**
 * DeviceMotion class for accelerometer access
 */
class DeviceMotion {
  /**
   * Get current acceleration values
   * @returns Promise resolving to current Acceleration data
   */
  static getCurrentAcceleration(): Promise<Acceleration>;

  /**
   * Watch acceleration changes continuously
   * @param options Accelerometer configuration options
   * @returns Observable emitting Acceleration updates
   */
  static watchAcceleration(options?: AccelerometerOptions): Observable<Acceleration>;
}

Usage Examples:

import { DeviceMotion, AccelerometerOptions } from 'ionic-native';

// Get current acceleration
async function getCurrentMotion() {
  try {
    const acceleration = await DeviceMotion.getCurrentAcceleration();
    
    console.log('Current acceleration:');
    console.log(`X: ${acceleration.x.toFixed(3)} m/s²`);
    console.log(`Y: ${acceleration.y.toFixed(3)} m/s²`);
    console.log(`Z: ${acceleration.z.toFixed(3)} m/s²`);
    
    return acceleration;
  } catch (error) {
    console.error('Error getting acceleration:', error);
    throw error;
  }
}

// Monitor device motion for shake detection
function setupShakeDetection() {
  const options: AccelerometerOptions = {
    frequency: 100 // Update every 100ms
  };
  
  let lastAcceleration = { x: 0, y: 0, z: 0, timestamp: 0 };
  const shakeThreshold = 15; // m/s²
  
  return DeviceMotion.watchAcceleration(options).subscribe(
    (acceleration) => {
      // Calculate acceleration difference
      const deltaX = Math.abs(acceleration.x - lastAcceleration.x);
      const deltaY = Math.abs(acceleration.y - lastAcceleration.y);
      const deltaZ = Math.abs(acceleration.z - lastAcceleration.z);
      
      const totalDelta = deltaX + deltaY + deltaZ;
      
      if (totalDelta > shakeThreshold) {
        console.log('Shake detected!');
        handleShakeEvent();
      }
      
      lastAcceleration = acceleration;
    },
    (error) => {
      console.error('Accelerometer error:', error);
    }
  );
}

// Motion-based gesture recognition
class MotionGestureDetector {
  private subscription: any;
  private motionBuffer: Acceleration[] = [];
  private readonly bufferSize = 20;
  
  startDetection() {
    const options: AccelerometerOptions = { frequency: 50 };
    
    this.subscription = DeviceMotion.watchAcceleration(options).subscribe(
      (acceleration) => {
        this.processMotionData(acceleration);
      }
    );
  }
  
  stopDetection() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
    this.motionBuffer = [];
  }
  
  private processMotionData(acceleration: Acceleration) {
    // Add to buffer
    this.motionBuffer.push(acceleration);
    
    // Keep buffer size manageable
    if (this.motionBuffer.length > this.bufferSize) {
      this.motionBuffer.shift();
    }
    
    // Analyze gestures
    this.detectGestures();
  }
  
  private detectGestures() {
    if (this.motionBuffer.length < 10) return;
    
    // Detect shake
    if (this.detectShake()) {
      this.onGestureDetected('shake');
    }
    
    // Detect tilt
    const tiltDirection = this.detectTilt();
    if (tiltDirection) {
      this.onGestureDetected('tilt', tiltDirection);
    }
    
    // Detect tap
    if (this.detectTap()) {
      this.onGestureDetected('tap');
    }
  }
  
  private detectShake(): boolean {
    const recent = this.motionBuffer.slice(-5);
    const avgAcceleration = recent.reduce((acc, curr) => {
      return Math.abs(curr.x) + Math.abs(curr.y) + Math.abs(curr.z);
    }, 0) / recent.length;
    
    return avgAcceleration > 20;
  }
  
  private detectTilt(): string | null {
    const latest = this.motionBuffer[this.motionBuffer.length - 1];
    
    if (Math.abs(latest.x) > 7) {
      return latest.x > 0 ? 'left' : 'right';
    }
    
    if (Math.abs(latest.y) > 7) {
      return latest.y > 0 ? 'forward' : 'backward';
    }
    
    return null;
  }
  
  private detectTap(): boolean {
    if (this.motionBuffer.length < 3) return false;
    
    const recent = this.motionBuffer.slice(-3);
    const zAccelerations = recent.map(a => Math.abs(a.z));
    
    // Look for spike in Z acceleration (tap)
    const maxZ = Math.max(...zAccelerations);
    return maxZ > 15;
  }
  
  private onGestureDetected(gesture: string, direction?: string) {
    console.log(`Gesture detected: ${gesture}`, direction ? `(${direction})` : '');
    
    // Trigger appropriate actions
    switch (gesture) {
      case 'shake':
        this.handleShake();
        break;
      case 'tilt':
        this.handleTilt(direction!);
        break;
      case 'tap':
        this.handleTap();
        break;
    }
  }
  
  private handleShake() {
    // Implement shake action (e.g., refresh, undo)
  }
  
  private handleTilt(direction: string) {
    // Implement tilt actions (e.g., navigation, scrolling)
  }
  
  private handleTap() {
    // Implement tap action (e.g., select, activate)
  }
}

Compass (Device Orientation)

Access device compass and magnetometer for heading information and navigation features.

/**
 * Compass heading data
 */
interface CompassHeading {
  /** Magnetic heading in degrees (0-359.99) */
  magneticHeading: number;
  /** True heading in degrees (0-359.99) */
  trueHeading: number;
  /** Heading accuracy in degrees */
  headingAccuracy: number;
  /** Timestamp when heading was captured */
  timestamp: number;
}

/**
 * Compass error information
 */
interface CompassError {
  /** Error code (0: COMPASS_INTERNAL_ERR, 20: COMPASS_NOT_SUPPORTED) */
  code: number;
}

/**
 * Compass configuration options
 */
interface CompassOptions {
  /** Update frequency in milliseconds (default: 100) */
  frequency?: number;
  /** Compass filter value (iOS only, default: 1) */
  filter?: number;
}

/**
 * DeviceOrientation class for compass access
 */
class DeviceOrientation {
  /**
   * Get current compass heading
   * @returns Promise resolving to current CompassHeading
   */
  static getCurrentHeading(): Promise<CompassHeading>;

  /**
   * Watch compass heading changes
   * @param options Compass configuration options
   * @returns Observable emitting CompassHeading updates
   */
  static watchHeading(options?: CompassOptions): Observable<CompassHeading>;
}

Usage Examples:

import { DeviceOrientation, CompassOptions } from 'ionic-native';

// Get current compass heading
async function getCurrentHeading() {
  try {
    const heading = await DeviceOrientation.getCurrentHeading();
    
    console.log('Current heading:');
    console.log(`Magnetic: ${heading.magneticHeading.toFixed(1)}°`);
    console.log(`True: ${heading.trueHeading.toFixed(1)}°`);
    console.log(`Accuracy: ±${heading.headingAccuracy.toFixed(1)}°`);
    
    return heading;
  } catch (error) {
    console.error('Error getting compass heading:', error);
    throw error;
  }
}

// Compass navigation system
class CompassNavigation {
  private subscription: any;
  private currentHeading = 0;
  private targetHeading = 0;
  
  startCompass(updateCallback?: (heading: number) => void) {
    const options: CompassOptions = {
      frequency: 100,
      filter: 1
    };
    
    this.subscription = DeviceOrientation.watchHeading(options).subscribe(
      (heading) => {
        this.currentHeading = heading.magneticHeading;
        
        if (updateCallback) {
          updateCallback(this.currentHeading);
        }
        
        this.updateCompassUI(heading);
      },
      (error) => {
        console.error('Compass error:', error);
        this.handleCompassError(error);
      }
    );
  }
  
  stopCompass() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
  
  setTarget(targetHeading: number) {
    this.targetHeading = targetHeading;
  }
  
  getDirectionToTarget(): { direction: string; degrees: number } {
    let difference = this.targetHeading - this.currentHeading;
    
    // Normalize to -180 to 180 range
    while (difference > 180) difference -= 360;
    while (difference < -180) difference += 360;
    
    const absDifference = Math.abs(difference);
    let direction = '';
    
    if (absDifference < 5) {
      direction = 'straight';
    } else if (difference > 0) {
      direction = 'right';
    } else {
      direction = 'left';
    }
    
    return { direction, degrees: absDifference };
  }
  
  private updateCompassUI(heading: CompassHeading) {
    // Update compass rose or navigation arrow
    const compassElement = document.getElementById('compass');
    if (compassElement) {
      compassElement.style.transform = `rotate(${-heading.magneticHeading}deg)`;
    }
    
    // Update direction indicator
    const directionInfo = this.getDirectionToTarget();
    const directionElement = document.getElementById('direction');
    if (directionElement) {
      directionElement.textContent = `${directionInfo.direction} (${directionInfo.degrees.toFixed(1)}°)`;
    }
  }
  
  private handleCompassError(error: any) {
    if (error.code === 20) {
      console.error('Compass not supported on this device');
    } else {
      console.error('Compass internal error');
    }
  }
}

// Compass-based features
function getCardinalDirection(heading: number): string {
  const directions = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 
                     'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'];
  const index = Math.round(heading / 22.5) % 16;
  return directions[index];
}

function calculateBearing(lat1: number, lon1: number, lat2: number, lon2: number): number {
  const dLon = (lon2 - lon1) * Math.PI / 180;
  const lat1Rad = lat1 * Math.PI / 180;
  const lat2Rad = lat2 * Math.PI / 180;
  
  const y = Math.sin(dLon) * Math.cos(lat2Rad);
  const x = Math.cos(lat1Rad) * Math.sin(lat2Rad) - 
           Math.sin(lat1Rad) * Math.cos(lat2Rad) * Math.cos(dLon);
  
  let bearing = Math.atan2(y, x) * 180 / Math.PI;
  return (bearing + 360) % 360;
}

Gyroscope

Access device gyroscope for rotation rate detection and advanced motion sensing.

/**
 * Gyroscope orientation data
 */
interface GyroscopeOrientation {
  /** Angular velocity around x-axis in deg/s */
  x: number;
  /** Angular velocity around y-axis in deg/s */
  y: number;
  /** Angular velocity around z-axis in deg/s */
  z: number;
  /** Timestamp when data was captured */
  timestamp: number;
}

/**
 * Gyroscope configuration options
 */
interface GyroscopeOptions {
  /** Update frequency in milliseconds (default: 100) */
  frequency?: number;
}

/**
 * Gyroscope class for rotation sensing
 */
class Gyroscope {
  /**
   * Get current gyroscope data
   * @param options Gyroscope configuration options
   * @returns Promise resolving to GyroscopeOrientation
   */
  static getCurrent(options?: GyroscopeOptions): Promise<GyroscopeOrientation>;

  /**
   * Watch gyroscope changes continuously
   * @param options Gyroscope configuration options
   * @returns Observable emitting GyroscopeOrientation updates
   */
  static watch(options?: GyroscopeOptions): Observable<GyroscopeOrientation>;
}

Usage Examples:

import { Gyroscope, GyroscopeOptions } from 'ionic-native';

// Rotation rate monitoring
class RotationDetector {
  private subscription: any;
  private rotationThreshold = 50; // deg/s
  
  startMonitoring() {
    const options: GyroscopeOptions = {
      frequency: 50
    };
    
    this.subscription = Gyroscope.watch(options).subscribe(
      (orientation) => {
        this.processRotationData(orientation);
      },
      (error) => {
        console.error('Gyroscope error:', error);
      }
    );
  }
  
  stopMonitoring() {
    if (this.subscription) {
      this.subscription.unsubscribe();
    }
  }
  
  private processRotationData(orientation: GyroscopeOrientation) {
    const totalRotation = Math.abs(orientation.x) + Math.abs(orientation.y) + Math.abs(orientation.z);
    
    if (totalRotation > this.rotationThreshold) {
      this.detectRotationGesture(orientation);
    }
  }
  
  private detectRotationGesture(orientation: GyroscopeOrientation) {
    // Detect specific rotation patterns
    if (Math.abs(orientation.z) > this.rotationThreshold) {
      const direction = orientation.z > 0 ? 'clockwise' : 'counterclockwise';
      console.log(`Device rotation: ${direction}`);
      this.onRotationDetected('spin', direction);
    }
    
    if (Math.abs(orientation.x) > this.rotationThreshold) {
      const direction = orientation.x > 0 ? 'forward' : 'backward';
      console.log(`Device pitch: ${direction}`);
      this.onRotationDetected('pitch', direction);
    }
    
    if (Math.abs(orientation.y) > this.rotationThreshold) {
      const direction = orientation.y > 0 ? 'left' : 'right';
      console.log(`Device roll: ${direction}`);
      this.onRotationDetected('roll', direction);
    }
  }
  
  private onRotationDetected(type: string, direction: string) {
    // Handle rotation gestures
    console.log(`Rotation gesture: ${type} ${direction}`);
  }
}

Battery Status

Monitor device battery level and charging status for power management features.

/**
 * Battery status data
 */
interface StatusObject {
  /** Battery level (0-100) */
  level: number;
  /** Whether device is plugged in */
  isPlugged: boolean;
}

/**
 * BatteryStatus class for battery monitoring
 */
class BatteryStatus {
  /**
   * Monitor battery status changes
   * @returns Observable emitting battery status updates
   */
  static onStatusChange(): Observable<StatusObject>;

  /**
   * Monitor low battery events
   * @returns Observable emitting low battery events
   */
  static onLow(): Observable<StatusObject>;

  /**
   * Monitor critical battery events
   * @returns Observable emitting critical battery events
   */
  static onCritical(): Observable<StatusObject>;
}

Usage Examples:

import { BatteryStatus } from 'ionic-native';

// Battery monitoring service
class BatteryMonitor {
  private statusSubscription: any;
  private lowBatterySubscription: any;
  private criticalBatterySubscription: any;
  
  startMonitoring() {
    // Monitor general status changes
    this.statusSubscription = BatteryStatus.onStatusChange().subscribe(
      (status) => {
        this.updateBatteryUI(status);
        this.handleBatteryStatus(status);
      }
    );
    
    // Monitor low battery
    this.lowBatterySubscription = BatteryStatus.onLow().subscribe(
      (status) => {
        this.handleLowBattery(status);
      }
    );
    
    // Monitor critical battery
    this.criticalBatterySubscription = BatteryStatus.onCritical().subscribe(
      (status) => {
        this.handleCriticalBattery(status);
      }
    );
  }
  
  stopMonitoring() {
    if (this.statusSubscription) this.statusSubscription.unsubscribe();
    if (this.lowBatterySubscription) this.lowBatterySubscription.unsubscribe();
    if (this.criticalBatterySubscription) this.criticalBatterySubscription.unsubscribe();
  }
  
  private updateBatteryUI(status: StatusObject) {
    // Update battery indicator
    const batteryElement = document.getElementById('battery-level');
    if (batteryElement) {
      batteryElement.textContent = `${status.level}%`;
      batteryElement.className = `battery-level ${this.getBatteryClass(status.level)}`;
    }
    
    // Update charging indicator
    const chargingElement = document.getElementById('charging-status');
    if (chargingElement) {
      chargingElement.textContent = status.isPlugged ? 'Charging' : 'Not Charging';
    }
  }
  
  private getBatteryClass(level: number): string {
    if (level > 80) return 'high';
    if (level > 50) return 'medium';
    if (level > 20) return 'low';
    return 'critical';
  }
  
  private handleBatteryStatus(status: StatusObject) {
    // Adjust app behavior based on battery level
    if (status.level < 20 && !status.isPlugged) {
      this.enablePowerSavingMode();
    } else if (status.level > 30 || status.isPlugged) {
      this.disablePowerSavingMode();
    }
  }
  
  private handleLowBattery(status: StatusObject) {
    console.warn('Low battery warning:', status);
    
    // Show low battery notification
    this.showBatteryWarning('Battery Low', `Battery level: ${status.level}%. Please charge your device.`);
    
    // Enable aggressive power saving
    this.enablePowerSavingMode();
  }
  
  private handleCriticalBattery(status: StatusObject) {
    console.error('Critical battery warning:', status);
    
    // Show critical battery alert
    this.showBatteryWarning('Critical Battery', `Battery critically low: ${status.level}%. Save your work immediately.`);
    
    // Enable emergency power saving
    this.enableEmergencyMode();
  }
  
  private enablePowerSavingMode() {
    console.log('Enabling power saving mode');
    
    // Reduce app functionality to save battery
    // - Lower screen brightness
    // - Reduce sync frequency
    // - Disable animations
    // - Limit background processes
  }
  
  private disablePowerSavingMode() {
    console.log('Disabling power saving mode');
    
    // Restore normal app functionality
  }
  
  private enableEmergencyMode() {
    console.log('Enabling emergency mode');
    
    // Minimal functionality only
    // - Auto-save data
    // - Disable non-essential features
    // - Show power saving tips
  }
  
  private showBatteryWarning(title: string, message: string) {
    // Show appropriate warning UI
    // Could use Toast, Dialogs, or custom notification
  }
}

Vibration

Control device vibration for haptic feedback and notifications.

/**
 * Vibration class for haptic feedback
 */
class Vibration {
  /**
   * Vibrate device
   * @param time Vibration duration in milliseconds, or array of durations for pattern
   */
  static vibrate(time: number | number[]): void;
}

Usage Examples:

import { Vibration } from 'ionic-native';

// Haptic feedback patterns
class HapticFeedback {
  // Success feedback
  static success() {
    Vibration.vibrate(100);
  }
  
  // Error feedback
  static error() {
    Vibration.vibrate([100, 50, 100]);
  }
  
  // Warning feedback
  static warning() {
    Vibration.vibrate([200, 100, 200]);
  }
  
  // Notification feedback
  static notification() {
    Vibration.vibrate([50, 50, 50]);
  }
  
  // Custom pattern
  static customPattern(pattern: number[]) {
    Vibration.vibrate(pattern);
  }
  
  // Long press feedback
  static longPress() {
    Vibration.vibrate(50);
  }
  
  // Button tap feedback
  static tap() {
    Vibration.vibrate(30);
  }
  
  // Heartbeat pattern
  static heartbeat() {
    Vibration.vibrate([100, 100, 200, 100, 300]);
  }
  
  // SOS pattern
  static sos() {
    // S-O-S in morse code
    Vibration.vibrate([
      100, 50, 100, 50, 100, // S
      200, 300, 50, 300, 50, 300, // O  
      200, 100, 50, 100, 50, 100  // S
    ]);
  }
}

// Usage examples
function showHapticExamples() {
  // Basic vibrations
  HapticFeedback.success();
  HapticFeedback.error();
  HapticFeedback.warning();
  
  // Custom patterns
  HapticFeedback.customPattern([200, 100, 200, 100, 400]);
  
  // Contextual feedback
  HapticFeedback.tap(); // For button presses
  HapticFeedback.longPress(); // For long press gestures
}

Flashlight

Control device LED flashlight for utility and emergency features.

/**
 * Flashlight class for LED control
 */
class Flashlight {
  /**
   * Check if flashlight is available
   * @returns Promise resolving to availability status
   */
  static available(): Promise<boolean>;

  /**
   * Turn flashlight on
   * @returns Promise resolving to success status
   */
  static switchOn(): Promise<boolean>;

  /**
   * Turn flashlight off
   * @returns Promise resolving to success status
   */
  static switchOff(): Promise<boolean>;

  /**
   * Toggle flashlight state
   * @returns Promise resolving to new state (true = on)
   */
  static toggle(): Promise<boolean>;
}

Usage Examples:

import { Flashlight } from 'ionic-native';

// Flashlight controller
class FlashlightController {
  private isOn = false;
  
  async initialize() {
    try {
      const available = await Flashlight.available();
      if (!available) {
        console.log('Flashlight not available on this device');
        return false;
      }
      
      console.log('Flashlight available');
      return true;
    } catch (error) {
      console.error('Error checking flashlight availability:', error);
      return false;
    }
  }
  
  async turnOn() {
    try {
      const success = await Flashlight.switchOn();
      if (success) {
        this.isOn = true;
        console.log('Flashlight turned on');
      }
      return success;
    } catch (error) {
      console.error('Error turning on flashlight:', error);
      return false;
    }
  }
  
  async turnOff() {
    try {
      const success = await Flashlight.switchOff();
      if (success) {
        this.isOn = false;
        console.log('Flashlight turned off');
      }
      return success;
    } catch (error) {
      console.error('Error turning off flashlight:', error);
      return false;
    }
  }
  
  async toggle() {
    try {
      const newState = await Flashlight.toggle();
      this.isOn = newState;
      console.log(`Flashlight ${newState ? 'on' : 'off'}`);
      return newState;
    } catch (error) {
      console.error('Error toggling flashlight:', error);
      return this.isOn;
    }
  }
  
  getState(): boolean {
    return this.isOn;
  }
  
  // Morse code signaling
  async morseCode(message: string) {
    const morseMap: { [key: string]: string } = {
      'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
      'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
      'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
      'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
      'Y': '-.--', 'Z': '--..', '0': '-----', '1': '.----', '2': '..---',
      '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...',
      '8': '---..', '9': '----.', ' ': '/'
    };
    
    for (const char of message.toUpperCase()) {
      const morse = morseMap[char];
      if (morse) {
        await this.sendMorseSequence(morse);
        await this.delay(200); // Inter-character pause
      }
    }
  }
  
  private async sendMorseSequence(morse: string) {
    for (const symbol of morse) {
      if (symbol === '.') {
        await this.flash(100); // Dot
      } else if (symbol === '-') {
        await this.flash(300); // Dash
      } else if (symbol === '/') {
        await this.delay(500); // Word separator
      }
      await this.delay(100); // Inter-element pause
    }
  }
  
  private async flash(duration: number) {
    await this.turnOn();
    await this.delay(duration);
    await this.turnOff();
  }
  
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
  
  // SOS emergency signal
  async sos() {
    const sosPattern = '... --- ...'; // SOS in morse
    await this.morseCode('SOS');
  }
  
  // Strobe effect
  async strobe(duration: number = 5000, frequency: number = 10) {
    const interval = 1000 / frequency;
    const endTime = Date.now() + duration;
    
    while (Date.now() < endTime) {
      await this.toggle();
      await this.delay(interval / 2);
    }
    
    // Ensure flashlight is off when done
    if (this.isOn) {
      await this.turnOff();
    }
  }
}

docs

analytics-monetization.md

camera-media.md

device-sensors.md

device-system.md

index.md

input-hardware.md

location-maps.md

network-communication.md

notifications-ui.md

security-auth.md

social-sharing.md

storage-files.md

tile.json