我正在尝试使用flutter与SunMi移动打印机进行通信。我想使用 AIDL 调用打印机作为与打印机通信的方式之一,但我不知道如何以及在何处将 AIDL 文件放置在 flutter 中,或者在我的情况下是否可以使用 flutter。我需要知道是否可以使用 AIDL 与打印机进行通信。我选择在我的应用程序中使用 flutter 或 android studio 和 java。
问题来源:https://github.com/flutter/flutter/issues/49413#issue-554566892
我找不到正确的答案,因此将问题发布在这里。
由于这是我们正在讨论的 AIDL 文件,因此可以安全地假设这是 Android 独有的功能。
为此,与任何其他特定于 Android 的
MethodChannel
实现一样,您需要创建一个 MethodCallHandler 和/或一个 StreamHandler (取决于您是否想要执行流或只是一个命令 -> 结果方法),将其注册到Main FlutterActivity,并通过 MethodChannels 从 dart 调用它。
免责声明
创建MethodCallHandler/StreamHandler
在 flutter 应用程序的
android/app/src/main/com/some/path
文件夹中,创建一个新的 java 文件并实现 ServiceConnection
、MethodChannel.MethodCallHandler
和/或 EventChannel.StreamHandler
:
public class PrinterPlugin implements MethodChannel.MethodCallHandler, EventChannel.StreamHandler, ServiceConnection {
public static final CHANNEL = "com.some.path/printer";
public static final EVENT_CHANNEL = "com.some.path/printer-events";
private Context context;
private IPrinterService printerService = null; // where IPrinterService would be the AIDL's name
public EventChannel.EventSink eventSink = null;
public PrinterPlugin(Context context) {
this.context = context;
if (printerService == null) {
// these strings should be in your documentation or you can find these values from the package manager
Intent intent = new Intent("com.your.printer.service");
intent.setPackage("com.whatever.aidl");
context.bindService(intent, this, Context.BIND_AUTO_CREATE);
}
}
public void disconnect() {
context.unbindService(this);
}
// streamhandler implementation
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
this.eventSink = events;
}
@Override
public void onCancel(Object arguments) {
this.eventSink = null;
}
// /streamhandler implementation
// methodcallhandler implementation
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
try {
switch (call.method) {
case "initialize": printerService.printerInit(); break;
case "print-text": printerService.printText(call.argument("data")); break;
// implement other aidl methods
}
} catch (RemoteException e) {
result.error("", ex.getMessage(), null);
}
}
// /methodcallhandler implementation
// serviceConnection implementation
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
printerService = IPrinterService .Stub.asInterface(service);
if (eventSink != null) {
eventSink.success("Printer Connected");
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
printerService = null;
if (eventSink != null) {
eventSink.success("Printer Disconnected");
}
}
// /serviceConnection implementation
}
将 PrinterPlugin 注册到 MainActivity 作为 MethodChannel 和 EventChannel
既然已经解决了,您需要在
MainActivity
的 configureFlutterEngine
方法上注册此插件:
public class MainActivity extends FlutterActivity {
private PrinterPlugin printerPlugin;
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
Context context = getContext();
printerPlugin = new PrinterPlugin(context);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), PrinterPlugin.CHANNEL)
.setMethodCallHandler(printerPlugin);
new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), PrinterPlugin.EVENT_CHANNEL)
.setStreamHandler(printerPlugin);
}
@Override
protected void onDestroy() {
super.onDestroy();
this.printerPlugin.unbindService();
}
}
从 dart 调用方法
现在您需要做的最后一件事就是从 dart 调用这些。
const MethodChannel _channel = MethodChannel('com.some.path/printer'); // should match the CHANNEL constant on the java side
const EventChannel _evntChannel = EventChannel('com.some.path/printer-events'); // should match the EVENT_CHANNEL constant on the java side
class PrinterPlugin {
static Stream<dynamic> _printerStream = _eventChannel.receiveBroadcastStream();
Stream<String> status$;
PrinterPlugin() {
status$ = _printerStream;
}
static Future printText(String data) async {
await _channel.invokeMethod('initialize');
await _channel.invokeMethod('print-text', 'Foo Bar');
}
}
嗯,这是很多代码 - 但这基本上就是我的做法。只是一个
MethodCallHandler
和 ServiceConnection
实现。
您也可以对这个实现感到疯狂,例如实时打印进度,或获取流式打印机状态等。
让我知道它是否适合您的需求。
如果您的打印机使用 BT 或 USB 接口(有时即使设备有内置打印机,它们仍然通过带状电缆使用 USB 接口),您可以放弃供应商的 SDK 并使用 flutter 包POS 打印,如 flutter_esc_pos_utils。
要检查正在使用哪个接口,请首先安装上述软件包并运行以下命令:
final profiles = await CapabilityProfile.getAvailableProfiles();
我已经使用这种方法在自助点餐机的内置打印机上进行打印。减少开发时间并让您 应用程序兼容更多硬件。