React Native module that supports for SUNMI mobile printer devices.
I validate it with GMS enable and developable SUNMI V2 PRO and SUNMI V2s as follows. Though I do not have other devices, users report to work with V1s and V2.
| Android | SUNMI OS | firmware | storage | memory | NFC | |
|---|---|---|---|---|---|---|
| SUNMI V2 PRO | 7.1 | 3.6.23 | 754 | 16 GB | 2 GB | enable |
| SUNMI V2 PRO (foodpanda) | 7.1 | 1.0.33 | 138 | 8 GB | 1 GB | disable |
| SUNMI V2s | 11 | 3.0.11 | 242 | 32 GB | 3 GB | enable |
npm install @mitsuharu/react-native-sunmi-printer-libraryor
yarn add @mitsuharu/react-native-sunmi-printer-libraryThis package contains custom Android native code, so it does not work in Expo Go. Install it in an Expo project that uses a development build:
yarn expo install expo-dev-client @mitsuharu/react-native-sunmi-printer-libraryRegenerate the Android project after installing or updating the package, then compile and install it locally. An EAS Build or Expo account is not required:
yarn expo prebuild --platform android --clean
yarn expo run:android --deviceSee Expo's development build documentation for details. This library supports Android only.
See the React Native example in example/ or the Expo example in
example-expo/ for details.
import * as SunmiPrinterLibrary from '@mitsuharu/react-native-sunmi-printer-library'try {
await SunmiPrinterLibrary.prepare()
} catch (error: any) {
console.warn("This device is not supported.")
}await SunmiPrinterLibrary.printText('Hello World')or
SunmiPrinterLibrary.printText('Hello World')Warning
Printing without await is faster, but may be interrupted by other printing. When it use without await, it is better to use with Transaction.
await SunmiPrinterLibrary.setAlignment('center')
await SunmiPrinterLibrary.setTextStyle('bold', true)
await SunmiPrinterLibrary.setParagraphStyle('textRightSpacing', 5)
await SunmiPrinterLibrary.setFontSize(32)
await SunmiPrinterLibrary.printText('Hello World')const base64 = 'data:image/png;base64,iVBORw0KGgoAAAA...'
await SunmiPrinterLibrary.printImage(base64, 384, 'binary')
await SunmiPrinterLibrary.printImage(base64, 384, 'grayscale')await SunmiPrinterLibrary.printQRCode('Hello World', 8, 'middle')const result = await SunmiPrinterLibrary.scan()or
SunmiPrinterLibrary.scan()useEffect(() => {
DeviceEventEmitter.addListener(
SunmiPrinterLibrary.EventType.onScanSuccess,
(message) => {
console.log(`[onScanSuccess] ${message}`)
})
DeviceEventEmitter.addListener(
SunmiPrinterLibrary.EventType.onScanFailed,
(message) => {
console.log(`[onScanFailed] ${message}`)
})
return () => {
DeviceEventEmitter.removeAllListeners(SunmiPrinterLibrary.EventType.onScanSuccess)
DeviceEventEmitter.removeAllListeners(SunmiPrinterLibrary.EventType.onScanFailed)
}
}, [])await SunmiPrinterLibrary.enterPrinterBuffer(true)
SunmiPrinterLibrary.printText('Transaction Test 0')
await SunmiPrinterLibrary.commitPrinterBuffer()
SunmiPrinterLibrary.printText('Transaction Test 1')
SunmiPrinterLibrary.printText('Transaction Test 2')
SunmiPrinterLibrary.printText('Transaction Test 3')
SunmiPrinterLibrary.lineWrap(4)
await SunmiPrinterLibrary.exitPrinterBuffer(true)// use to convert data to Base 64
import { Buffer } from 'buffer'
// ESC/POS command
// see: https://developer.sunmi.com/docs/en-US/index
const boldOn = new Uint8Array([0x1B, 0x45, 0x01])
const boldOnBase64 = Buffer.from(boldOn).toString('base64')
await SunmiPrinterLibrary.sendRAWData(boldOnBase64)
await SunmiPrinterLibrary.printText('Bold is ON')
const boldOff = new Uint8Array([0x1B, 0x45, 0x00])
const boldOffBase64= Buffer.from(boldOff).toString('base64')
await SunmiPrinterLibrary.sendRAWData(boldOffBase64)
await SunmiPrinterLibrary.printText('Bold is OFF')- Cash Drawer API
- Black Mark Print API
See the contributing guide to learn how to contribute to the repository and the development workflow.
yarn
yarn example androidexample/is the bare React Native example and uses React Native 0.87.example-expo/is the Expo example and uses Expo SDK 57 with React Native 0.86.- Both examples reuse the same printer operation screen.
The Expo example uses local Continuous Native Generation. It does not use EAS Build or any other cloud build service. Generate a fresh Android project with Expo Prebuild and build the APK with the generated Gradle Wrapper:
yarn example:expo build:androidThe generated example-expo/android/ directory is intentionally ignored. Do
not edit it directly; update the Expo app configuration or a config plugin and
run Prebuild again.
The Expo SDK 57 development launcher uses java.time.Duration during startup.
Without compatibility handling, the APK cannot resolve this API below Android
8.0 and crashes at startup on Android 7.1 devices such as the SUNMI V2 PRO:
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Duration;
The Expo example registers
example-expo/plugins/withAndroidCoreLibraryDesugaring.js as a config plugin
in app.json. During Prebuild, it enables core library desugaring and adds
desugar_jdk_libs, allowing the development build to start on Android 7.x.
Do not add this configuration directly to the generated
example-expo/android/app/build.gradle; expo prebuild --clean will replace
that file. Keep native configuration in the config plugin instead. See the
Expo config plugin documentation
and Android Java API desugaring documentation
for more information.
To start the Expo development server for an installed development build:
yarn example:expo start- Create Pull Requests against the
mainbranch. - I recommend that add or fix test, readme and example.
Maintainers only: update the version in package.json in a pull request against
main. After the pull request is merged and CI succeeds, run the Release to
npm workflow from the Actions tab and enter that exact version. The workflow
builds and verifies the package, creates a matching tag and GitHub release, and
publishes the package to npm. Merging into main never publishes a package.
MIT
Made with create-react-native-library