ra-qrcode-util-cordova
v1.0.6
Published
RemoteApps QR/barcode scan + generate utility for Cordova. Android: CameraX + ML Kit. iOS: AVFoundation. Includes a visible close button on the scan screen. Scan API is compatible with phonegap-plugin-barcodescanner; generation API is compatible with the
Maintainers
Readme
ra-qrcode-util-cordova
A from-scratch replacement for the old, unmaintained phonegap-plugin-barcodescanner — and a bundled QR code generator, so you don't need a separate qrcode npm dependency either. Two-in-one.
Install
# 1. Remove the old plugin
cordova plugin remove phonegap-plugin-barcodescanner
# 2. Add this one (from local folder, or publish it to npm/git first)
cordova plugin add /path/to/ra-qrcode-util-cordovacordova plugin add also registers the package in your app's package.json / node_modules, which is what makes the TypeScript import below resolve. If the import can't be found, run npm install /path/to/ra-qrcode-util-cordova once from the app root.
Usage — Ionic / Angular (TypeScript)
Import QRUtil from ra-qrcode-util-cordova/ngx and inject it. It is providedIn: 'root', so there is no module, providers entry, or declare var cordova needed — no (window as any).cordova casts anywhere in your code.
import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
import { QRUtil, QRScanResult } from 'ra-qrcode-util-cordova/ngx';
@Component({ /* ... */ })
export class ScanPage {
qrDataUrl = '';
constructor(private qrUtil: QRUtil, private platform: Platform) {}
async scan(): Promise<void> {
await this.platform.ready(); // plugin exists only after deviceready
const result: QRScanResult = await this.qrUtil.scan({
prompt: 'Point your camera at the QR code',
showTorchButton: true,
formats: 'QR_CODE'
});
if (result.cancelled) {
console.log('User closed the scanner.');
} else {
console.log(`Scanned: ${result.text} (${result.format})`);
}
}
async generate(): Promise<void> {
await this.platform.ready();
// data URL you can bind straight to <img [src]="qrDataUrl">
this.qrDataUrl = await this.qrUtil.toDataURL('https://example.com', {
errorCorrectionLevel: 'H',
width: 256
});
}
}All methods return Promises and reject (never throw synchronously) if the plugin isn't available yet — so call them after platform.ready() (or the deviceready event).
QRUtil API
| Method | Returns | Notes |
|---|---|---|
| scan(options?: QRScanOptions) | Promise<QRScanResult> | Opens the native scan screen |
| checkPermission() | Promise<QRPermissionResult> | { granted: boolean }, no prompt |
| toDataURL(text, options?) | Promise<string> | PNG data URL for <img> |
| toCanvas(canvas, text, options?) | Promise<HTMLCanvasElement> | Draws into your canvas element |
| toString(text, options?) | Promise<string> | SVG/terminal string, per options |
QRScanOptions, QRScanResult, QRPermissionResult, and QRCodeOptions are all exported from ra-qrcode-util-cordova/ngx too.
You can also use the class without Angular DI — new QRUtil() works, the constructor takes no arguments.
How the ngx wrapper ships (important if you edit it)
ra-qrcode-util-cordova/ngx resolves (via ngx/package.json) to precompiled files:
ngx/index.js— plain ES-module JS with the Ivy injectable definition (ɵprov) attached statically, so it works in JIT and AOT production builds without@angular/compiler.ngx/index.d.ts— the TypeScript types.
Do not point the entry at raw .ts: Angular CLI doesn't compile TypeScript out of node_modules (the import silently becomes undefined), and a runtime @Injectable decorator needs the JIT compiler, which AOT builds don't include (injection then breaks the page). The readable source lives in ngx/src/QRUtil.ts — if you change it, mirror the change in index.js and index.d.ts.
Usage — plain JavaScript (non-Angular)
The Cordova modules are also available globally after deviceready, API-compatible with the old plugins:
cordova.plugins.barcodeScanner.scan(
function (result) {
if (result.cancelled) {
console.log('User closed the scanner.');
} else {
console.log('Scanned: ' + result.text + ' (' + result.format + ')');
}
},
function (error) {
console.error('Scan error: ' + error);
},
{
prompt: 'Point your camera at the QR code',
showTorchButton: true, // Android: shows/hides the flashlight button
formats: 'QR_CODE' // comma-separated: QR_CODE,EAN_13,CODE_128,...
}
);
// generation — same signatures as the npm 'qrcode' package
cordova.plugins.qrGenerator.toDataURL('some text', { errorCorrectionLevel: 'H' }, function (err, url) { /* ... */ });
const url = await cordova.plugins.qrGenerator.toDataURL('some text'); // promise styleNo JS changes needed in your app if you were only using .scan() from the old plugin.
Scan options
| Option | Type | Default | Notes |
|---------------------|---------|---------------------|----------------------------------------------------|
| prompt | String | "Align the QR code within the frame" | Text shown under the scan frame |
| showTorchButton | Boolean | true | Android only; iOS torch toggle can be added the same way if you need it |
| formats | String | "QR_CODE" | Comma-separated list of formats to detect |
Scan result
{ text: "https://example.com", format: "QR_CODE", cancelled: false }If the user taps the close button, presses back, or denies camera permission after previously allowing it, you get:
{ text: "", format: "", cancelled: true }Generator options
toCanvas(canvasEl, text, options, callback) and toString(text, options, callback) are exposed the same way as toDataURL, both callback- and promise-style. Full option list (errorCorrectionLevel, margin, width, color.dark, color.light, etc.) is the same as documented on the qrcode npm page, since it's literally that package running under the hood.
Scanning
- Android: CameraX + ML Kit on-device barcode scanning (no more bundled ZXing
.aar, no morecom.android.supportv4). Fully AndroidX. The scan screen has a visible close (X) button in the top-right corner at all times, plus a torch toggle, plus back-button support — this is the piece the old plugin was missing. - iOS: AVFoundation-based scanner, also with its own close button, same JS result shape.
- JS API is unchanged — it still attaches to
cordova.plugins.barcodeScanner, so existing app code that calls.scan(success, error, options)keeps working with no changes.
Generating
This plugin also vendors the real, MIT-licensed qrcode npm package (browserified, pure JS/canvas — no native code, works identically on Android/iOS/browser), exposed as cordova.plugins.qrGenerator.
Why a rewrite instead of patching the old plugin
The old plugin (last real Android update years ago) bundles a barcodescanner-release-2.1.5.aar (ZXing) and depends on com.android.support:support-v4, which breaks on any recent AndroidX / target-SDK-34+ project, and its Android CaptureActivity has no close button in its UI — you can only cancel via the hardware back button. This plugin drops that dependency chain entirely.
Requirements
cordova-android >= 10.0.0(AndroidX)cordova-ioswith a recent Xcode / iOS deployment target- Camera permission is requested at runtime automatically before the scanner opens.
Folder layout
plugin.xml
package.json <- main/types point at ngx/index.js / index.d.ts
ngx/package.json <- resolves 'ra-qrcode-util-cordova/ngx'
ngx/index.js <- precompiled Angular wrapper (JIT + AOT safe)
ngx/index.d.ts <- TypeScript types for the wrapper
ngx/src/QRUtil.ts <- readable source for the wrapper (not shipped as entry)
www/qrScanner.js <- scan JS bridge (kept API-compatible)
www/qrGenerator.js <- generator JS wrapper (npm 'qrcode' API)
www/qrcode.bundle.js <- vendored 'qrcode' npm package (MIT), browserified
src/android/.../QRScannerPlugin.java <- Cordova entry point, permission handling
src/android/.../ScannerActivity.java <- CameraX + ML Kit scan screen w/ close button
src/android/res/... <- layout, icons, styles for the scan screen
src/ios/QRScannerPlugin.h / .m <- AVFoundation scan screen w/ close buttonNotes / next steps for your project
- Double check your
config.xml/build.gradledon't still reference the old plugin's gradle file or the ZXing.aar. - You can now remove your separate
qrcodenpm dependency from your web/app bundle if you switch your generation calls toqrUtil.toDataURL(...)— one less thing to bundle. - Test scanning on a real Android device — camera + ML Kit behave differently on emulators without a working camera. Generation works fine in any WebView or browser, including emulators, since it's pure JS/canvas.
- If your app also used the old plugin's native
encode()(which opened a full-screen barcode display via ZXing'sEncodeActivity), that's superseded bytoDataURL— you now get a data URL you can put directly in an<img>or canvas instead of a separate screen. - After updating the plugin in an app, refresh the installed copy:
cordova plugin remove ra-qrcode-util-cordova && cordova plugin add /path/to/ra-qrcode-util-cordova, and restartionic serve/rebuild so the bundler picks up the newnode_modulesentry.
