Flutter自动登录插件autologin_linux的使用

Flutter自动登录插件autologin_linux的使用

autologin_linuxautologin 包在 Linux 平台上的实现。

使用

该包已被官方推荐,因此你可以直接使用 autologin。当你这样做时,该包会自动包含在你的应用中,所以你无需在 pubspec.yaml 中添加它。

然而,如果你导入此包以直接使用其 API,则应像往常一样将其添加到 pubspec.yaml 文件中。

以下是一个完整的示例代码,展示了如何使用 autologin 插件来处理登录凭证。

import 'dart:async';

import 'package:autologin/autologin.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

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

/// 此框架只是为了确保 DemoPage 可以显示一个 snackbar
class DemoFrame extends StatelessWidget {
  const DemoFrame({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Autologin-Plugin 示例应用'),
        ),
        body: const SingleChildScrollView(
          padding: EdgeInsets.symmetric(vertical: 8, horizontal: 24),
          child: Align(
            child: SizedBox(
              width: 400,
              child: DemoPage(),
            ),
          ),
        ),
      ),
    );
  }
}

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

  @override
  State<DemoPage> createState() => _DemoPageState();
}

/// 大多数这些状态字段仅用于调试
class _DemoPageState extends State<DemoPage> {
  bool? isPlatformSupported;
  String? usernameNote;
  String? passwordNote;
  bool obscurePassword = true;
  final usernameController = TextEditingController();
  final passwordController = TextEditingController();
  String loginToken = 'Loading...';

  @override
  void initState() {
    super.initState();
    unawaited(initPlatformState());
    usernameController.addListener(resetUsernameNote);
    passwordController.addListener(resetPasswordNote);
    AutologinPlugin.setup(
      domain: 'rekire.github.io',
      appId: 'eu.rekisoft.flutter.autologin',
      appName: 'Autologin Demo',
    );
    AutologinPlugin.requestLoginToken().then((value) async {
      if (value != null) {
        setState(() => loginToken = value);
      } else {
        final hasZeroTouchSupport = (await AutologinPlugin.performCompatibilityChecks()).hasZeroTouchSupport;
        setState(() => loginToken = hasZeroTouchSupport ? '这是首次启动' : '平台不支持');
        if (hasZeroTouchSupport) {
          await AutologinPlugin.saveLoginToken('首次启动 ${DateTime.now()}');
        }
      }
    }).onError((error, stackTrace) {
      setState(() => loginToken = error.toString());
    });
  }

  @override
  void dispose() {
    super.dispose();
    usernameController.removeListener(resetUsernameNote);
    passwordController.removeListener(resetPasswordNote);
  }

  // 平台消息是异步的,所以我们初始化在一个异步方法中。
  Future<void> initPlatformState() async {
    final isSupported = await AutologinPlugin.isPlatformSupported;
    setState(() => isPlatformSupported = isSupported);
  }

  void resetUsernameNote() {
    setState(() => usernameNote = null);
  }

  void resetPasswordNote() {
    setState(() => passwordNote = null);
  }

  Future<void> requestCredentials() async {
    final credentials = await AutologinPlugin.requestCredentials();

    if (mounted) {
      setState(() {
        if (credentials?.username != null) {
          usernameController.text = credentials!.username!;
          usernameNote = null;
        } else {
          usernameController.text = '';
          usernameNote = 'API 没有提供用户名';
        }
        if (credentials?.password != null) {
          passwordController.text = credentials!.password!;
          passwordNote = null;
        } else {
          passwordController.text = '';
          passwordNote = 'API 没有提供密码';
        }
      });
    }
  }

  Future<void> saveCredentials() async {
    final success = await AutologinPlugin.saveCredentials(
      Credential(username: usernameController.text, password: passwordController.text, domain: 'rekire.github.io'),
    );

    if (!success && mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('保存凭证失败!'),
        ),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        if (isPlatformSupported != true)
          const Padding(
            padding: EdgeInsets.only(bottom: 16),
            child: Text('⚠️ 当前平台不支持 ⚠️'),
          ),
        TextFormField(
          controller: usernameController,
          textInputAction: TextInputAction.next,
          autofillHints: const [AutofillHints.username],
          decoration: InputDecoration(
            border: const OutlineInputBorder(),
            labelText: '用户名',
            helperText: usernameNote,
          ),
          onFieldSubmitted: (_) => saveCredentials(),
        ),
        const SizedBox(height: 16),
        TextFormField(
          controller: passwordController,
          obscureText: obscurePassword,
          textInputAction: TextInputAction.send,
          keyboardType: TextInputType.visiblePassword,
          autofillHints: const [AutofillHints.password],
          decoration: InputDecoration(
            border: const OutlineInputBorder(),
            labelText: '密码',
            helperText: passwordNote,
            suffixIcon: IconButton(
              icon: Icon(obscurePassword ? Icons.visibility : Icons.visibility_off),
              onPressed: () {
                setState(() => obscurePassword = !obscurePassword);
              },
              tooltip: obscurePassword ? '显示密码' : '隐藏密码',
            ),
          ),
          onFieldSubmitted: (_) => saveCredentials(),
        ),
        const SizedBox(height: 16),
        FilledButton(
          onPressed: isPlatformSupported == true ? saveCredentials : null,
          child: const Text('保存凭证'),
        ),
        const SizedBox(height: 8),
        OutlinedButton(
          onPressed: () {
            usernameController.text = 'Some-Username';
            passwordController.text = r'Example-P@§$w0rd!';
          },
          child: const Text('输入示例数据'),
        ),
        const SizedBox(height: 8),
        OutlinedButton(
          onPressed: isPlatformSupported == true ? requestCredentials : null,
          child: const Text('请求登录数据'),
        ),
        const SizedBox(height: 8),
        Text('登录令牌: $loginToken'),
      ],
    );
  }
}

以上代码展示了一个完整的 Flutter 应用程序,该应用程序使用 autologin 插件来处理登录凭证。你可以根据需要调整域名、应用 ID 和应用名称等参数。


更多关于Flutter自动登录插件autologin_linux的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter自动登录插件autologin_linux的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用autologin_linux插件来实现自动登录功能的示例代码。这个插件允许你在Linux平台上实现自动登录功能,非常适合需要在启动时自动登录到应用中的场景。

首先,确保你的Flutter开发环境已经正确设置,并且你的项目已经初始化。然后,按照以下步骤进行操作:

  1. 添加依赖: 在你的pubspec.yaml文件中添加autologin_linux依赖:

    dependencies:
      flutter:
        sdk: flutter
      autologin_linux: ^最新版本号  # 请替换为实际发布的最新版本号
    

    然后运行flutter pub get来安装依赖。

  2. 配置Linux平台代码: 打开你的Linux平台特定代码目录(通常是linux文件夹),并编辑CMakeLists.txtplugin_impl.cc文件(如果它们不存在,你可能需要创建它们)。

    CMakeLists.txt(如果尚不存在,创建它):

    cmake_minimum_required(VERSION 3.10)
    
    project(autologin_linux_plugin LANGUAGES CXX)
    
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    find_package(Flutter REQUIRED)
    
    add_library(autologin_linux_plugin SHARED
        plugin_impl.cc
    )
    
    target_link_libraries(autologin_linux_plugin PRIVATE Flutter::Dart)
    

    plugin_impl.cc(如果尚不存在,创建它):

    #include <flutter_linux/flutter_linux.h>
    #include <string>
    #include <memory>
    
    class AutologinLinuxPlugin : public flutter::Plugin {
    public:
        static void RegisterWithRegistrar(flutter::PluginRegistrar* registrar);
    
        AutologinLinuxPlugin();
        virtual ~AutologinLinuxPlugin();
    
    private:
        // Implement your plugin's methods here.
        void AttemptAutoLogin();
    };
    
    void AutologinLinuxPlugin::RegisterWithRegistrar(flutter::PluginRegistrar* registrar) {
        auto channel =
            std::make_unique<flutter::MethodChannel<AutologinLinuxPlugin>>(
                *registrar,
                "autologin_linux/channel",
                &AutologinLinuxPlugin::HandleMethodCall);
    
        auto plugin = std::make_unique<AutologinLinuxPlugin>();
    
        channel->SetMethodCallHandler(
            [plugin_pointer = plugin.get()](
                const flutter::MethodCall<>& call,
                std::unique_ptr<flutter::MethodResult<>> result) {
                if (call.method_name() == "attemptAutoLogin") {
                    plugin_pointer->AttemptAutoLogin();
                    result->Success();
                } else {
                    result->NotImplemented();
                }
            });
    
        registrar->AddPlugin(std::move(plugin));
        registrar->AddChannel(std::move(channel));
    }
    
    AutologinLinuxPlugin::AutologinLinuxPlugin() {}
    
    AutologinLinuxPlugin::~AutologinLinuxPlugin() {}
    
    void AutologinLinuxPlugin::AttemptAutoLogin() {
        // 实现自动登录逻辑
        // 例如,这里你可以使用Linux特定的API来自动填充登录凭据
        // 注意:这只是一个示例,实际实现将取决于你的应用需求
        std::string username = "default_user";
        std::string password = "default_password";
        // TODO: 使用这些凭据自动登录
    }
    
    IMPLEMENT_FLUTTER_PLUGIN(AutologinLinuxPlugin)
    
  3. 在Dart代码中调用插件: 在你的Flutter应用的Dart代码中,你可以通过MethodChannel与本地插件进行通信。

    import 'package:flutter/services.dart';
    
    class AutologinService {
      static const MethodChannel _channel = MethodChannel('autologin_linux/channel');
    
      static Future<void> attemptAutoLogin() async {
        try {
          await _channel.invokeMethod('attemptAutoLogin');
        } on PlatformException catch (e) {
          print("Failed to invoke: '${e.message}'.");
        }
      }
    }
    
    void main() {
      // 在应用启动时尝试自动登录
      AutologinService.attemptAutoLogin();
    
      runApp(MyApp());
    }
    

请注意,上述AttemptAutoLogin方法中的实现只是一个占位符。在实际应用中,你需要根据Linux系统的具体API或方法来填充登录凭据。此外,自动登录功能可能涉及安全性和隐私问题,因此在实际部署之前,请确保你遵守了所有相关的法律和最佳实践。

这个示例代码展示了如何在Flutter项目中集成和使用autologin_linux插件,但具体的自动登录逻辑需要你根据你的应用需求来实现。

回到顶部