1. React Native
  2. Model Management API

React Native

Model Management API

NEW in v2.0.2: The React Native Vision SDK includes a comprehensive Model Management API that provides fine-grained control over on-device ML models. This replaces the deprecated loadModel() and unLoadModel() methods with a more powerful and flexible system.


Overview

The Model Management API allows you to:

  • Download models from the server to disk with progress tracking
  • Load models into memory for fast inference
  • Unload models from memory to free resources
  • Delete models from disk permanently
  • Query model status (downloaded, loaded, size, version)
  • Switch between different models dynamically
  • Track lifecycle events for all model operations

Key Benefits

  • Separation of Concerns: Download and load are separate operations
  • Progress Tracking: Per-download progress callbacks with unique request IDs
  • Model Caching: Download once, load multiple times without re-downloading
  • Memory Control: Unload without deleting, or delete permanently
  • Type Safety: OCRModule type instead of separate string parameters
  • Explicit Selection: Specify exact model for predictions

Quick Start

        import { VisionCore } from 'react-native-vision-sdk';

const module = { type: 'shipping_label', size: 'large' };

// 1. Initialize (REQUIRED on Android, not needed on iOS)
VisionCore.initializeModelManager({ maxConcurrentDownloads: 2 });

// 2. Download model with progress tracking
await VisionCore.downloadModel(
  module,
  apiKey,
  token,
  'react_native',
  (progress) => console.log(`${(progress.progress * 100).toFixed(1)}%`)
);

// 3. Load into memory
await VisionCore.loadOCRModel(module, apiKey, token);

// 4. Make predictions
const result = await VisionCore.predictWithModule(module, imageUri, barcodes);

// 5. Cleanup
await VisionCore.unloadModel(module);  // From memory
await VisionCore.deleteModel(module);  // From disk (permanent)

      

Initialization

initializeModelManager(config)

Initialize the Model Manager singleton with configuration options.

Parameters

  • config (ModelManagerConfig):
    • maxConcurrentDownloads?: number - Maximum concurrent downloads (default: 2)
    • enableLogging?: boolean - Enable debug logging (default: true)

Platform Requirements

  • Android: REQUIRED - Must be called before any model operations
  • iOS: Not needed - This method is a hardcoded no-op for API consistency

Example

        VisionCore.initializeModelManager({
  maxConcurrentDownloads: 3,
  enableLogging: __DEV__ // Only in development
});

      
WARNING

Android: Model operations will fail if initializeModelManager() is not called first.

iOS: This method exists only for cross-platform API consistency and has no effect.


isModelManagerInitialized()

Check if the Model Manager has been initialized.

Returns

  • boolean - true if initialized, false otherwise

Example

        // Android: Check before operations
if (!VisionCore.isModelManagerInitialized()) {
  VisionCore.initializeModelManager({ maxConcurrentDownloads: 2 });
}

// Now safe to proceed
await VisionCore.downloadModel(module, apiKey, token);

      
NOTE

iOS: Always returns true (hardcoded). iOS doesn't require initialization.


Download Operations

downloadModel(module, apiKey, token, platformType, progressCallback)

Download a model from the server to device storage with progress tracking.

Parameters

  • module (OCRModule): Model to download
    • type: 'shipping_label' | 'item_label' | 'bill_of_lading' | 'document_classification'
    • size: 'nano' | 'micro' | 'small' | 'medium' | 'large' | 'xlarge'
  • apiKey (string | null): API key for authentication
  • token (string | null): Auth token for authentication
  • platformType (string, optional): Platform identifier (default: 'react_native')
  • progressCallback (function, optional): Callback for progress updates

Returns

  • Promise<void> - Resolves when download completes

Progress Callback

The callback receives a DownloadProgress object:

        {
  module: OCRModule;     // The module being downloaded
  progress: number;      // 0.0 to 1.0 (download percentage)
}

      

Example

        await VisionCore.downloadModel(
  { type: 'shipping_label', size: 'large' },
  apiKey,
  token,
  'react_native',
  (progress) => {
    const percent = (progress.progress * 100).toFixed(1);
    console.log(`Downloading: ${percent}%`);

    // Update UI
    setDownloadProgress(progress.progress);
  }
);

      

Error Handling

        try {
  await VisionCore.downloadModel(module, apiKey, token);
  console.log('Download complete');
} catch (error) {
  console.error('Download failed:', error.message);
  Alert.alert('Error', `Failed to download: ${error.message}`);
}

      

cancelDownload(module)

Cancel an active download operation for a specific model.

Parameters

  • module (OCRModule): The model whose download to cancel

Returns

  • Promise<boolean> - true if cancelled, false if no active download

Example

        const module = { type: 'shipping_label', size: 'large' };

// Start download
VisionCore.downloadModel(module, apiKey, token, 'react_native', (progress) => {
  console.log(`Progress: ${progress.progress * 100}%`);
});

// Cancel if needed
const cancelled = await VisionCore.cancelDownload(module);
if (cancelled) {
  console.log('Download cancelled successfully');
}

      

Load/Unload Operations

loadOCRModel(module, apiKey, token, platformType, executionProvider)

Load a model from disk into memory for inference.

Parameters

  • module (OCRModule): Model to load
  • apiKey (string | null): API key
  • token (string | null): Auth token
  • platformType (string, optional): Platform identifier (default: 'react_native')
  • executionProvider (ExecutionProvider, optional): Android only
    • 'CPU' (default) - Best compatibility, works on all devices
    • 'NNAPI' - Android Neural Networks API for hardware acceleration
    • 'XNNPACK' - Optimized CPU kernels for ARM processors

Returns

  • Promise<void> - Resolves when loaded

Example

        // Basic usage (CPU execution)
await VisionCore.loadOCRModel(
  { type: 'shipping_label', size: 'large' },
  apiKey,
  token
);

// Android: Use NNAPI for better performance
await VisionCore.loadOCRModel(
  { type: 'shipping_label', size: 'large' },
  apiKey,
  token,
  'react_native',
  'NNAPI'
);

      
NOTE

If the model is not downloaded, it will be automatically downloaded first before loading.


unloadModel(module)

Unload a model from memory. Files remain on disk for faster reloading.

Parameters

  • module (OCRModule): Model to unload

Returns

  • Promise<boolean> - true if unloaded, false if wasn't loaded

Example

        const unloaded = await VisionCore.unloadModel({
  type: 'shipping_label',
  size: 'large'
});

if (unloaded) {
  console.log('Model unloaded from memory');
} else {
  console.log('Model was not loaded');
}

      

isModelLoaded(module)

Check if a specific model is currently loaded in memory.

Parameters

  • module (OCRModule): Model to check

Returns

  • boolean - true if loaded, false otherwise

Example

        const loaded = VisionCore.isModelLoaded({
  type: 'shipping_label',
  size: 'large'
});

if (!loaded) {
  await VisionCore.loadOCRModel(module, apiKey, token);
}

      

getLoadedModelCount()

Get the number of models currently loaded in memory.

Returns

  • number - Count of loaded models

Example

        const count = VisionCore.getLoadedModelCount();
console.log(`${count} model(s) currently loaded`);

// Unload some models if too many are loaded
if (count > 2) {
  await VisionCore.unloadModel(oldModule);
}

      

Query Operations

findDownloadedModels()

List all models downloaded to device storage.

Returns

  • Promise<ModelInfo[]> - Array of downloaded models

ModelInfo Structure

        {
  module: OCRModule;        // Model type and size
  version: string;          // Model version (e.g., "2025-05-05")
  versionId: string | null; // Unique version identifier
  dateString: string;       // Model release date
  isLoaded: boolean;        // Whether currently loaded in memory
}

      

Example

        const downloaded = await VisionCore.findDownloadedModels();

console.log(`Found ${downloaded.length} downloaded model(s):`);
downloaded.forEach(model => {
  console.log(`- ${model.module.type} (${model.module.size})`);
  console.log(`  Version: ${model.version}`);
  console.log(`  Loaded: ${model.isLoaded ? 'Yes' : 'No'}`);
});

      

findDownloadedModel(module)

Find information about a specific downloaded model.

Parameters

  • module (OCRModule): Model to find

Returns

  • Promise<ModelInfo | null> - Model info if found, null otherwise

Example

        const modelInfo = await VisionCore.findDownloadedModel({
  type: 'shipping_label',
  size: 'large'
});

if (modelInfo) {
  console.log('Model found on disk');
  console.log('Version:', modelInfo.version);
} else {
  console.log('Model not downloaded - downloading now...');
  await VisionCore.downloadModel(module, apiKey, token);
}

      

findLoadedModels()

List all models currently loaded in memory.

Returns

  • Promise<ModelInfo[]> - Array of loaded models

Example

        const loaded = await VisionCore.findLoadedModels();

console.log(`${loaded.length} model(s) in memory:`);
loaded.forEach(model => {
  console.log(`- ${model.module.type} (${model.module.size})`);
});

      

Delete Operations

deleteModel(module)

Permanently delete a model from disk. If the model is loaded, it will be unloaded first.

Parameters

  • module (OCRModule): Model to delete

Returns

  • Promise<boolean> - true if deleted, false if not found

Example

        const deleted = await VisionCore.deleteModel({
  type: 'shipping_label',
  size: 'large'
});

if (deleted) {
  console.log('Model deleted from disk');
} else {
  console.log('Model was not found on disk');
}

      
WARNING

Deletion is permanent. The model must be re-downloaded to use again.


Prediction with Specific Models

predictWithModule(module, imagePath, barcodes)

Perform OCR prediction using a specific model.

Parameters

  • module (OCRModule): The model to use for prediction
  • imagePath (string): Path to image file or URI
  • barcodes (string[]): Array of barcode strings detected in image

Returns

  • Promise<any> - Prediction result (structure varies by model type)

Example

        const result = await VisionCore.predictWithModule(
  { type: 'shipping_label', size: 'large' },
  'file:///path/to/image.jpg',
  ['1234567890', '9876543210']
);

console.log('Sender:', result.sender);
console.log('Recipient:', result.recipient);
console.log('Tracking:', result.trackingNumber);

      
NOTE

The model must be loaded into memory before calling this method.


Event Listeners

onModelLifecycle(listener)

Subscribe to global model lifecycle events.

Parameters

  • listener (function): Callback for lifecycle events

Returns

  • EmitterSubscription - Subscription object (call .remove() to unsubscribe)

Event Types

  • onDownloadStarted - Model download began
  • onDownloadCompleted - Model download finished
  • onDownloadFailed - Model download failed
  • onDownloadCancelled - Model download was cancelled
  • onModelLoaded - Model loaded into memory
  • onModelUnloaded - Model unloaded from memory
  • onModelDeleted - Model deleted from disk

Example

        const subscription = VisionCore.onModelLifecycle((event) => {
  console.log('Event:', event.type);
  console.log('Module:', `${event.module.type} (${event.module.size})`);

  switch (event.type) {
    case 'onDownloadStarted':
      console.log('Download started');
      break;
    case 'onDownloadCompleted':
      console.log('Download completed');
      break;
    case 'onDownloadFailed':
      console.error('Download failed:', event.error);
      break;
    case 'onModelLoaded':
      console.log('Model loaded into memory');
      break;
    case 'onModelUnloaded':
      console.log('Model unloaded from memory');
      break;
    case 'onModelDeleted':
      console.log('Model deleted from disk');
      break;
  }
});

// Later: cleanup
subscription.remove();

      

Complete Examples

Download Multiple Models Concurrently

        const models = [
  { type: 'shipping_label', size: 'large' },
  { type: 'item_label', size: 'medium' },
  { type: 'bill_of_lading', size: 'large' }
];

// Initialize with concurrent downloads
VisionCore.initializeModelManager({ maxConcurrentDownloads: 3 });

// Download all models in parallel
const downloads = models.map(module =>
  VisionCore.downloadModel(module, apiKey, token, 'react_native', (progress) => {
    console.log(`${progress.module.type}: ${(progress.progress * 100).toFixed(1)}%`);
  })
);

// Wait for all downloads
await Promise.all(downloads);
console.log('All downloads complete');

      

Switch Between Models

        const model1 = { type: 'shipping_label', size: 'large' };
const model2 = { type: 'item_label', size: 'medium' };

// Ensure both are downloaded (only need to download once)
await VisionCore.downloadModel(model1, apiKey, token);
await VisionCore.downloadModel(model2, apiKey, token);

// Use first model
await VisionCore.loadOCRModel(model1, apiKey, token);
const result1 = await VisionCore.predictWithModule(model1, image1, barcodes1);

// Switch to second model (unload first to free memory)
await VisionCore.unloadModel(model1);
await VisionCore.loadOCRModel(model2, apiKey, token);
const result2 = await VisionCore.predictWithModule(model2, image2, barcodes2);

      

Check Before Operations

        const module = { type: 'shipping_label', size: 'large' };

// Check if downloaded
const info = await VisionCore.findDownloadedModel(module);
if (!info) {
  console.log('Model not downloaded, downloading now...');
  await VisionCore.downloadModel(module, apiKey, token);
}

// Check if loaded
if (!VisionCore.isModelLoaded(module)) {
  console.log('Model not loaded, loading now...');
  await VisionCore.loadOCRModel(module, apiKey, token);
}

// Now safe to predict
const result = await VisionCore.predictWithModule(module, imagePath, barcodes);

      

Full Workflow with State Management

        import React, { useState, useEffect } from 'react';
import { View, Button, Text, Alert } from 'react-native';
import { VisionCore } from 'react-native-vision-sdk';

const ModelManagementExample = () => {
  const [isModelLoaded, setIsModelLoaded] = useState(false);
  const [downloadProgress, setDownloadProgress] = useState(0);
  const [prediction, setPrediction] = useState('');

  const module = {
    type: 'shipping_label',
    size: 'large'
  };

  useEffect(() => {
    // Initialize on mount (Android only - iOS is no-op)
    VisionCore.initializeModelManager({
      maxConcurrentDownloads: 2,
      enableLogging: true
    });

    // Listen to lifecycle events
    const subscription = VisionCore.onModelLifecycle((event) => {
      console.log('Lifecycle event:', event.type);
    });

    return () => subscription.remove();
  }, []);

  const loadModel = async () => {
    try {
      // Download with progress
      await VisionCore.downloadModel(
        module,
        'your-api-key',
        null,
        'react_native',
        (progress) => {
          setDownloadProgress(progress.progress);
        }
      );

      // Load into memory
      await VisionCore.loadOCRModel(module, 'your-api-key', null);

      setIsModelLoaded(true);
      Alert.alert('Success', 'Model loaded and ready!');
    } catch (error) {
      Alert.alert('Error', `Failed to load: ${error.message}`);
    }
  };

  const runPrediction = async () => {
    if (!isModelLoaded) {
      Alert.alert('Warning', 'Please load model first');
      return;
    }

    try {
      const imagePath = 'path/to/image.jpg';
      const result = await VisionCore.predictWithModule(
        module,
        imagePath,
        []
      );
      setPrediction(JSON.stringify(result, null, 2));
    } catch (error) {
      Alert.alert('Error', 'Prediction failed');
    }
  };

  const cleanup = async () => {
    await VisionCore.unloadModel(module);
    await VisionCore.deleteModel(module);
    setIsModelLoaded(false);
    Alert.alert('Success', 'Model unloaded and deleted');
  };

  return (
    <View style={{ padding: 20 }}>
      <Button
        title="Download & Load Model"
        onPress={loadModel}
        disabled={isModelLoaded}
      />

      {downloadProgress > 0 && downloadProgress < 1 && (
        <Text>Progress: {(downloadProgress * 100).toFixed(1)}%</Text>
      )}

      <Button
        title="Run Prediction"
        onPress={runPrediction}
        disabled={!isModelLoaded}
      />

      <Button
        title="Cleanup"
        onPress={cleanup}
        disabled={!isModelLoaded}
      />

      <Text>Model Status: {isModelLoaded ? 'Ready' : 'Not Loaded'}</Text>

      {prediction && (
        <Text style={{ fontFamily: 'monospace', marginTop: 10 }}>
          {prediction}
        </Text>
      )}
    </View>
  );
};

      

Platform Differences

iOS vs Android

Feature iOS Android
Initialization Not needed (hardcoded no-op) Required (must call before operations)
isModelManagerInitialized() Always returns true Returns actual status
Model unloading Granular (specific model) Granular (specific model)
Execution provider Not exposed CPU, NNAPI, XNNPACK
Concurrent downloads Supported Supported
Model switching Supported Supported
Lifecycle events Full support Full support

Android-Specific Behavior

Initialization Requirement:

Android requires explicit initialization before any model operations:

        // Android: This will fail if not initialized
await VisionCore.downloadModel(module, apiKey, token); // Error!

// Android: Correct approach
VisionCore.initializeModelManager({ maxConcurrentDownloads: 2 });
await VisionCore.downloadModel(module, apiKey, token); // Works

// iOS: Works without initialization
await VisionCore.downloadModel(module, apiKey, token); // Works

      

iOS-Specific Behavior

Initialization Not Required:

iOS does not require initialization. The methods exist only for API consistency:

  • initializeModelManager() - Does nothing (hardcoded no-op)
  • isModelManagerInitialized() - Always returns true (hardcoded)

You can safely call these methods for cross-platform code consistency.


Migration from Deprecated API

Old API (Deprecated)

        // Will be removed in v3.0.0
await VisionCore.loadModel(token, apiKey, 'shipping_label', 'large');
const result = await VisionCore.predict(imageUri, barcodes);
await VisionCore.unLoadModel('shipping_label', true);

      
        const module = { type: 'shipping_label', size: 'large' };

// Initialize (Android only)
VisionCore.initializeModelManager({ maxConcurrentDownloads: 2 });

// Download (with progress)
await VisionCore.downloadModel(module, apiKey, token, 'react_native', (progress) => {
  console.log(`Progress: ${progress.progress * 100}%`);
});

// Load into memory
await VisionCore.loadOCRModel(module, apiKey, token);

// Predict with specific model
const result = await VisionCore.predictWithModule(module, imageUri, barcodes);

// Cleanup
await VisionCore.unloadModel(module);  // From memory
await VisionCore.deleteModel(module);  // From disk

      

Benefits of New API

  • Separate download and load phases
  • Progress tracking per download
  • Model caching (download once, load multiple times)
  • Clear separation: unload vs delete
  • Boolean return values for status checking
  • Type-safe OCRModule parameter
  • Explicit model selection for predictions

Best Practices

1. Initialize Once (Android Only)

        // At app startup
VisionCore.initializeModelManager({
  maxConcurrentDownloads: 2,
  enableLogging: __DEV__  // Only in development
});

// Or check first
if (!VisionCore.isModelManagerInitialized()) {
  VisionCore.initializeModelManager({ maxConcurrentDownloads: 2 });
}

      

2. Check Before Operations

        // Avoid unnecessary downloads
const info = await VisionCore.findDownloadedModel(module);
if (!info) {
  await VisionCore.downloadModel(module, apiKey, token);
}

// Ensure model is loaded before prediction
if (!VisionCore.isModelLoaded(module)) {
  await VisionCore.loadOCRModel(module, apiKey, token);
}

      

3. Clean Up Unused Models

        // When done with a model
await VisionCore.unloadModel(module);  // Frees memory

// When permanently done
await VisionCore.deleteModel(module);  // Frees disk space

      

4. Handle Errors Gracefully

        try {
  await VisionCore.downloadModel(module, apiKey, token);
} catch (error) {
  if (error.message.includes('network')) {
    Alert.alert('No Connection', 'Please check your internet connection');
  } else if (error.message.includes('storage')) {
    Alert.alert('Storage Full', 'Please free up some space');
  } else {
    Alert.alert('Error', error.message);
  }
}

      

5. Monitor Lifecycle Events

        useEffect(() => {
  const subscription = VisionCore.onModelLifecycle((event) => {
    switch (event.type) {
      case 'onDownloadCompleted':
        // Auto-load after download
        VisionCore.loadOCRModel(event.module, apiKey, token);
        break;
      case 'onDownloadFailed':
        Alert.alert('Download Failed', event.error);
        break;
    }
  });

  return () => subscription.remove();
}, []);

      

Types & Interfaces

OCRModule

        type OCRModule = {
  type: 'shipping_label' | 'item_label' | 'bill_of_lading' | 'document_classification';
  size: 'nano' | 'micro' | 'small' | 'medium' | 'large' | 'xlarge';
};

      

ModelManagerConfig

        type ModelManagerConfig = {
  maxConcurrentDownloads?: number;  // Default: 2
  enableLogging?: boolean;          // Default: true
};

      

DownloadProgress

        interface DownloadProgress {
  module: OCRModule;       // The module being downloaded
  progress: number;        // 0.0 to 1.0 (download percentage)
}

      

ModelInfo

        interface ModelInfo {
  module: OCRModule;        // Model type and size
  version: string;          // Model version (e.g., "2025-05-05")
  versionId: string | null; // Unique version identifier
  dateString: string;       // Model release date
  isLoaded: boolean;        // Whether currently loaded in memory
}

      

ExecutionProvider (Android only)

        type ExecutionProvider = 'CPU' | 'NNAPI' | 'XNNPACK';

      

Recommendations:

  • CPU: Best compatibility, works on all devices
  • NNAPI: Potentially faster on supported devices (Android 8.1+)
  • XNNPACK: Optimized for ARM processors


API Reference Summary

Method Description Returns
initializeModelManager(config) Initialize model manager (Android only) void
isModelManagerInitialized() Check initialization status boolean
downloadModel(...) Download model to disk with progress Promise<void>
cancelDownload(module) Cancel active download Promise<boolean>
loadOCRModel(...) Load model into memory Promise<void>
unloadModel(module) Unload from memory Promise<boolean>
isModelLoaded(module) Check if loaded boolean
getLoadedModelCount() Count loaded models number
findDownloadedModels() List downloaded models Promise<ModelInfo[]>
findDownloadedModel(module) Find specific model Promise<ModelInfo | null>
findLoadedModels() List loaded models Promise<ModelInfo[]>
deleteModel(module) Delete from disk Promise<boolean>
predictWithModule(...) Predict with specific model Promise<any>
onModelLifecycle(listener) Subscribe to events EmitterSubscription

Last Updated: December 2024 SDK Version: 2.0.2+