[Flutter翻译]在Flutter中为linux编写插件

1,170 阅读3分钟

原文地址:medium.com/@yashjohri1…

原文作者:medium.com/@yashjohri1…

发布时间:2020年8月10日 - 2分钟阅读

嘿,希望你在这次流行病中没事。我们都知道Flutter最近用canonical扩展了对linux的支持。有了这个,我们现在可以更容易地用Flutter为linux构建和部署应用程序了。

从升级Flutter开始

flutter channel master
flutter upgrade

在Flutter中启用Linux支持

flutter config --enable-linux-desktop

让我们创建一个简单的电池插件

在这个例子中,我们将创建一个插件,它将为我们提供电池百分比水平和它的技术。

flutter create -t plugin --platforms=linux battery

分析环境

在你的插件文件夹中,你会得到一个lib文件夹,其中包含battery.dart文件,它将处理你的方法通道,一个example文件夹,其中包含一个示例应用程序来演示你的插件的使用,还有一个linux文件夹,其中包含battery_plugin.cc文件,它将处理你的平台级方法。平台级的代码是用Linux的C++编写的。

每当有来自Flutter的调用时,函数battery_plugin_handle_method_call将被调用。我们可以通过调用fl_method_call_get_name(method_call)函数来获取方法。响应将以FlMethodResponse数据类型从linux平台发送到flutter。

在linux中,我们要处理的数据类型是FlValue。FlValue的一些例子是:

对于字符串:

string flutter = "Flutter".g_autoptr(FlValue);
g_autoptr(FlValue) converted = fl_value_new_string(flutter.c_str());

对于Maps:

// Initialize a map.
g_autoptr(FlValue) mapExample = fl_value_new_map();
string flutter = "Flutter", dart = "Dart";
// Set a value in map.
fl_value_set(mapExample, fl_value_new_string(flutter.c_str()),               fl_value_new_string(dart.c_str()));
// First parameter is the variable.
// Second parameter is the key.
// Third paramter is its value.

为了将FlValue转换为响应,我们必须使用:

g_autoptr(FlMethodResponse) response = FL_METHOD_RESPONSE(fl_method_success_response_new(value));
// It takes a FlValue as its parameter.

更多关于FlValue的信息可以在这里找到。

让我们开始工作

lib/battery.dart文件中,添加一个函数来调用getBatteryData方法,像这样:

static Future<Map<String, dynamic>> get getBatteryLevel async {
    final Map<String, dynamic> version = Map<String, dynamic>.from(
        await _channel.invokeMethod('getBatteryData')
    );
    return version;
}

这就是我们在flutter应用中要调用的getter。现在在linux/battery_plugin.cc中,我们必须为我们的getBatteryData方法通道添加一个条件。

if (strcmp(method, "getPlatformVersion") == 0) {
  /*
   * already implemented.
   */
} else if (strcmp(method, "getBatteryData") == 0) {
  g_autoptr(FlValue) batteryData = fl_value_new_map();
  string command = "cat /sys/class/power_supply/BAT1/capacity";
  char buffer[256];
  FILE * pipe = popen(command.c_str(), "r");
  while (!feof(pipe)) {
    if (fgets(buffer, 128, pipe) != NULL) {
      fl_value_set(batteryData, fl_value_new_string("capacity"), fl_value_new_string(buffer));
    }
  }
  pclose(pipe);

  command = "cat /sys/class/power_supply/BAT1/technology";
  pipe = popen(command.c_str(), "r");
  while (!feof(pipe)) {
    if (fgets(buffer, 128, pipe) != NULL) {
      fl_value_set(batteryData, fl_value_new_string("technology"), fl_value_new_string(buffer));
    }
  }
  pclose(pipe);

  response = FL_METHOD_RESPONSE(fl_method_success_response_new(batteryData));
}

注意:这不是整个battery_plugin.cc,只是我们实现的部分。

在这里,我们使用C++中的管道来提取Linux命令的输出。我们使用文件/sys/class/power_supply/BAT1/capacity来获取电池的百分比水平,使用/sys/class/power_supply/BAT1/technology来获取其技术。

现在到前台

这是我们的main.dart文件,它使用电池插件来获取电池数据。

import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:battery/battery.dart';

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String capacity = "Unknown", technology = "Unknown";

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

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    Map<String, dynamic> batteryDataLocal;
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      batteryDataLocal = await Battery.getBatteryLevel;
    } on PlatformException {
      batteryDataLocal = <String, dynamic>{
        'capacity': 'Failed to get capacity',
        'technology': 'Failed to get technology',
      };
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      capacity = batteryDataLocal["capacity"];
      technology = batteryDataLocal["technology"];
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
          child: Text(
            'Battery is : $capacity\nTechnology is : $technology',
          ),
        ),
      ),
    );
  }
}

运行应用程序

flutter run -d linux

要获得详细的调试数据,请使用:

flutter run -d linux -v

就这样吧

这是应用程序作为linux可执行文件运行的截图。

电池插件示例

Github : github.com/yash1200/fl…


通过( www.DeepL.com/Translator )(免费版)翻译