The plugin's on-device proof (Mob.Plugin.SelfTest), run by
mix mob.selftest and mob_ci for every activated plugin.
The scanner's only feature, MobScanner.scan/2, opens a full-screen camera
view, so the test never calls it. It asks the side-effect-free
:mob_scanner_nif.scanner_available/0 instead: no camera input is opened,
no permission is requested, nothing is presented or launched.
- iOS — the Objective-C NIF runs the same
AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideolookupscan/2does before presenting. Any answer proves the NIF is linked and registered viaERL_NIF_INIT.:available(a capture device exists) is a pass.:no_camerais{:skip, :needs_hardware}: the iOS Simulator has no capture device, so this is the expected result there, and a scan on it would end in{:scan, :not_available}. - Android — the zig NIF calls
MobScannerBridge.scanner_available()through the method ID cached bynativeRegister, so any answer proves the Kotlin bridge is registered. The bridge resolves the explicitMobScannerActivityIntent against the host'sPackageManager(the same lookup the scan launch does) and then checksFEATURE_CAMERA_ANY.:availableis a pass: the bootstrap handed the bridge an Activity, the manifest snippet declared the scanner Activity, and a camera exists (a default emulator emulates one, so a pass is expected there).:no_camerais{:skip, :needs_hardware}, reported only after the Activity check passed. - Failures: the host stub's
nif_not_loaded;{:error, :bridge_not_registered}(register()never ran or the method-ID lookup failed);{:error, :no_activity}(the bootstrap never calledsetActivity, a scan would only ever answer:cancelled);{:error, :activity_not_declared}(the manifest snippet was not spliced, a scan would answer:not_available);{:error, :query_failed}(the PackageManager query threw);{:error, :no_jni_env}(the NIF could not attach to the JVM); anything else.