Petnow LogoPetnow

SDK v1.4 → v1.5 Migration

What changes when upgrading a v1.4.x integration to v1.5.0 — an Android rebuild, one breaking removal, and a changed default.

v1.5.0 moves dog-nose quality assessment onto the device, removes the realtime server quality path introduced in 1.4.2, retires difficulty levels, adds x86_64 to the Android AAR, and adds an environment selector to LicenseInfo.

Three things need your attention before you ship: Android apps must be rebuilt, the server-quality surface is gone outright, and enableFakeDetection now defaults to true. Everything else is source-compatible.

Android: rebuild the app, do not swap the AAR

1.5 is not binary-compatible on Android. DetectionConfiguration gained inferenceTier and LicenseInfo gained environment in their primary constructors, and a Kotlin data class carries its parameter list in the JVM signatures it generates — the constructor, the synthetic default-argument constructor, copy and copy$default all changed shape.

An app compiled against 1.4.5 whose AAR is replaced with 1.5, without the app itself being rebuilt, installs and starts as usual and then throws NoSuchMethodError the first time it constructs or copies a configuration. Nothing about that shows up at build time.

Rebuild the app against 1.5. There is nothing to change in its source.

Coming from v1.3.x? Do the v1.3 → v1.4 Migration first (it has real API changes), then return here. On Android, versions 1.4.1–1.4.4 were never published, so you upgrade from 1.4.0 or 1.4.5 directly to 1.5.0.

Version bump

Platformv1.4.xv1.5.0
Androidio.petnow:ui:1.4.5io.petnow:ui:1.5.0
iOS (SwiftPM registry)petnow.ui 1.4.5petnow.ui 1.5.0
React Native@petify/react-native-camera-ui@1.4.5@petify/react-native-camera-ui@1.5.0

Package size grows because the on-device quality model ships inside the SDK: the Android AAR is about 74 MB with both ABIs (the 12 MB model is stored once; App Bundles carry it once), and the iOS framework grows by about 12 MB.


Breaking: the realtime server-quality surface is gone

If you took part in the 1.4.2–1.4.5 realtime server quality pilot, this is a compile error, not a cleanup you can defer. There is no deprecated no-op left behind.

PlatformRemove
React Nativethe onRealtimeServerIqaDiagnostic prop and every use of the RealtimeServerIqaDiagnosticEvent / RealtimeServerIqaFeatureScores / RealtimeServerIqaDiagnosticPhase types
AndroidPETNOW_SERVER_IQA_* BuildConfig fields / Gradle properties
iOSPetnowServerIqa* keys in Info.plist, and any setRealtimeServerIqaDiagnosticHandler call

Delete the prop and the types — nothing replaces them. The callback reported a server judgement that no longer happens, and dog quality scores are not part of the public API. Integrations that never enabled the pilot have nothing to do here.

Capture no longer waits on a server call. License validation runs in initializeCamera(), once per API key per process; an unreachable server at that moment fails with InvalidLicense. After that, detection and the returned files are local, and the usage metrics the SDK reports in the background never block a capture or make one fail. If your app handled "session stuck at detected" or server-quality timeouts specially, that handling can go. → How capture quality is decided


Changed default: enableFakeDetection is true

DetectionConfiguration.enableFakeDetection defaults to true on every surface (iOS, Android, React Native). In 1.4.5 an integrator who never set the flag got no spoof detection; on 1.5 the same code gets it. Check your own call sites before upgrading — a flow tested against photographs of pets will start failing.

Passing false turns spoof detection off for that session, which is how you evaluate the SDK against photographs instead of live animals.

// 1.4.5 — off unless you asked for it
DetectionConfiguration(species = PetSpecies.DOG, purpose = DetectionPurpose.PET_PROFILE_REGISTRATION)

// 1.5.0 — the same call now has spoof detection on

// 1.5.0 — testing against photographs
DetectionConfiguration(
    species = PetSpecies.DOG,
    purpose = DetectionPurpose.PET_PROFILE_REGISTRATION,
    enableFakeDetection = false, 
)

New: LicenseInfo.environment

A staging-console API key is only valid against the staging backend, and vice versa. v1.5 lets the host name the backend its key belongs to, restoring the capability v1.3.x had as isDebugMode and v1.4 removed.

// Android
LicenseInfo(apiKey = "YOUR_API_KEY", environment = PetnowEnvironment.STAGING)
// iOS
LicenseInfo(apiKey: "YOUR_API_KEY", environment: .staging)
// React Native
const camera = usePetnowCamera({ apiKey, environment: 'staging' });

Omitting it keeps the environment the SDK was built for, which is production for every published build — nothing changes for an app that does not set it. It is a named environment rather than a boolean on purpose: do not wire it to your own DEBUG / __DEV__ flag, because a release build that accidentally selected staging would send real captures to a backend where the pets are not registered.


New: one API key per process

A second, different API key in the same process is now refused instead of silently replacing the first. The console can issue several keys; one process must pick one of them and keep it.

PlatformError
AndroidPetnowUIError.MultipleApiKeys from initializeCamera()
iOSPetnowUIError.multipleApiKeys
React Nativegive usePetnowCamera one stable apiKey; switching keys needs an app restart

The first key keeps working. Re-initializing with the same key is unaffected.


Deprecated: difficultyMode

Still accepted, still ignored, and it stays that way through 1.5 — it goes in the next major release. Remove the argument at your convenience to silence the deprecation warning.

// v1.4.x
DetectionConfiguration(
    species = PetSpecies.DOG,
    purpose = DetectionPurpose.PET_PROFILE_REGISTRATION,
    enableFakeDetection = true,
    difficultyMode = DifficultyMode.NORMAL,   // deprecated in 1.5.0 — ignored
)

// v1.5.0
DetectionConfiguration(
    species = PetSpecies.DOG,
    purpose = DetectionPurpose.PET_PROFILE_REGISTRATION,
    enableFakeDetection = true,
)

The same applies to iOS DetectionConfiguration(difficultyMode:) and the React Native <CameraView difficultyMode> prop.

Why: dog-nose capture quality is judged by the on-device model, and difficulty levels no longer take part in that judgement. → How capture quality is decided


Android

1. Dependencies — a single self-contained AAR

dependencies {
    implementation("io.petnow:ui:1.5.0")
    // remove if still present:
    // implementation("io.petnow:api-client:...")
    // implementation(files("AndroidCameraFramework-release.aar"))
}

io.petnow:ui bundles everything it needs. The api-client module and the AndroidCameraFramework artifact are not published for 1.4/1.5 and must not be declared. Server calls belong on your app server → Server API.

2. ABIs — x86_64 added, armeabi-v7a not shipped

The AAR contains arm64-v8a and x86_64. Emulator-based tests now run the SDK (GPU acceleration on an emulator depends on its GL/OpenCL support and falls back to CPU). If your app declares abiFilters, make sure armeabi-v7a-only builds are not expected to include the SDK.

3. Optional: inferenceTier and performanceStats

  • DetectionConfiguration.inferenceTier (AUTO default / CPU / GPU) selects the detector path. AUTO picks the path that suits the device, and falls back if that path is unavailable. It is read once, when the process creates its first detector engine, and fixed from then on — set it on the first initializeCamera() or restart the app to change it. Force a tier only when support asks you to.
  • CameraController.performanceStats (StateFlow<CameraPerformanceStats>) and PetnowCameraFragment.performanceStats() report camera init time, first-frame time, fps, detector ms and the chosen tier — useful in a diagnostics screen or a support report. → Basic Usage

4. Legacy Fragment path — result lists per species

If you still use PetnowCameraFragment with the V1 DetectionCaptureResult: for a dog both noseImageFiles (biometric set → upload as fingerprints) and faceImageFiles (appearance set) are populated; for a cat only faceImageFiles is populated and it is the biometric set. This is unchanged from 1.4 but was previously undocumented.


iOS

  • CameraController.performanceStats (@Published CameraPerformanceStats) is new; nothing to change.
  • CameraOpticsPolicy and the adaptive rear-camera mode are gone — they existed only for the server-quality path. Rear lens selection behaves as in 1.4.3.
  • setRealtimeServerIqaDiagnosticHandler and the RealtimeServerIqa* types are gone (see Breaking above).

React Native

  • onRealtimeServerIqaDiagnostic and the RealtimeServerIqa* types are removed (see Breaking above); difficultyMode is deprecated and never reaches native. Everything else in usePetnowCamera / <CameraView> is unchanged.
  • Supported range is unchanged: React Native 0.75 or newer, tested through 0.86.x, with the New Architecture enabled.
  • A new example app is available for 1.5.0; contact support@petnow.io for it.

Migration checklist

  • Bump the package version (io.petnow:ui:1.5.0 / petnow.ui 1.5.0 / @petify/react-native-camera-ui@1.5.0)
  • Android: rebuild the app. Do not ship 1.5's AAR inside a binary compiled against 1.4.5
  • Pilot integrations only: delete onRealtimeServerIqaDiagnostic, the RealtimeServerIqa* types, and the PETNOW_SERVER_IQA_* / Info.plist / .env configuration
  • Review every DetectionConfiguration call site for the new enableFakeDetection default
  • Confirm one API key per process, and that a staging key is paired with environment = staging
  • Remove difficultyMode arguments (optional, silences the deprecation warning)
  • Android: remove api-client / AndroidCameraFramework declarations if present
  • Re-run your capture flow on a device; nothing in the callbacks or result files changed

On this page