Alaqan Mini SDK
для Android
Интегрируйте биометрическую аутентификацию по венам ладони в ваши Android-приложения с помощью нашего безопасного и простого в использовании SDK.
Введение
Alaqan Mini SDK позволяет Android-приложениям интегрировать биометрическую аутентификацию по венам ладони с использованием устройства Alaqan Mini. SDK обеспечивает USB-связь, обработку кадров в реальном времени с обнаружением руки, а также биометрические операции регистрации и идентификации.
Высокая безопасность
Мультиспектральная съёмка с определением живости для корпоративной безопасности.
Быстрое распознавание
Идентификация менее чем за секунду для бесшовного пользовательского опыта.
Простая интеграция
Простой API с подробными обратными вызовами и понятной документацией.
Бесконтактный
Гигиеничное распознавание вен ладони без физического контакта.
Сценарии использования
- Аутентификация в POS-терминалах
- Банковские и финансовые услуги
- Системы контроля доступа
- Учёт рабочего времени
- Верификация личности
Требования
Аппаратное обеспечение
| Компонент | Требование |
|---|---|
| Устройство | Сканер ладони Alaqan Mini |
| Подключение | USB Type-C |
| Хост-устройство | Android-устройство с поддержкой OTG |
Программное обеспечение
| Компонент | Требование |
|---|---|
| Android SDK | Минимум API Level 24 (Android 7.0 Nougat) |
| Target SDK | API Level 34 (Android 14) рекомендуется |
| Архитектура | arm64-v8a, armeabi-v7a |
Сеть
- Активное интернет-соединение для активации SDK и биометрических операций
- Рекомендуемая пропускная способность: 1 Мбит/с
Установка
Добавьте SDK в проект
Добавьте AAR-файл Alaqan Mini SDK в папку libs вашего проекта:
app/
├── libs/
│ └── alaqan-mini-sdk.aar
├── src/
└── build.gradle
Настройте Gradle
Добавьте следующее в build.gradle уровня приложения:
android {
defaultConfig {
minSdk 24
ndk {
abiFilters 'arm64-v8a', 'armeabi-v7a'
}
}
}
dependencies {
implementation files('libs/alaqan-mini-sdk.aar')
implementation 'androidx.appcompat:appcompat:1.6.1'
}
Настройте USB-фильтр
Создайте res/xml/device_filter.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-device vendor-id="17992" product-id="65280" />
</resources>
Обновите AndroidManifest.xml
Добавьте необходимые разрешения и конфигурацию USB:
<manifest>
<uses-feature android:name="android.hardware.usb.host" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
</application>
</manifest>
Быстрый старт
Рекомендуемая интеграция использует высокоуровневый API. SDK автоматически управляет настройкой камеры, обнаружением руки, захватом и биометрическим сопоставлением.
class MainActivity : AppCompatActivity(), AlaqanMiniListener {
private val sdk = AlaqanMiniSDK()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sdk.setApiKey("YOUR_API_KEY")
sdk.initialize(this)
}
override fun onResume() {
super.onResume()
sdk.setListener(this)
if (sdk.isInitialized && !sdk.device.isConnected) {
sdk.device.connect()
}
}
override fun onPause() {
sdk.setListener(null)
super.onPause()
}
override fun onDestroy() {
sdk.destroy()
super.onDestroy()
}
override fun onInitialized() {
sdk.device.connect()
}
override fun onDeviceConnected(device: Device) {
// Устройство готово — запускаем операцию идентификации
sdk.startIdentify(object : IdentifyCallback {
override fun onGuidance(guidance: Guidance) {
statusText.text = when (guidance) {
Guidance.SHOW_PALM -> "Show your palm"
Guidance.MOVE_CLOSER -> "Move closer"
Guidance.MOVE_FURTHER -> "Move further"
Guidance.CENTER_PALM -> "Center your palm"
Guidance.HOLD_STEADY -> "Hold steady"
Guidance.CAPTURING -> "Capturing..."
Guidance.PROCESSING -> "Processing..."
}
}
override fun onPreviewFrame(result: FrameResult) {
result.bitmap?.let { imageView.setImageBitmap(it) }
}
override fun onResult(result: IdentifyResult) {
if (result.isSuccess) {
Log.d("Alaqan", "Identified: ${result.name}")
} else {
Log.e("Alaqan", "Failed: ${result.error}")
}
}
})
}
override fun onDeviceDisconnected(device: Device) {
Log.d("Alaqan", "Disconnected")
}
override fun onError(code: String) {
Log.e("Alaqan", "Error: $code")
}
}
Архитектура SDK
Вызовите startIdentify() или startEnroll() — SDK возьмёт на себя настройку камеры, обнаружение руки, захват и биометрическое сопоставление. Используйте getPersons() и deletePerson() для управления пользователями.
Нижележащие уровни:
- Уровень устройства — USB-подключение, управление камерами, датчик расстояния
- Уровень обработки — обнаружение руки в реальном времени и оценка качества
- Уровень API — Регистрация, идентификация и управление пользователями
Жизненный цикл
SDK следует лучшим практикам жизненного цикла Android. Все обратные вызовы доставляются в главном (UI) потоке.
| Состояние приложения | Рекомендуемое действие SDK |
|---|---|
Application.onCreate() | setApiKey() + initialize() |
Activity.onResume() | setListener(this) + device.connect() |
Activity.onPause() | setListener(null) |
Завершение приложения | destroy() |
Создайте экземпляр SDK один раз (например, в классе Application) и используйте его во всех Activity. Только один слушатель может быть активен одновременно — устанавливайте его в onResume() и очищайте в onPause(). Используйте setGlobalListener() для постоянной обработки событий при переходах между Activity.
Высокоуровневый API
Вызовите startIdentify() или startEnroll(), и SDK возьмёт на себя настройку камеры, детекцию, захват и биометрическое сопоставление. Вы получаете обновления подсказок, кадры превью и итоговый результат через обратный вызов.
Одновременно может выполняться только одна операция. Вызовите stopOperation() для отмены.
Управление операциями
fun startIdentify(callback: IdentifyCallback)
fun startEnroll(externalId: String, name: String, metadata: String?, callback: EnrollCallback)
fun stopOperation()
fun setOperationTimeout(ms: Long) // по умолчанию 30000, 0 = без таймаута
fun getOperationState(): OperationState // IDLE, DETECTING, CAPTURING, PROCESSING
fun getOperationInfo(): OperationInfo? // null когда нет активной операции
OperationState
| Значение | Описание |
|---|---|
IDLE | Нет запущенных операций |
DETECTING | Ожидание руки с достаточным качеством и стабильностью |
CAPTURING | Стабильная рука найдена, захват кадров |
PROCESSING | Кадры захвачены, выполняется обработка |
OperationInfo
| Поле | Тип | Описание |
|---|---|---|
type | OperationInfo.Type | IDENTIFY или ENROLL |
state | OperationState | Текущая фаза операции |
Идентификация
Запускает операцию идентификации. SDK обнаруживает и захватывает ладонь пользователя, захватывает кадры и возвращает результат совпадения.
sdk.startIdentify(object : IdentifyCallback {
override fun onPreviewFrame(result: FrameResult) {
// Опционально: отображение превью камеры
result.bitmap?.let { imageView.setImageBitmap(it) }
}
override fun onGuidance(guidance: Guidance) {
// Обновление UI с инструкциями по позиционированию
statusText.text = guidanceToString(guidance)
}
override fun onResult(result: IdentifyResult) {
if (result.isSuccess) {
showMatch(result.externalId, result.name, result.metadata)
} else {
showError(result.error)
}
}
})
IdentifyResult
| Поле | Тип | Описание |
|---|---|---|
scanId | String? | Идентификатор скана |
externalId | String? | Внешний ID найденного пользователя |
name | String? | Имя найденного пользователя |
metadata | String? | JSON-метаданные, заданные при регистрации |
error | String? | Константа ErrorCodes или сообщение об ошибке (null при успехе) |
fun isSuccess(): Boolean // true если error == null
Регистрация
Запускает операцию регистрации. SDK захватывает несколько кадров, и возвращает результат регистрации. Обратный вызов onProgress сообщает о прогрессе захвата.
sdk.startEnroll("user-123", "John Doe", null, object : EnrollCallback {
override fun onPreviewFrame(result: FrameResult) {
result.bitmap?.let { imageView.setImageBitmap(it) }
}
override fun onGuidance(guidance: Guidance) {
statusText.text = guidanceToString(guidance)
}
override fun onProgress(captured: Int, total: Int) {
progressBar.progress = captured * 100 / total
}
override fun onResult(result: EnrollResult) {
if (result.isSuccess) {
showSuccess(result.scanId)
} else {
showError(result.error)
}
}
})
EnrollResult
| Поле | Тип | Описание |
|---|---|---|
scanId | String? | Идентификатор скана |
error | String? | Константа ErrorCodes или сообщение об ошибке (null при успехе) |
fun isSuccess(): Boolean // true если error == null
Подсказки
Перечисление Guidance предоставляет подсказки по позиционированию в реальном времени во время операций идентификации и регистрации. Сопоставьте их с вашими собственными локализованными строками UI.
| Значение | Описание |
|---|---|
SHOW_PALM | Рука не обнаружена — предложите пользователю показать ладонь |
MOVE_CLOSER | Рука слишком далеко от устройства |
MOVE_FURTHER | Рука слишком близко к устройству |
CENTER_PALM | Рука смещена от центра кадра |
HOLD_STEADY | Рука обнаружена, но недостаточно стабильна |
CAPTURING | Кадр захвачен (только при регистрации, может срабатывать несколько раз) |
PROCESSING | Захват завершён, обработка биометрических данных |
Справочник API
Инициализация
setApiKey()
Устанавливает API-ключ для активации SDK. Должен быть вызван до initialize().
fun setApiKey(apiKey: String?)
initialize()
Асинхронная инициализация SDK — создаёт нативный контекст, активируется по API-ключу и загружает модели. Вызывает onInitialized() при успехе или onError() при ошибке.
fun initialize(context: Context)
isInitialized()
fun isInitialized(): Boolean
getNativeVersion()
Возвращает строку версии нативной библиотеки. Доступна после initialize().
fun getNativeVersion(): String?
setLedGateEnabled()
Включает или отключает LED-гейт для инференса. Когда включён (по умолчанию), инференс пропускается на кадрах, где LED выключен. Отключите для запуска инференса на всех кадрах вне зависимости от состояния LED.
fun setLedGateEnabled(enabled: Boolean) // по умолчанию: true
setGlobalListener()
Устанавливает постоянный слушатель, который получает события вне зависимости от слушателя уровня Activity, установленного через setListener(). Полезен для обработки событий устройства в сервисе или компоненте уровня приложения, который переживает переходы между Activity.
fun setGlobalListener(listener: AlaqanMiniListener?)
destroy()
Освобождает все ресурсы SDK, включая нативную память и USB-подключения. Вызывайте в onDestroy().
fun destroy()
Устройство
Доступ к экземпляру устройства через sdk.getDevice(). Класс Device управляет USB-подключением, камерами и датчиками.
Подключение
fun connect()
fun disconnect()
fun isConnected(): Boolean
Информация об устройстве
fun getSerialNumber(): String? // например, "GX4TYQWH3D"
fun getFirmwareVersion(): String? // например, "1.2.3"
Датчик расстояния
fun getDistance(): Int // текущее расстояние в мм, -1 если недоступно
fun getSensingRange(): IntArray? // [min, max] в мм, или null
fun setSensingRange(min: Int, max: Int) // установить диапазон (по умолчанию 70–170)
Управление LED
fun setLedMode(mode: Int) // Device.LED_AUTO (по умолчанию) или Device.LED_MANUAL
fun isLedModeSupported(): Boolean // сначала проверьте аппаратную поддержку
| Константа | Значение | Описание |
|---|---|---|
Device.LED_AUTO | 0 | LED включаются автоматически датчиком расстояния |
Device.LED_MANUAL | 1 | LED выключены; измерение расстояния продолжается |
Управление устройством
fun reboot() // вызывает отключение, затем автоматическое переподключение
Камера
Устройство имеет две камеры: Camera.Type.IR (инфракрасная) и Camera.Type.VL (видимый свет). Активная камера предоставляет кадры превью; камера инференса используется для обнаружения руки.
Выбор камеры
fun setActiveCamera(type: Camera.Type) // камера превью
fun setInferenceCamera(type: Camera.Type?) // камера детекции (null = как активная)
fun getActiveCamera(): Camera
fun getInferenceCamera(): Camera
fun getIrCamera(): Camera
fun getVlCamera(): Camera
Свойства камеры
fun getType(): Camera.Type
fun isLedOn(): Boolean
fun getFrameCount(): Int
Управление пользователями
Управление зарегистрированными пользователями. Это блокирующие вызовы — выполняйте в фоновом потоке.
getPersons()
Получает постраничный список зарегистрированных пользователей.
fun getPersons(page: Int, perPage: Int): PersonsPage
PersonsPage
| Поле | Тип | Описание |
|---|---|---|
data | List<Person> | Список пользователей на этой странице |
total | Int | Общее число зарегистрированных пользователей |
page | Int | Номер текущей страницы |
perPage | Int | Элементов на странице |
error | String? | Константа ErrorCodes или сообщение об ошибке (null при успехе) |
Person
| Поле | Тип | Описание |
|---|---|---|
id | Int | ID пользователя |
externalId | String? | Ваш внешний ID пользователя |
name | String? | Отображаемое имя |
metadata | String? | JSON-метаданные, заданные при регистрации |
createdAt | String? | Дата создания в формате ISO 8601 |
deletePerson()
Удаляет зарегистрированного пользователя по ID.
fun deletePerson(personId: Int): DeleteResult
DeleteResult
| Поле | Тип | Описание |
|---|---|---|
error | String? | Константа ErrorCodes или сообщение об ошибке (null при успехе) |
fun isSuccess(): Boolean // true если error == null
Обратные вызовы
AlaqanMiniListener
Получает события жизненного цикла SDK и подключения устройства. Все обратные вызовы доставляются в главном потоке. Устанавливается через setListener() (уровень Activity) или setGlobalListener() (постоянный).
interface AlaqanMiniListener {
fun onInitialized()
fun onDeviceConnected(device: Device)
fun onDeviceDisconnected(device: Device)
fun onError(code: String)
}
| Обратный вызов | Когда срабатывает |
|---|---|
onInitialized() | Активация SDK и загрузка моделей завершены успешно |
onDeviceConnected(device) | USB-устройство подключено и аутентифицировано, стриминг запущен |
onDeviceDisconnected(device) | USB-устройство отключено |
onError(code) | Произошла ошибка — code является константой ErrorCodes (см. Коды ошибок) |
IdentifyCallback
Получает события во время высокоуровневой операции идентификации, запущенной через startIdentify(). Все методы вызываются в главном потоке.
interface IdentifyCallback {
fun onPreviewFrame(result: FrameResult) // по умолчанию без действия, переопределите для превью
fun onGuidance(guidance: Guidance)
fun onResult(result: IdentifyResult)
}
| Обратный вызов | Когда срабатывает |
|---|---|
onPreviewFrame(result) | Каждый обработанный кадр камеры (по умолчанию без действия, переопределите для отображения превью) |
onGuidance(guidance) | Подсказка позиционирования изменилась — обновите ваш UI соответственно |
onResult(result) | Ровно один раз при завершении операции (успех, ошибка, таймаут или отмена) |
EnrollCallback
Получает события во время высокоуровневой операции регистрации, запущенной через startEnroll(). Все методы вызываются в главном потоке.
interface EnrollCallback {
fun onPreviewFrame(result: FrameResult) // по умолчанию без действия, переопределите для превью
fun onGuidance(guidance: Guidance)
fun onProgress(captured: Int, total: Int)
fun onResult(result: EnrollResult)
}
| Обратный вызов | Когда срабатывает |
|---|---|
onPreviewFrame(result) | Каждый обработанный кадр камеры (по умолчанию без действия, переопределите для отображения превью) |
onGuidance(guidance) | Подсказка позиционирования изменилась — обновите ваш UI соответственно |
onProgress(captured, total) | После каждого успешного захвата кадра — обновите индикатор прогресса |
onResult(result) | Ровно один раз при завершении операции (успех, ошибка, таймаут или отмена) |
FrameCallback
Обратный вызов, получающий каждый обработанный кадр камеры. Обработка кадров работает только при зарегистрированном обратном вызове. Установите null, когда кадры не нужны, для экономии CPU и батареи.
interface FrameCallback {
fun onFrameProcessed(result: FrameResult)
}
Регистрируется через sdk.setFrameCallback(callback). Полезен для отображения превью камеры в реальном времени вне операций идентификации/регистрации.
Пример
sdk.setFrameCallback { result ->
result.bitmap?.let { imageView.setImageBitmap(it) }
}
// Остановить, когда не нужен
sdk.setFrameCallback(null)
Модели данных
FrameResult
Доставляется через FrameCallback.onFrameProcessed() или onPreviewFrame() высокоуровневого обратного вызова для каждого кадра камеры.
| Поле | Тип | Описание |
|---|---|---|
jpegSize | Int | Размер JPEG-кадра в байтах |
width | Int | Ширина кадра в пикселях |
height | Int | Высота кадра в пикселях |
bitmap | Bitmap? | Декодированное изображение для отображения (общее — не вызывайте recycle) |
hands | HandDetection[]? | Обнаруженные руки в кадре |
moreHands | Boolean | True если обнаружено больше рук, чем допустимо |
inferenceMs | Float | Общее время инференса в миллисекундах |
ledOn | Boolean | Состояние LED при захвате кадра |
steady | Boolean | True если ограничивающий прямоугольник руки стабилен на последовательных детекциях |
HandDetection
| Поле | Тип | Описание |
|---|---|---|
confidence | Float | Уверенность детекции (0.0 - 1.0) |
x, y, w, h | Float | Ограничивающий прямоугольник в пикселях |
quality | Float | Оценка качества (0.0 - 1.0), или -1 если не вычислена |
Объекты результатов
Все объекты результатов следуют одному шаблону: сначала проверьте isSuccess(). При ошибке поле error содержит либо константу ErrorCodes (4-значная строка, например "5002"), либо человекочитаемое сообщение об ошибке.
| Класс результата | Поля | Используется в |
|---|---|---|
IdentifyResult | scanId, externalId, name, metadata, error | startIdentify() |
EnrollResult | scanId, error | startEnroll() |
DeleteResult | error | deletePerson() |
PersonsPage | data, total, page, perPage, error | getPersons() |
Коды ошибок
Коды ошибок — это 4-значные строковые константы, определённые в ErrorCodes. Они доставляются через onError(code: String) слушателя и как поле error в объектах результатов.
1xxx — Устройство / USB
| Код | Константа | Описание |
|---|---|---|
| 1001 | ErrorCodes.USB_PERMISSION_DENIED | USB-разрешение отклонено пользователем |
| 1002 | ErrorCodes.USB_NO_INTERFACE | USB-интерфейс не найден на устройстве |
| 1003 | ErrorCodes.USB_NO_ENDPOINTS | Отсутствуют необходимые USB-эндпоинты |
| 1004 | ErrorCodes.USB_OPEN_FAILED | Не удалось открыть USB-устройство |
| 1005 | ErrorCodes.USB_CLAIM_FAILED | Не удалось захватить USB-интерфейс |
| 1006 | ErrorCodes.USB_NO_SERIAL | Серийный номер устройства недоступен |
| 1007 | ErrorCodes.DEVICE_NOT_RESPONDING | Устройство подключено, но не отправляет кадры |
2xxx — Аутентификация
| Код | Константа | Описание |
|---|---|---|
| 2001 | ErrorCodes.AUTH_CHALLENGE_FAILED | Ошибка запроса challenge |
| 2002 | ErrorCodes.AUTH_INVALID_REPLY | Некорректный ответ challenge от устройства |
| 2003 | ErrorCodes.AUTH_COMPUTE_FAILED | Ошибка вычисления аутентификации |
| 2004 | ErrorCodes.AUTH_VERIFY_FAILED | Не удалось отправить команду верификации |
| 2005 | ErrorCodes.AUTH_REJECTED | Устройство отклонило аутентификацию |
3xxx — Стриминг
| Код | Константа | Описание |
|---|---|---|
| 3001 | ErrorCodes.STREAM_START_FAILED | Не удалось отправить команду запуска стрима |
| 3002 | ErrorCodes.STREAM_REJECTED | Устройство отклонило запуск стрима |
4xxx — SDK
| Код | Константа | Описание |
|---|---|---|
| 4001 | ErrorCodes.NATIVE_CREATE_FAILED | Ошибка создания нативного контекста |
| 4002 | ErrorCodes.MODEL_LOAD_FAILED | Ошибка загрузки моделей |
5xxx — Сеть
| Код | Константа | Описание |
|---|---|---|
| 5001 | ErrorCodes.API_KEY_MISSING | API-ключ не установлен |
| 5002 | ErrorCodes.SERVER_NETWORK_ERROR | Сетевая ошибка при запросе |
| 5003 | ErrorCodes.SERVER_INVALID_RESPONSE | Некорректный или неожиданный ответ |
| 5004 | ErrorCodes.SERVER_REJECTED | Запрос отклонён |
| 5005 | ErrorCodes.SERVER_TIMEOUT | Таймаут запроса |
6xxx — Операции
| Код | Константа | Описание |
|---|---|---|
| 6001 | ErrorCodes.OP_ALREADY_RUNNING | Другая операция уже выполняется |
| 6002 | ErrorCodes.OP_CANCELLED | Операция отменена через stopOperation() |
| 6003 | ErrorCodes.OP_TIMEOUT | Таймаут операции |
| 6004 | ErrorCodes.OP_DISCONNECTED | Устройство отключилось во время операции |
| 6005 | ErrorCodes.OP_NOT_INITIALIZED | SDK не инициализирован при запуске операции |
| 6006 | ErrorCodes.OP_NOT_CONNECTED | Устройство не подключено при запуске операции |
| 6007 | ErrorCodes.OP_INVALID_PARAMS | Некорректные параметры (например, null externalId для регистрации) |
Объекты результатов также могут содержать человекочитаемое сообщение об ошибке в поле error при отклонении запроса.
Лучшие практики
Всегда проверяйте isConnected() перед запуском операций регистрации или идентификации.
Высокоуровневый API (рекомендуется)
Для большинства интеграций используйте startIdentify() / startEnroll(). SDK управляет камерой, детекцией и биометрическим сопоставлением за вас:
// Идентификация — простейшая возможная интеграция
sdk.startIdentify(object : IdentifyCallback {
override fun onGuidance(guidance: Guidance) {
updateStatusUI(guidance)
}
override fun onResult(result: IdentifyResult) {
if (result.isSuccess) handleMatch(result)
else handleError(result.error)
}
})
// Отмена, если пользователь уходит со страницы
sdk.stopOperation()
Настройка камер
Для регистрации и идентификации показывайте VL-камеру, а детекцию запускайте на ИК-камере:
sdk.device.setActiveCamera(Camera.Type.VL) // пользователь видит видимый свет
sdk.device.setInferenceCamera(Camera.Type.IR) // детекция на инфракрасной
Потоки
getPersons()иdeletePerson()— блокирующие вызовы, всегда выполняйте в фоновом потоке- Все методы слушателя и обратных вызовов доставляются в главном потоке — безопасно обновлять UI напрямую
Обработка ошибок
override fun onError(code: String) {
when {
code.startsWith("1") -> handleDeviceError(code)
code.startsWith("2") -> handleAuthError(code)
code.startsWith("5") -> handleNetworkError(code)
code == ErrorCodes.DEVICE_NOT_RESPONDING -> {
// Устройство перестало отправлять кадры — автоматически отключится
}
else -> Log.e("Alaqan", "Error: $code")
}
}
Устранение неполадок
Устройство не обнаружено
Симптомы: onDeviceConnected() не вызывается
- Проверьте подключение Alaqan Mini через USB-C
- Убедитесь, что USB OTG включён на Android-устройстве
- Проверьте
device_filter.xmlна правильность VID/PID - Попробуйте другой USB-кабель
Ошибка разрешения USB
Симптомы: onError() с кодом ErrorCodes.USB_PERMISSION_DENIED ("1001")
- Убедитесь, что диалог разрешения USB отображается и принимается
- Проверьте правильность обработки USB-интентов в Activity
- Очистите данные приложения и попробуйте снова
Ошибка инициализации SDK
Симптомы: onError() с кодом ErrorCodes.API_KEY_MISSING ("5001") или ErrorCodes.SERVER_NETWORK_ERROR ("5002")
- Проверьте правильность API-ключа и его срок действия
- Убедитесь в наличии активного интернет-соединения
- Проверьте logcat для подробных сообщений об ошибках
Низкое качество детекции
Симптомы: quality не достигает порога
- Проверьте расстояние до руки (
getDistance()) - Направляйте пользователя центрировать ладонь в кадре
- Убедитесь, что LED включён (
camera.isLedOn()) - Избегайте прямого солнечного света на сканер
- Снимите защитную плёнку со стекла сканера
Устройство не отвечает
Симптомы: onError() с кодом ErrorCodes.DEVICE_NOT_RESPONDING ("1007")
- Устройство перестало отправлять кадры — SDK автоматически отключится
- Попробуйте
device.reboot()для перезагрузки устройства - Проверьте подключение USB-кабеля
Пример реализации
Свяжитесь с поддержкой Alaqan для получения полного примера проекта с исходным кодом.
Поддержка
Техническая поддержка
support@alaqan.com
Коммерческие вопросы
sales@alaqan.com
Укажите: код ошибки, шаги воспроизведения, серийный номер и версию прошивки устройства, версию SDK.
