Flutter自定义功能插件brady_flutter_plugin的使用

Flutter自定义功能插件brady_flutter_plugin的使用

brady_flutter_plugin

每个人都希望有一个更简便的方式来打印。特别是在现场工作时,时间就是金钱。 如果你的应用无法连接到Brady打印机,那么这里有解决方案:Brady的软件开发工具包(SDK)。 通过它,你的员工可以使用他们自己的移动应用来打印标签。这既快速又方便。 这是将你的标签数据无缝传输到Brady打印机的一种方式。

这个Brady Print SDK Flutter插件展示了Brady SDK可以实现的功能。你将能够通过API发现、连接并打印所需的模板和图像。该插件还允许你查看十几个打印机的详细信息,并根据打印选项来自定义你的标签打印方式。

如果您的业务希望从其自身的移动应用程序中打印标签,这是一个完美的例子,展示如何在完全完成后集成看起来是多么无缝!

开始使用

1. 添加依赖

pubspec.yaml文件中添加以下依赖项:

dependencies:
  brady_flutter_plugin: ^3.0.0+2

2. 演示基本功能

为了演示Brady SDK Flutter插件的基本功能,请复制并粘贴以下代码到一个新的Flutter项目中的main.dart文件:

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:brady_flutter_plugin/brady_flutter_plugin.dart';
import 'package:permission_handler/permission_handler.dart';

Uint8List? previewImage;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _bradyFlutterPlugin = BradyFlutterPlugin();

  bool showImage = false;
  var isTemplate = true;

  @override
  void initState() {
    super.initState();
  }

  Future<void> discover() async {
    Map<Permission, PermissionStatus> statuses = await [
      Permission.bluetooth,
      Permission.bluetoothConnect,
      Permission.bluetoothScan,
      Permission.nearbyWifiDevices,
      Permission.locationWhenInUse
    ].request();

    _bradyFlutterPlugin.startBlePrinterDiscovery();
    _bradyFlutterPlugin.startWifiPrinterDiscovery();
  }

  Future<void> connect() async {
    /// 获取所有已发现的打印机及其发现方式(蓝牙或Wi-Fi)。
    /// 可以显示列表让用户选择一个。
    Map<String, String> printerMap = await _bradyFlutterPlugin.getPrinters();
    bool? connected;
    for (var printer in printerMap.keys) {
      try {
        /**
         * 下面的代码展示了如何实现自动连接。
         *
         * "如果有之前连接过的打印机,找到一个与它的名称匹配的已发现打印机并连接。"
         *
         * final printerToConnectTo = _bradyFlutterPlugin.getLastConnectedPrinterName()
         * if (printer == printerToConnectTo) {
         *    final userSelectedProtocol = printerMap[printer] == "BLE" ? true : false;
         *    final connected = await _bradyFlutterPlugin.connect(printer, userSelectedProtocol);
         * }
         */
        // TODO: 替换为你打印机的名称。
        if (printer == "S3700-PGS372308901005") {
          /**
           * 你可以允许用户选择是通过蓝牙还是Wi-Fi连接。
           * 如果他们选择蓝牙(BLE),传递“true”给connect方法。
           * 如果他们选择Wi-Fi,传递“false”给connect方法。
           * 如果你不给他们选择的机会,传递“null”忽略协议并连接到具有匹配名称的任何打印机。
           *
           * 有关支持的连接,请参阅https://sdk.bradyid.com/supported_printers/
           * 例如,M211只能通过蓝牙连接,所以不要给用户选择通过Wi-Fi连接的选项。
           */
          final userSelectedProtocol = printerMap[printer] == "BLE" ? true : false;
          connected = await _bradyFlutterPlugin.connect(printer, true /*userSelectedProtocol*/);
          if (connected == true) {
            debugPrint("CONNECTED!");
          } else {
            debugPrint("FAILED TO CONNECT!");
          }
          break;
        }
      } on PlatformException catch (e) {
        if (kDebugMode) {
          print("Where: ${e.message!}\nDetails: ${e.details}");
        }
      }
    }
  }

  void setTemplate() async {
    // TODO: 替换为你的模板名称。
    try {
      final byteData = await rootBundle.load("assets/code128anotexttemplate.BWT");
      final bytes = byteData.buffer.asUint8List();
      await _bradyFlutterPlugin.setTemplateWithBase64(base64.encode(bytes), true);
      /**
       * 下面的代码展示了如何设置一个图像(如png,jpg等)而不是模板进行打印。
       *
       * final byteData = await rootBundle.load("assets/bitmap_rectangular_barcode.png");
       * final bytes = byteData.buffer.asUint8List();
       * _bradyFlutterPlugin.setTemplateWithBase64(base64.encode(bytes), false);
       */
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print(
            "Error setting the template.\nWhere: ${e.message!}\nDetails: ${e.details}");
      }
    }

    try {
      // TODO: 替换为你模板占位符的名称。
      await _bradyFlutterPlugin.setPlaceholderValue("BARCODE 1", "HELLO WORLD");
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print(
            "Error setting a placeholder.\nWhere: ${e.message!}\nDetails: ${e.details}");
      }
    }

    /// 如何从BWT文件(模板)中检索占位符信息。
    try {
      final templateData = await _bradyFlutterPlugin.getTemplateData();
      for (var key in templateData.keys) {
        debugPrint("getTemplateDataNames() -> $key");
        debugPrint("getTemplateDataTypes() -> ${templateData[key]}");
      }
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print(
            "Error getting template data names.\nWhere: ${e.message!}\nDetails: ${e.details}");
      }
    }

    /// 检索有关连接打印机的所有信息。
    try {
      var details = "";
      details += "Connection Status: ${await _bradyFlutterPlugin.getPrinterStatus()}";
      details += " (${await _bradyFlutterPlugin.getConnectionType()})\n";
      details += "Connection Status Message: ${await _bradyFlutterPlugin.getPrinterStatusMessage()}\n";
      details += "Connection Status Message Title: ${await _bradyFlutterPlugin.getPrinterStatusMessageTitle()}\n";
      details += "Connection Status Remedy Explanation Message: ${await _bradyFlutterPlugin.getPrinterStatusRemedyExplanationMessage()}\n";
      details += "Has Ownership: ${await _bradyFlutterPlugin.getHaveOwnership()}\n";
      details += "Printer Name: ${await _bradyFlutterPlugin.getPrinterName()}";
      details += " (${await _bradyFlutterPlugin.getPrinterModel()})\n";
      details += "Last Connected Printer: ${await _bradyFlutterPlugin.getLastConnectedPrinterName()}\n";
      details += "Supply Name: ${await _bradyFlutterPlugin.getSupplyName()}\n";
      details += "Template Supply Name: ${await _bradyFlutterPlugin.getTemplateSupplyName()}\n";
      details += "Y Number: ${await _bradyFlutterPlugin.getYNumber()}\n";
      details += "Supply Dimensions: ${await _bradyFlutterPlugin.getSupplyWidth()}in. x  ${await _bradyFlutterPlugin.getSupplyHeight()}in.\n";
      details += "Supply Color: ${(await _bradyFlutterPlugin.getSupplyColor())!.value.toString()}\n";
      details += "Remaining Supply: ${await _bradyFlutterPlugin.getSupplyRemainingPercentage()}\n";
      details += "Ribbon Name: ${await _bradyFlutterPlugin.getRibbonName()}\n";
      details += "Remaining Ribbon: ${await _bradyFlutterPlugin.getRibbonRemainingPercentage()}\n";
      details += "Ribbon Color: ${(await _bradyFlutterPlugin.getRibbonColor())!.value.toString()}\n";
      details += "Battery Level: ${await _bradyFlutterPlugin.getBatteryLevelPercentage()}";
      details += ", Charging: ${await _bradyFlutterPlugin.getIsAcConnected()}\n";
      details += "PreSized: ${await _bradyFlutterPlugin.getIsSupplyPreSized()}\n";
      details += "Supplies Match: ${await _bradyFlutterPlugin.suppliesMatch()}";
      debugPrint(details);
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print(
            "Error getting printer details.\n Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 打印设置的模板对象。
  Future<void> printTemplate() async {
    try {
      final printed = await _bradyFlutterPlugin.print(1, false, true, true);
      if (printed == true) {
        debugPrint("PRINTING SUCCESSFUL!");
      } else {
        debugPrint("PRINTING FAILED!");
      }
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 仅适用于M211和M511。阅读sdk.bradyid.com上的文档
  Future<void> feedSupply() async {
    try {
      final fed = await _bradyFlutterPlugin.feedSupply();
      if (fed == true) {
        debugPrint("FED SUCCESSFUL!");
      } else {
        debugPrint("FED FAILED!");
      }
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 仅适用于M211和M511。阅读sdk.bradyid.com上的文档
  Future<void> cutSupply() async {
    try {
      final cut = await _bradyFlutterPlugin.cutSupply();
      if (cut == true) {
        debugPrint("CUT SUCCESSFUL!");
      } else {
        debugPrint("CUT FAILED!");
      }
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 仅适用于M211和M511。阅读sdk.bradyid.com上的文档
  Future<void> setAutomaticShutoffTime() async {
    try {
      final setResult = await _bradyFlutterPlugin.setAutomaticShutoffTime(30);
      if (setResult == true) {
        debugPrint("AUTOMATIC SHUTOFF TIME SET SUCCESSFULLY!");
      } else {
        debugPrint("AUTOMATIC SHUTOFF TIME SET FAILED!");
      }
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 此方法是以下两个方法的组合。
  /// disconnect = disconnectWithoutForget + forgetLastConnectedPrinter
  Future<void> disconnect() async {
    try {
      final disconnected = await _bradyFlutterPlugin.disconnect();
      if (disconnected == true) {
        debugPrint("DISCONNECT SUCCESSFUL!");
      } else {
        debugPrint("DISCONNECT FAILED!");
      }
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 断开连接而不保存getLastConnectedPrinterName
  Future<void> disconnectWithoutForget() async {
    try {
      final disconnected = await _bradyFlutterPlugin.disconnectWithoutForget();
      if (disconnected == true) {
        debugPrint("DISCONNECT SUCCESSFUL!");
      } else {
        debugPrint("DISCONNECT FAILED!");
      }
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 此方法将getLastConnectedPrinterName的结果设置为null。
  Future<void> forgetLastConnectedPrinter() async {
    try {
      await _bradyFlutterPlugin.forgetLastConnectedPrinter();
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  /// 显示将要打印的图像预览。
  Future<void> getPreview() async {
    try {
      var base64 = await _bradyFlutterPlugin.getPreview(200);
      previewImage = base64Decode(base64!);
      setState(() {
        showImage = true;
      });
    } on PlatformException catch (e) {
      if (kDebugMode) {
        print("Where: ${e.message!}\nDetails: ${e.details}");
      }
    }
  }

  Future<void> getAvailableUpdates() async {
    /**
     * 每次连接的打印机发生变化时,都会将其属性作为字符串添加到内部列表中。
     * 调用getAvailablePrinterUpdates()会检索字符串列表并清空列表。
     * 有关所有属性键,请参阅https://sdk.bradyid.com/printer_properties_ios/
     */
    var updatesList = await _bradyFlutterPlugin.getAvailablePrinterUpdates();
    for (int i = 0; i < updatesList.length; i++) {
      /**
       * 例如,你可以循环遍历更新。当字符串等于“BatteryChargePercentage”时,
       * 你可以使用从printerDetails.getBatteryLevelPercentage()获得的值在UI中更新电池符号。
       */
      debugPrint(updatesList[i]);
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      appBar: AppBar(
        title: const Text('Plugin example app'),
      ),
      body: SingleChildScrollView(
        child: Stack(
          children: <Widget>[
            Column(
              children: [
                ElevatedButton(
                    onPressed: () {
                      discover();
                    },
                    child: const Text('开始发现')),
                ElevatedButton(
                    onPressed: () {
                      connect();
                    },
                    child: const Text('连接')),
                ElevatedButton(
                    onPressed: () {
                      setTemplate();
                    },
                    child: const Text('设置模板')),
                ElevatedButton(
                    onPressed: () {
                      printTemplate();
                    },
                    child: const Text('打印')),
                ElevatedButton(
                    onPressed: () {
                      feedSupply();
                    },
                    child: const Text('送纸')),
                ElevatedButton(
                    onPressed: () {
                      cutSupply();
                    },
                    child: const Text('切割')),
                ElevatedButton(
                    onPressed: () {
                      setAutomaticShutoffTime();
                    },
                    child: const Text('设置自动关机时间')),
                ElevatedButton(
                    onPressed: () {
                      disconnect();
                    },
                    child: const Text('断开连接')),
                ElevatedButton(
                    onPressed: () {
                      disconnectWithoutForget();
                    },
                    child: const Text('断开连接不忘记')),
                ElevatedButton(
                    onPressed: () {
                      forgetLastConnectedPrinter();
                    },
                    child: const Text('忘记')),
                ElevatedButton(
                    onPressed: () {
                      getPreview();
                    },
                    child: const Text('显示打印预览')),
                ElevatedButton(
                    onPressed: () {
                      getAvailableUpdates();
                    },
                    child: const Text('获取可用更新')),
                showImage
                    ? Column(
                        children: [
                          Image.memory(previewImage!),
                        ],
                      )
                    : const SizedBox(
                        height: 0,
                      ),
              ],
            ),
          ],
        ),
      ),
    ));
  }
}

3. 添加资源文件

pubspec.yaml文件中添加以下内容以指定资源文件路径:

assets:
  - assets/

然后,在项目的根目录下创建一个名为assets的文件夹,并在此文件夹中放置所有图像和模板文件(如.BWT文件)。

4. 安卓配置

建议将app/build.gradle文件中的minSdkVersion改为26。

android {
    defaultConfig {
        minSdkVersion 26
    }
}

如果minSdkVersion低于26,Flutter应用程序仍然可以构建,但如果移动设备的版本低于26(Android 8),SDK将无法与打印机通信。

在开发Flutter应用时,app/build.gradle文件中的buildTypes块应更改如下:

buildTypes {
    release {
        // 下面两行确保编译时不忽略第三方库类。
        // 这很关键,因为Brady Android SDK依赖这些类才能成功连接。
        shrinkResources false
        minifyEnabled false
        signingConfig signingConfigs.debug
    }
}

5. iOS配置

建议将最低iOS版本设置为iOS 15。

推荐使用广泛使用的Flutter权限库来处理权限问题。 在pubspec.yaml文件中添加以下内容:

dependencies:
  permission_handler: ^11.3.1

在Podfile的post_install部分添加以下权限:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      # 可以在这里移除未使用的权限
      # 更多信息请访问
      # https://github.com/BaseflowIT/flutter-permission-handler/blob/master/permission_handler/ios/Classes/PermissionHandlerEnums.h
      # 例如,如果你不需要相机权限,只需添加'PERMISSION_CAMERA=0'
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',
        ## dart: PermissionGroup.calendar
        'PERMISSION_EVENTS=0',
        ## dart: PermissionGroup.reminders
        'PERMISSION_REMINDERS=0',
        ## dart: PermissionGroup.contacts
        'PERMISSION_CONTACTS=0',
        ## dart: PermissionGroup.camera
        'PERMISSION_CAMERA=1',
        ## dart: PermissionGroup.microphone
        'PERMISSION_MICROPHONE=0',
        ## dart: PermissionGroup.speech
        'PERMISSION_SPEECH_RECOGNIZER=0',
        ## dart: PermissionGroup.photos
        'PERMISSION_PHOTOS=0',
        ## dart: [PermissionGroup.location, PermissionGroup.locationAlways, PermissionGroup.locationWhenInUse]
        'PERMISSION_LOCATION=1',
        'PERMISSION_LOCATION_ALWAYS=1',
        'PERMISSION_LOCATION_WHENINUSE=1',
        'PERMISSION_BLUETOOTH=1',
        ## dart: PermissionGroup.appTrackingTransparency
        'PERMISSION_APP_TRACKING_TRANSPARENCY=0',
        ## dart: PermissionGroup.criticalAlerts
        'PERMISSION_CRITICAL_ALERTS=0',
      ]
    end
  end
end

info.plist文件中添加以下权限:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>为了查找附近的打印机。</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>为了查找附近的打印机。</string>
<key>NSLocalNetworkUsageDescription</key>
<string>为了查找附近的打印机。</string>
<key>NSLocationUsageDescription</key>
<string>为了查找并连接到附近的打印机。</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>为了查找并连接到附近的打印机。</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>为了查找并连接到附近的打印机。</string>
<key>NSBonjourServices</key>
<array>
    <string>_pdl-datastream._tcp.</string>
</array>

使用以下代码向用户请求权限:

Map<Permission, PermissionStatus> statuses = await [
  Permission.bluetooth,
  Permission.bluetoothConnect,
  Permission.bluetoothScan,
  Permission.nearbyWifiDevices,
  Permission.locationWhenInUse
].request();

更多关于Flutter自定义功能插件brady_flutter_plugin的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自定义功能插件brady_flutter_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


要在Flutter项目中使用自定义功能插件 brady_flutter_plugin,你需要按照以下步骤进行配置和使用。假设你已经创建了这个插件,并且它已经发布到 pub.dev 或者你已经在本地进行了配置。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 brady_flutter_plugin 的依赖。

dependencies:
  flutter:
    sdk: flutter
  brady_flutter_plugin: ^1.0.0 # 替换为实际的版本号

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 代码中导入 brady_flutter_plugin

import 'package:brady_flutter_plugin/brady_flutter_plugin.dart';

3. 使用插件功能

根据 brady_flutter_plugin 提供的功能,你可以调用相应的方法或访问其属性。假设 brady_flutter_plugin 提供了一个名为 getBradyMessage 的方法,你可以这样使用它:

void getBradyMessage() async {
  String message = await BradyFlutterPlugin.getBradyMessage();
  print('Brady Message: $message');
}

4. 处理平台特定的代码

如果你的插件需要处理平台特定的代码(如 Android 或 iOS),你需要在相应的平台目录下进行配置。

Android

android/app/src/main/kotlin/.../MainActivity.kt 中,确保你正确初始化了插件:

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import com.example.brady_flutter_plugin.BradyFlutterPlugin

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        BradyFlutterPlugin.registerWith(flutterEngine.dartExecutor.binaryMessenger)
    }
}

iOS

ios/Runner/AppDelegate.swift 中,确保你正确初始化了插件:

import UIKit
import Flutter
import brady_flutter_plugin

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    BradyFlutterPlugin.register(with: controller.binaryMessenger)
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

5. 运行项目

完成上述步骤后,你可以运行你的 Flutter 项目,并调用 brady_flutter_plugin 提供的功能。

flutter run
回到顶部