diff --git a/CHANGELOG.md b/CHANGELOG.md index c926dcfb..da423a86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.2.5 + +* Upgrade Android build system to Gradle 8.14 and AGP 8.11.1 +* Migrate Android build files from Groovy to Kotlin DSL (build.gradle.kts) +* Update Kotlin version to 2.2.20 and target Java 17 +* Migrate example app Android build files to Kotlin DSL with new Flutter Gradle integration + ## 1.2.4 * Relax rxdart version to allow library usage in FlutterFlow app builder diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index bede56fa..00000000 --- a/android/build.gradle +++ /dev/null @@ -1,53 +0,0 @@ -group 'com.sersoluciones.flutter_pos_printer_platform' -version '1.0-SNAPSHOT' - -buildscript { - ext.kotlin_version = '1.6.20' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -rootProject.allprojects { - repositories { - google() - mavenCentral() - } -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - compileSdkVersion 31 - - namespace 'com.sersoluciones.flutter_pos_printer_platform' - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - minSdkVersion 21 - targetSdkVersion 31 - } -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 00000000..0cf57dd1 --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,65 @@ +group = "com.sersoluciones.flutter_pos_printer_platform" +version = "1.0-SNAPSHOT" + +buildscript { + val kotlinVersion = "2.2.20" + repositories { + google() + mavenCentral() + } + + dependencies { + classpath("com.android.tools.build:gradle:8.11.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +plugins { + id("com.android.library") + id("kotlin-android") +} + +android { + namespace = "com.sersoluciones.flutter_pos_printer_platform" + + compileSdk = 36 + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + sourceSets { + getByName("main") { + java.srcDirs("src/main/kotlin") + } + getByName("test") { + java.srcDirs("src/test/kotlin") + } + } + + defaultConfig { + minSdk = 24 + } + + java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } + } +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-stdlib:2.0.21") +} diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index b1159fc5..c6406bc3 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/android/settings.gradle b/android/settings.gradle deleted file mode 100644 index 057778de..00000000 --- a/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'flutter_pos_printer_platform' diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 00000000..9e78df2d --- /dev/null +++ b/android/settings.gradle.kts @@ -0,0 +1,23 @@ +import org.gradle.api.initialization.resolve.RepositoriesMode + +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } + plugins { + id("com.android.library") version "8.11.1" + id("org.jetbrains.kotlin.android") version "2.2.20" + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "flutter_pos_printer_platform" diff --git a/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/adapter/USBPrinterAdapter.kt b/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/adapter/USBPrinterAdapter.kt index e96576d9..01e8f0d2 100644 --- a/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/adapter/USBPrinterAdapter.kt +++ b/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/adapter/USBPrinterAdapter.kt @@ -40,27 +40,42 @@ class USBPrinterAdapter private constructor() { private val mUsbDeviceReceiver: BroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - val action = intent.action - if ((ACTION_USB_PERMISSION == action)) { + override fun onReceive(context: Context, intent: Intent?) { + if (intent == null) return + + val action = intent.action ?: return + + if (ACTION_USB_PERMISSION == action) { synchronized(this) { val usbDevice: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) - if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { + if (usbDevice == null) { + Log.e(LOG_TAG, "USB_PERMISSION received but EXTRA_DEVICE was null") + return + } + + val granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) + if (granted) { Log.i( LOG_TAG, - "Success get permission for device " + usbDevice!!.deviceId + ", vendor_id: " + usbDevice.vendorId + " product_id: " + usbDevice.productId + "Success get permission for device ${usbDevice.deviceId}, " + + "vendor_id: ${usbDevice.vendorId}, product_id: ${usbDevice.productId}" ) mUsbDevice = usbDevice } else { Toast.makeText( - context, mContext?.getString(R.string.user_refuse_perm) + ": ${usbDevice!!.deviceName}", + context, + "${mContext?.getString(R.string.user_refuse_perm)}: ${usbDevice.deviceName ?: "Unknown"}", Toast.LENGTH_LONG ).show() } } - } else if ((UsbManager.ACTION_USB_DEVICE_DETACHED == action)) { + } else if (UsbManager.ACTION_USB_DEVICE_DETACHED == action) { if (mUsbDevice != null) { - Toast.makeText(context, mContext?.getString(R.string.device_off), Toast.LENGTH_LONG).show() + Toast.makeText( + context, + mContext?.getString(R.string.device_off) ?: "Device disconnected", + Toast.LENGTH_LONG + ).show() closeConnectionIfExists() } } diff --git a/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/usb/USBPrinterService.kt b/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/usb/USBPrinterService.kt index 3c2fa21a..68ada09a 100644 --- a/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/usb/USBPrinterService.kt +++ b/android/src/main/kotlin/com/sersoluciones/flutter_pos_printer_platform/usb/USBPrinterService.kt @@ -31,38 +31,52 @@ class USBPrinterService private constructor(private var mHandler: Handler?) { private val mUsbDeviceReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { - val action = intent.action - if ((ACTION_USB_PERMISSION == action)) { - synchronized(this) { - val usbDevice: UsbDevice? = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) - if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { + val action = intent.action ?: return + + when (action) { + ACTION_USB_PERMISSION -> synchronized(this) { + val usbDevice: UsbDevice? = + intent.getParcelableExtra(UsbManager.EXTRA_DEVICE) + if (usbDevice == null) { + Log.e(LOG_TAG, "USB_PERMISSION geldi ama EXTRA_DEVICE null") + state = STATE_USB_NONE + mHandler?.obtainMessage(STATE_USB_NONE)?.sendToTarget() + return + } + + val granted = intent.getBooleanExtra( + UsbManager.EXTRA_PERMISSION_GRANTED, false + ) + if (granted) { Log.i( LOG_TAG, - "Success get permission for device ${usbDevice?.deviceId}, vendor_id: ${usbDevice?.vendorId} product_id: ${usbDevice?.productId}" + "Permission granted for device id=${usbDevice.deviceId}, " + + "vendor=${usbDevice.vendorId}, product=${usbDevice.productId}" ) mUsbDevice = usbDevice state = STATE_USB_CONNECTED mHandler?.obtainMessage(STATE_USB_CONNECTED)?.sendToTarget() } else { - Toast.makeText(context, mContext?.getString(R.string.user_refuse_perm) + ": ${usbDevice!!.deviceName}", Toast.LENGTH_LONG).show() + val name = usbDevice.deviceName ?: "Unknown USB Device" + val title = mContext?.getString(R.string.user_refuse_perm) + ?: "Permission denied" + Toast.makeText(context, "$title: $name", Toast.LENGTH_LONG).show() state = STATE_USB_NONE mHandler?.obtainMessage(STATE_USB_NONE)?.sendToTarget() } } - } else if ((UsbManager.ACTION_USB_DEVICE_DETACHED == action)) { - - if (mUsbDevice != null) { - Toast.makeText(context, mContext?.getString(R.string.device_off), Toast.LENGTH_LONG).show() - closeConnectionIfExists() - state = STATE_USB_NONE - mHandler?.obtainMessage(STATE_USB_NONE)?.sendToTarget() + + UsbManager.ACTION_USB_DEVICE_DETACHED -> { + if (mUsbDevice != null) { + val msg = mContext?.getString(R.string.device_off) + ?: "Device disconnected" + Toast.makeText(context, msg, Toast.LENGTH_LONG).show() + closeConnectionIfExists() + mUsbDevice = null + state = STATE_USB_NONE + mHandler?.obtainMessage(STATE_USB_NONE)?.sendToTarget() + } } - - } else if ((UsbManager.ACTION_USB_DEVICE_ATTACHED == action)) { -// if (mUsbDevice != null) { -// Toast.makeText(context, "USB device has been turned off", Toast.LENGTH_LONG).show() -// closeConnectionIfExists() -// } } } } diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle deleted file mode 100644 index 9ad963aa..00000000 --- a/example/android/app/build.gradle +++ /dev/null @@ -1,68 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion flutter.compileSdkVersion - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - kotlinOptions { - jvmTarget = '1.8' - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.sersoluciones.flutter_pos_printer_platform_example" - minSdkVersion 21 - targetSdkVersion 31 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/example/android/app/build.gradle.kts b/example/android/app/build.gradle.kts new file mode 100644 index 00000000..caf6a0db --- /dev/null +++ b/example/android/app/build.gradle.kts @@ -0,0 +1,51 @@ +plugins { + id("com.android.application") + id("kotlin-android") + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.sersoluciones.flutter_pos_printer_platform_example" + + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + sourceSets { + getByName("main") { + java.srcDirs("src/main/kotlin") + } + } + + defaultConfig { + applicationId = "com.sersoluciones.flutter_pos_printer_platform_example" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + signingConfig = signingConfigs.getByName("debug") + } + } + + java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) + } + } +} + +flutter { + source = "../.." +} diff --git a/example/android/build.gradle b/example/android/build.gradle deleted file mode 100644 index 83ae2200..00000000 --- a/example/android/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - ext.kotlin_version = '1.6.10' - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.1.2' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/example/android/build.gradle.kts b/example/android/build.gradle.kts new file mode 100644 index 00000000..7c5636e5 --- /dev/null +++ b/example/android/build.gradle.kts @@ -0,0 +1,26 @@ +buildscript { + val kotlinVersion = "2.2.20" + repositories { + google() + mavenCentral() + } + + dependencies { + classpath("com.android.tools.build:gradle:8.11.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + } +} + +rootProject.layout.buildDirectory.set(file("../build")) + +subprojects { + layout.buildDirectory.set(rootProject.layout.buildDirectory.dir(project.name)) +} + +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index cc5527d7..4cc8c0b0 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle deleted file mode 100644 index 44e62bcf..00000000 --- a/example/android/settings.gradle +++ /dev/null @@ -1,11 +0,0 @@ -include ':app' - -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() - -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } - -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/android/settings.gradle.kts b/example/android/settings.gradle.kts new file mode 100644 index 00000000..f59569bf --- /dev/null +++ b/example/android/settings.gradle.kts @@ -0,0 +1,39 @@ +import org.gradle.api.initialization.resolve.RepositoriesMode + +pluginManagement { + val flutterSdkPath = run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + checkNotNull(flutterSdkPath) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + settings.extra["flutterSdkPath"] = flutterSdkPath + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS) + repositories { + google() + mavenCentral() + maven { url = uri("https://storage.googleapis.com/download.flutter.io") } + } +} + +rootProject.name = "flutter_pos_printer_platform_example" +include(":app") diff --git a/example/lib/main.dart b/example/lib/main.dart index 7ff96da8..0fc30af8 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,8 +1,8 @@ import 'dart:async'; import 'dart:developer'; import 'dart:io'; -import 'package:esc_pos_utils/esc_pos_utils.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_esc_pos_utils/flutter_esc_pos_utils.dart'; import 'package:flutter_pos_printer_platform_image_3/flutter_pos_printer_platform_image_3.dart'; void main() { @@ -46,7 +46,8 @@ class _MyAppState extends State { _scan(); // subscription to listen change status of bluetooth connection - _subscriptionBtStatus = PrinterManager.instance.stateBluetooth.listen((status) { + _subscriptionBtStatus = + PrinterManager.instance.stateBluetooth.listen((status) { log(' ----------------- status bt $status ------------------ '); _currentStatus = status; if (status == BTStatus.connected) { @@ -62,11 +63,13 @@ class _MyAppState extends State { if (status == BTStatus.connected && pendingTask != null) { if (Platform.isAndroid) { Future.delayed(const Duration(milliseconds: 1000), () { - PrinterManager.instance.send(type: PrinterType.bluetooth, bytes: pendingTask!); + PrinterManager.instance + .send(type: PrinterType.bluetooth, bytes: pendingTask!); pendingTask = null; }); } else if (Platform.isIOS) { - PrinterManager.instance.send(type: PrinterType.bluetooth, bytes: pendingTask!); + PrinterManager.instance + .send(type: PrinterType.bluetooth, bytes: pendingTask!); pendingTask = null; } } @@ -78,7 +81,8 @@ class _MyAppState extends State { if (Platform.isAndroid) { if (status == USBStatus.connected && pendingTask != null) { Future.delayed(const Duration(milliseconds: 1000), () { - PrinterManager.instance.send(type: PrinterType.usb, bytes: pendingTask!); + PrinterManager.instance + .send(type: PrinterType.usb, bytes: pendingTask!); pendingTask = null; }); } @@ -99,7 +103,9 @@ class _MyAppState extends State { // method to scan devices according PrinterType void _scan() { devices.clear(); - _subscription = printerManager.discovery(type: defaultPrinterType, isBle: _isBle).listen((device) { + _subscription = printerManager + .discovery(type: defaultPrinterType, isBle: _isBle) + .listen((device) { devices.add(BluetoothPrinter( deviceName: device.name, address: device.address, @@ -139,8 +145,11 @@ class _MyAppState extends State { void selectDevice(BluetoothPrinter device) async { if (selectedPrinter != null) { - if ((device.address != selectedPrinter!.address) || (device.typePrinter == PrinterType.usb && selectedPrinter!.vendorId != device.vendorId)) { - await PrinterManager.instance.disconnect(type: selectedPrinter!.typePrinter); + if ((device.address != selectedPrinter!.address) || + (device.typePrinter == PrinterType.usb && + selectedPrinter!.vendorId != device.vendorId)) { + await PrinterManager.instance + .disconnect(type: selectedPrinter!.typePrinter); } } @@ -156,7 +165,8 @@ class _MyAppState extends State { // PaperSize.mm80 or PaperSize.mm58 final generator = Generator(PaperSize.mm80, profile); bytes += generator.setGlobalCodeTable('CP1252'); - bytes += generator.text('Test Print', styles: const PosStyles(align: PosAlign.center)); + bytes += generator.text('Test Print', + styles: const PosStyles(align: PosAlign.center)); bytes += generator.text('Product 1'); bytes += generator.text('Product 2'); @@ -174,7 +184,10 @@ class _MyAppState extends State { bytes += generator.cut(); await printerManager.connect( type: bluetoothPrinter.typePrinter, - model: UsbPrinterInput(name: bluetoothPrinter.deviceName, productId: bluetoothPrinter.productId, vendorId: bluetoothPrinter.vendorId)); + model: UsbPrinterInput( + name: bluetoothPrinter.deviceName, + productId: bluetoothPrinter.productId, + vendorId: bluetoothPrinter.vendorId)); pendingTask = null; break; case PrinterType.bluetooth: @@ -192,11 +205,14 @@ class _MyAppState extends State { case PrinterType.network: bytes += generator.feed(2); bytes += generator.cut(); - await printerManager.connect(type: bluetoothPrinter.typePrinter, model: TcpPrinterInput(ipAddress: bluetoothPrinter.address!)); + await printerManager.connect( + type: bluetoothPrinter.typePrinter, + model: TcpPrinterInput(ipAddress: bluetoothPrinter.address!)); break; default: } - if (bluetoothPrinter.typePrinter == PrinterType.bluetooth && Platform.isAndroid) { + if (bluetoothPrinter.typePrinter == PrinterType.bluetooth && + Platform.isAndroid) { if (_currentStatus == BTStatus.connected) { printerManager.send(type: bluetoothPrinter.typePrinter, bytes: bytes); pendingTask = null; @@ -214,7 +230,10 @@ class _MyAppState extends State { case PrinterType.usb: await printerManager.connect( type: selectedPrinter!.typePrinter, - model: UsbPrinterInput(name: selectedPrinter!.deviceName, productId: selectedPrinter!.productId, vendorId: selectedPrinter!.vendorId)); + model: UsbPrinterInput( + name: selectedPrinter!.deviceName, + productId: selectedPrinter!.productId, + vendorId: selectedPrinter!.vendorId)); _isConnected = true; break; case PrinterType.bluetooth: @@ -227,7 +246,9 @@ class _MyAppState extends State { autoConnect: _reconnect)); break; case PrinterType.network: - await printerManager.connect(type: selectedPrinter!.typePrinter, model: TcpPrinterInput(ipAddress: selectedPrinter!.address!)); + await printerManager.connect( + type: selectedPrinter!.typePrinter, + model: TcpPrinterInput(ipAddress: selectedPrinter!.address!)); _isConnected = true; break; default: @@ -262,7 +283,8 @@ class _MyAppState extends State { : () { _connectDevice(); }, - child: const Text("Connect", textAlign: TextAlign.center), + child: const Text("Connect", + textAlign: TextAlign.center), ), ), const SizedBox(width: 8), @@ -271,19 +293,22 @@ class _MyAppState extends State { onPressed: selectedPrinter == null || !_isConnected ? null : () { - if (selectedPrinter != null) printerManager.disconnect(type: selectedPrinter!.typePrinter); + if (selectedPrinter != null) + printerManager.disconnect( + type: selectedPrinter!.typePrinter); setState(() { _isConnected = false; }); }, - child: const Text("Disconnect", textAlign: TextAlign.center), + child: const Text("Disconnect", + textAlign: TextAlign.center), ), ), ], ), ), DropdownButtonFormField( - value: defaultPrinterType, + initialValue: defaultPrinterType, decoration: const InputDecoration( prefixIcon: Icon( Icons.print, @@ -325,9 +350,11 @@ class _MyAppState extends State { }, ), Visibility( - visible: defaultPrinterType == PrinterType.bluetooth && Platform.isAndroid, + visible: defaultPrinterType == PrinterType.bluetooth && + Platform.isAndroid, child: SwitchListTile.adaptive( - contentPadding: const EdgeInsets.only(bottom: 20.0, left: 20), + contentPadding: + const EdgeInsets.only(bottom: 20.0, left: 20), title: const Text( "This device supports ble (low energy)", textAlign: TextAlign.start, @@ -345,9 +372,11 @@ class _MyAppState extends State { ), ), Visibility( - visible: defaultPrinterType == PrinterType.bluetooth && Platform.isAndroid, + visible: defaultPrinterType == PrinterType.bluetooth && + Platform.isAndroid, child: SwitchListTile.adaptive( - contentPadding: const EdgeInsets.only(bottom: 20.0, left: 20), + contentPadding: + const EdgeInsets.only(bottom: 20.0, left: 20), title: const Text( "reconnect", textAlign: TextAlign.start, @@ -366,44 +395,59 @@ class _MyAppState extends State { .map( (device) => ListTile( title: Text('${device.deviceName}'), - subtitle: Platform.isAndroid && defaultPrinterType == PrinterType.usb + subtitle: Platform.isAndroid && + defaultPrinterType == PrinterType.usb ? null - : Visibility(visible: !Platform.isWindows, child: Text("${device.address}")), + : Visibility( + visible: !Platform.isWindows, + child: Text("${device.address}")), onTap: () { // do something selectDevice(device); }, leading: selectedPrinter != null && - ((device.typePrinter == PrinterType.usb && Platform.isWindows - ? device.deviceName == selectedPrinter!.deviceName - : device.vendorId != null && selectedPrinter!.vendorId == device.vendorId) || - (device.address != null && selectedPrinter!.address == device.address)) + ((device.typePrinter == PrinterType.usb && + Platform.isWindows + ? device.deviceName == + selectedPrinter!.deviceName + : device.vendorId != null && + selectedPrinter!.vendorId == + device.vendorId) || + (device.address != null && + selectedPrinter!.address == + device.address)) ? const Icon( Icons.check, color: Colors.green, ) : null, trailing: OutlinedButton( - onPressed: selectedPrinter == null || device.deviceName != selectedPrinter?.deviceName + onPressed: selectedPrinter == null || + device.deviceName != + selectedPrinter?.deviceName ? null : () async { _printReceiveTest(); }, child: const Padding( - padding: EdgeInsets.symmetric(vertical: 2, horizontal: 20), - child: Text("Print test ticket", textAlign: TextAlign.center), + padding: EdgeInsets.symmetric( + vertical: 2, horizontal: 20), + child: Text("Print test ticket", + textAlign: TextAlign.center), ), ), ), ) .toList()), Visibility( - visible: defaultPrinterType == PrinterType.network && Platform.isWindows, + visible: defaultPrinterType == PrinterType.network && + Platform.isWindows, child: Padding( padding: const EdgeInsets.only(top: 10.0), child: TextFormField( controller: _ipController, - keyboardType: const TextInputType.numberWithOptions(signed: true), + keyboardType: + const TextInputType.numberWithOptions(signed: true), decoration: const InputDecoration( label: Text("Ip Address"), prefixIcon: Icon(Icons.wifi, size: 24), @@ -413,12 +457,14 @@ class _MyAppState extends State { ), ), Visibility( - visible: defaultPrinterType == PrinterType.network && Platform.isWindows, + visible: defaultPrinterType == PrinterType.network && + Platform.isWindows, child: Padding( padding: const EdgeInsets.only(top: 10.0), child: TextFormField( controller: _portController, - keyboardType: const TextInputType.numberWithOptions(signed: true), + keyboardType: + const TextInputType.numberWithOptions(signed: true), decoration: const InputDecoration( label: Text("Port"), prefixIcon: Icon(Icons.numbers_outlined, size: 24), @@ -428,17 +474,21 @@ class _MyAppState extends State { ), ), Visibility( - visible: defaultPrinterType == PrinterType.network && Platform.isWindows, + visible: defaultPrinterType == PrinterType.network && + Platform.isWindows, child: Padding( padding: const EdgeInsets.only(top: 10.0), child: OutlinedButton( onPressed: () async { - if (_ipController.text.isNotEmpty) setIpAddress(_ipController.text); + if (_ipController.text.isNotEmpty) + setIpAddress(_ipController.text); _printReceiveTest(); }, child: const Padding( - padding: EdgeInsets.symmetric(vertical: 4, horizontal: 50), - child: Text("Print test ticket", textAlign: TextAlign.center), + padding: + EdgeInsets.symmetric(vertical: 4, horizontal: 50), + child: Text("Print test ticket", + textAlign: TextAlign.center), ), ), ), diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 79641d30..79228a9f 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -6,7 +6,7 @@ description: Demonstrates how to use the flutter_pos_printer_platform plugin. publish_to: 'none' # Remove this line if you wish to publish to pub.dev environment: - sdk: '>=3.1.0 <4.0.0' + sdk: '>=3.4.1 <4.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -28,9 +28,12 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.2 + cupertino_icons: ^1.0.9 - esc_pos_utils: ^1.1.0 + flutter_esc_pos_utils: + git: + url: https://github.com/E-MRE/flutter_esc_pos_utils + ref: 1.0.1 dev_dependencies: flutter_test: @@ -41,7 +44,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^1.0.0 + flutter_lints: ^6.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/lib/src/printers/escpos.dart b/lib/src/printers/escpos.dart index 6ad845ac..7265309a 100644 --- a/lib/src/printers/escpos.dart +++ b/lib/src/printers/escpos.dart @@ -2,10 +2,12 @@ import 'dart:typed_data'; import 'package:flutter_pos_printer_platform_image_3/printer.dart'; import 'package:flutter_pos_printer_platform_image_3/src/utils.dart'; -import 'package:image_v3/image_v3.dart'; +import 'package:image/image.dart' as img; class EscPosPrinter extends GenericPrinter { - EscPosPrinter(PrinterConnector connector, T model, {this.dpi = 200, required this.width, this.beepCount = 4}) : super(connector, model); + EscPosPrinter(PrinterConnector connector, T model, + {this.dpi = 200, required this.width, this.beepCount = 4}) + : super(connector, model); final int width; final int dpi; @@ -19,9 +21,13 @@ class EscPosPrinter extends GenericPrinter { @override Future image(Uint8List image, {int threshold = 150}) async { - final decodedImage = decodeImage(image)!; + final decodedImage = img.decodeImage(image)!; - final converted = toPixel(ImageData(width: decodedImage.width, height: decodedImage.height), paperWidth: width, dpi: dpi, isTspl: false); + final converted = toPixel( + ImageData(width: decodedImage.width, height: decodedImage.height), + paperWidth: width, + dpi: dpi, + isTspl: false); // final resizedImage = copyResize(decodedImage, width: converted.width, height: converted.height, interpolation: Interpolation.cubic); diff --git a/lib/src/printers/tspl.dart b/lib/src/printers/tspl.dart index 6869fc34..ad214169 100644 --- a/lib/src/printers/tspl.dart +++ b/lib/src/printers/tspl.dart @@ -2,7 +2,7 @@ import 'dart:core'; import 'dart:typed_data'; import 'package:flutter_pos_printer_platform_image_3/printer.dart'; -import 'package:image_v3/image_v3.dart'; +import 'package:image/image.dart' as img; import '../utils.dart'; @@ -70,11 +70,14 @@ class Command { return createLine(SHIFT, [shiftLeft, shiftTop]); } - static String imageString(String x, String y, String widthByte, String heightDot, {String mode = "0"}) { + static String imageString( + String x, String y, String widthByte, String heightDot, + {String mode = "0"}) { return createString(BITMAP, [x, y, widthByte, heightDot, mode, ""]); } - static String reverse(String x, String y, String widthByte, String heightDot) { + static String reverse( + String x, String y, String widthByte, String heightDot) { return createLine(REVERSE, [x, y, widthByte, heightDot]); } @@ -165,14 +168,18 @@ class TsplPrinter extends GenericPrinter { @override Future beep() async { return await sendToConnector(() { - return [Command.clearCache(), Command.beep(), Command.close()].join().codeUnits; + return [Command.clearCache(), Command.beep(), Command.close()] + .join() + .codeUnits; }); } @override Future selfTest() async { return await sendToConnector(() { - return [Command.clearCache(), Command.selfTest(), Command.close()].join().codeUnits; + return [Command.clearCache(), Command.selfTest(), Command.close()] + .join() + .codeUnits; }); } @@ -183,10 +190,13 @@ class TsplPrinter extends GenericPrinter { @override Future image(Uint8List image, {int threshold = 150}) async { - final decodedImage = decodeImage(image)!; + final decodedImage = img.decodeImage(image)!; final rasterizeImage = _toRaster(decodedImage, dpi: int.parse(dpi)); - final converted = toPixel(ImageData(width: decodedImage.width, height: decodedImage.height), - paperWidth: int.parse(_sizeWidth), dpi: int.parse(dpi), isTspl: true); + final converted = toPixel( + ImageData(width: decodedImage.width, height: decodedImage.height), + paperWidth: int.parse(_sizeWidth), + dpi: int.parse(dpi), + isTspl: true); final ms = 1000 + (converted.height * 0.5).toInt(); @@ -195,7 +205,10 @@ class TsplPrinter extends GenericPrinter { List buffer = []; buffer += this._config.codeUnits; buffer += Command.clearCache().codeUnits; - buffer += Command.imageString('0', '0', converted.width.toString(), converted.height.toString(), mode: '0').codeUnits; + buffer += Command.imageString('0', '0', converted.width.toString(), + converted.height.toString(), + mode: '0') + .codeUnits; buffer += rasterizeImage.data; buffer += Command.EOL_HEX; buffer += Command.printIt('1', repeat: '1').codeUnits; @@ -207,22 +220,27 @@ class TsplPrinter extends GenericPrinter { }, delayMs: ms); } - ImageRaster _toRaster(Image imgSrc, {int dpi = 200}) { + ImageRaster _toRaster(img.Image imgSrc, {int dpi = 200}) { // 200 DPI : 1 mm = 8 dots // 300 DPI : 1 mm = 12 dots // width 35mm = 280px // height 25mm = 200px final int multiplier = dpi == 200 ? 8 : 12; - final Image image = copyResize(imgSrc, - width: int.parse(this._sizeWidth) * multiplier, height: int.parse(this._sizeHeight) * multiplier, interpolation: Interpolation.linear); + final img.Image image = img.copyResize(imgSrc, + width: int.parse(this._sizeWidth) * multiplier, + height: int.parse(this._sizeHeight) * multiplier, + interpolation: img.Interpolation.linear); final int widthPx = image.width; final int heightPx = image.height; final int widthBytes = widthPx ~/ 8; // one byte is 8 bits - final List imageBytes = image.getBytes(format: Format.argb); + final List imageBytes = image.getBytes(); List monoPixel = []; for (int i = 0; i < imageBytes.length; i += 4) { - bool shouldBeWhite = imageBytes[i + 3] == 0 || (imageBytes[i] > 100 && imageBytes[i + 1] > 100 && imageBytes[i + 2] > 100); + bool shouldBeWhite = imageBytes[i + 3] == 0 || + (imageBytes[i] > 100 && + imageBytes[i + 1] > 100 && + imageBytes[i + 2] > 100); monoPixel.add(shouldBeWhite ? 1 : 0); } @@ -235,7 +253,10 @@ class TsplPrinter extends GenericPrinter { } } - return new ImageRaster(data: rasterizeImage, width: widthBytes.toString(), height: heightPx.toString()); + return new ImageRaster( + data: rasterizeImage, + width: widthBytes.toString(), + height: heightPx.toString()); } @override diff --git a/pubspec.yaml b/pubspec.yaml index 27a636b2..3800c6ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,22 +1,21 @@ name: flutter_pos_printer_platform_image_3 description: A flutter plugin that prints esc commands to printers in different platforms such as android, ios, windows and different interfaces Bluetooth and BLE, TCP and USB -version: 1.2.4 +version: 1.2.5 homepage: https://github.com/diantahoc/flutter_pos_printer_platform environment: - sdk: '>=3.1.0 <4.0.0' + sdk: '>=3.4.1 <4.0.0' flutter: ">=1.20.0" dependencies: flutter: sdk: flutter - # flutter_star_prnt: ^2.3.6 - enum_to_string: ^2.0.1 - image_v3: ^3.3.0 - network_info_plus: ^4.0.2 + enum_to_string: ^2.2.1 + image: ^4.8.0 + network_info_plus: ^8.1.0 ping_discover_network_forked: ^0.0.1 - rxdart: ^0.27.7 + rxdart: ^0.28.0 dev_dependencies: flutter_test: