0.1.3 • Published 2 months ago
capsule-native v0.1.3
@capsule/native
This package provides production-ready native functionality for React Native applications built with Capsule.
Features
- 📸 Camera API - Take photos and record videos
- 🔐 Biometric Authentication - Secure your app with fingerprint, face recognition, or other biometric methods
- 🔔 Push Notifications - Send and receive push notifications
- 💾 Offline Storage - Store data securely on the device
- 📍 Geolocation - Access the device's location
- 📱 NFC - Read from and write to NFC tags
- 📁 File System Access - Read and write files on the device
- 🌐 Network Connectivity Monitoring - Monitor network status and changes
Installation
npm install @capsule/native
Additional Setup Required
- iOS: Add the following to your
Info.plist
:
<key>NSCameraUsageDescription</key>
<string>We need access to your camera for...</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>We need access to your location for...</string>
<key>NSFaceIDUsageDescription</key>
<string>We need access to Face ID for secure authentication</string>
<key>NFCReaderUsageDescription</key>
<string>We need access to NFC for...</string>
- Android: Add the following permissions to your
AndroidManifest.xml
:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.NFC" />
Basic Usage
import { NativeFeatures } from '@capsule/native';
// Initialize with default configuration
const native = new NativeFeatures();
// Or initialize with custom configuration
const native = new NativeFeatures({
featureToggles: {
camera: true,
biometricAuth: true,
nfc: true
}
});
Feature Usage
📸 Camera API
// Initialize camera
const camera = await native.initializeCamera({
quality: 'high',
flash: 'auto'
});
// Take a photo
try {
const photo = await native.takePhoto({
quality: 'high',
flash: 'auto'
});
console.log('Photo taken:', photo.uri);
} catch (error) {
console.error('Failed to take photo:', error);
}
// Record video
try {
await native.startVideoRecording();
// Later...
const video = await native.stopVideoRecording();
console.log('Video saved at:', video.path);
} catch (error) {
console.error('Video recording error:', error);
}
🔐 Biometric Authentication
// Check if biometrics are available
const { available, biometryType } = await native.isBiometricAvailable();
if (available) {
try {
// Authenticate user
const result = await native.authenticateWithBiometrics(
'Verify your identity',
{
cancelButtonText: 'Cancel',
fallbackPromptMessage: 'Please use your device passcode'
}
);
if (result.success) {
// User authenticated successfully
console.log('Authentication successful');
}
} catch (error) {
if (error.code === 'permission_denied') {
console.error('Biometric permission denied');
} else {
console.error('Authentication failed:', error);
}
}
}
🔔 Push Notifications
// Initialize notifications
try {
await native.initializeNotifications();
// Request permission
const permission = await native.requestNotificationPermission();
if (permission === 'granted') {
// Register for push notifications
const token = await native.registerForPushNotifications();
console.log('Push token:', token);
// Send to your backend
await sendTokenToBackend(token);
}
// Send a local notification
await native.sendLocalNotification({
title: 'Hello',
body: 'This is a local notification',
data: { screen: 'home' }
});
// Listen for notifications
const unsubscribe = native.onNotificationReceived((notification) => {
console.log('Received notification:', notification);
});
// Later, when no longer needed
unsubscribe();
} catch (error) {
console.error('Notification error:', error);
}
💾 Offline Storage
// Store data
try {
await native.storeData('user-profile', {
id: 123,
name: 'John Doe',
preferences: { theme: 'dark' }
});
// Retrieve data
const userData = await native.getData('user-profile');
// Remove data
await native.removeData('user-profile');
// Check if data exists
const exists = await native.hasData('user-profile');
} catch (error) {
console.error('Storage error:', error);
}
📍 Geolocation
// Get current position
try {
const position = await native.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000
});
console.log(
`Latitude: ${position.coords.latitude}, ` +
`Longitude: ${position.coords.longitude}`
);
} catch (error) {
console.error('Location error:', error);
}
// Watch position changes
const watchId = native.watchPosition(
(position) => {
console.log('Position updated:', position);
},
(error) => {
console.error('Watch position error:', error);
},
{
enableHighAccuracy: true,
distanceFilter: 10 // minimum distance in meters
}
);
// Stop watching
native.clearWatch(watchId);
📱 NFC (Near Field Communication)
// Check if NFC is supported
const isSupported = await native.isNfcSupported();
if (isSupported) {
try {
// Initialize NFC
await native.initializeNfc();
// Read an NFC tag
const tag = await native.readNfcTag({
alertMessage: 'Hold your device near an NFC tag',
invalidateAfterFirstRead: true
});
console.log('Tag ID:', tag.id);
console.log('Tag type:', tag.type);
if (tag.data) {
// Process tag data
tag.data.records.forEach(record => {
console.log('Record type:', record.recordType);
console.log('Payload:', record.payload);
});
}
// Write to an NFC tag
const success = await native.writeNfcTag(
[
// Text record
{
recordType: 'text',
payload: 'Hello from Capsule!'
},
// URI record
{
recordType: 'uri',
payload: 'https://example.com'
},
// Custom MIME data
{
recordType: 'mime',
mimeType: 'application/json',
payload: JSON.stringify({ id: 123, name: 'Product' })
}
],
{
alertMessage: 'Hold your device near an NFC tag to write',
formatReadOnly: false
}
);
if (success) {
console.log('Successfully wrote to NFC tag');
}
// Stop NFC when done
await native.stopNfc();
} catch (error) {
console.error('NFC error:', error);
}
}
📁 File System Access
try {
// Write a file
await native.writeFile('documents/note.txt', 'Hello, World!', {
encoding: 'utf8'
});
// Read a file
const content = await native.readFile('documents/note.txt');
// Check if file exists
const exists = await native.fileExists('documents/note.txt');
// Delete a file
await native.deleteFile('documents/note.txt');
// List directory contents
const files = await native.listDirectory('documents');
} catch (error) {
console.error('File system error:', error);
}
🌐 Network Connectivity
try {
// Check current network status
const networkStatus = await native.checkNetworkStatus();
console.log('Connected:', networkStatus.isConnected);
console.log('Connection type:', networkStatus.type); // 'wifi', 'cellular', etc.
// Subscribe to network changes
const unsubscribe = native.subscribeToNetworkChanges((status) => {
console.log('Network status changed:', status);
});
// Later, when no longer needed
unsubscribe();
} catch (error) {
console.error('Network error:', error);
}
Permissions
Most native features require user permissions. The bridge handles permission requests automatically, but you can also request them explicitly:
// Request camera permission
const cameraPermission = await native.requestPermission('camera');
// Request location permission
const locationPermission = await native.requestPermission('location');
// Request NFC permission (Android only)
const nfcPermission = await native.requestPermission('nfc');
// Check permission status
const notificationStatus = await native.checkPermission('notifications');
Error Handling
All methods throw descriptive errors with error codes when permissions are denied or operations fail. Always wrap calls in try-catch blocks:
try {
await native.initializeCamera();
} catch (error) {
if (error.code === 'permission_denied') {
// Handle permission denial
console.error('Camera permission denied');
} else if (error.code === 'device_unavailable') {
// Handle device unavailability
console.error('Camera not available on this device');
} else {
// Handle other errors
console.error('Camera initialization failed:', error);
}
}
Available error codes:
permission_denied
- User denied permissiondevice_unavailable
- Device doesn't have the required hardwarefeature_unsupported
- Feature is not supported on this platforminitialization_failed
- Failed to initialize the featureoperation_failed
- Operation failedinvalid_parameter
- Invalid parameter providedtimeout
- Operation timed outnetwork_error
- Network-related errorunknown_error
- Unknown error
Configuration
The native feature bridge can be configured using the Capsule configuration system:
import { NativeFeatures } from '@capsule/native';
// Initialize with custom configuration
const native = new NativeFeatures({
featureToggles: {
camera: true,
biometricAuth: true,
nfc: false,
pushNotifications: true,
geolocation: true,
fileSystem: true,
networkMonitoring: true,
localStorage: true
},
appSettings: {
// App-specific settings
}
});
// Check if a feature is enabled
if (native.isFeatureEnabled('camera')) {
// Camera is enabled
}
Security Considerations
Biometric Authentication
- Uses the device's secure hardware (TouchID/FaceID on iOS, Fingerprint/Face Unlock on Android)
- Credentials never leave the secure hardware
Storage
- Sensitive data is stored using the platform's secure storage mechanisms
- Consider encrypting sensitive data before storage
Permissions
- All features request permissions at runtime
- Users can revoke permissions at any time through system settings
Performance Considerations
Camera
- Initialize camera only when needed
- Release camera resources when not in use
Geolocation
- Consider battery impact of continuous location tracking
- Use appropriate accuracy settings based on needs
Network Monitoring
- Unsubscribe from network changes when no longer needed
- Use
unsubscribe()
function returned bysubscribeToNetworkChanges
NFC
- Stop NFC scanning when not in use to save battery
- Use
stopNfc()
when done with NFC operations
Platform-Specific Considerations
NFC Platform Considerations
- iOS: NFC reading is supported on iPhone 7 and newer running iOS 11+. NFC writing requires iOS 13+. Background NFC scanning is only available on iOS 13+.
- Android: Most Android devices with NFC hardware support both reading and writing. Background scanning is supported.
- Web: NFC is supported via the Web NFC API, but only in Chrome for Android (version 89+) and with limited functionality.
Contributing
Please read CONTRIBUTING.md for details on our code of conduct and the process for submitting pull requests.