Flutter自动登录功能插件autologin_platform_interface的使用

Flutter自动登录功能插件autologin_platform_interface的使用

autologin_platform_interface 插件是 autologin 插件的通用平台接口。它允许特定平台实现 autologin 插件,并确保它们支持相同的接口。

使用方法

要实现一个新的平台特定实现,可以扩展 AutologinPlatform 并添加执行平台特定行为的实现。

示例代码

以下是一个完整的示例,展示了如何在 Flutter 应用中使用 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](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('自动登录插件示例应用'),
        ),
        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](/user/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 = '加载中...';

  [@override](/user/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: '自动登录示例',
    );
    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](/user/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](/user/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_platform_interface的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,以下是一个关于如何使用Flutter自动登录功能插件autologin_platform_interface的示例代码。请注意,autologin_platform_interface通常是一个平台接口层,用于定义与平台相关的自动登录功能的接口。实际的功能实现会在对应平台(如iOS和Android)的插件中完成。这里主要展示如何在Flutter项目中集成和使用这个接口。

首先,确保你已经在pubspec.yaml文件中添加了必要的依赖项。由于autologin_platform_interface通常是一个基础接口库,你可能还需要添加具体的平台实现库,例如autologin。但在这个例子中,我们主要关注接口层。

dependencies:
  flutter:
    sdk: flutter
  autologin_platform_interface: ^x.y.z  # 替换为实际的版本号

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

接下来,在你的Flutter项目中创建一个服务类来使用这个接口。以下是一个简单的示例:

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

class AutoLoginService {
  static const MethodChannel _channel = MethodChannel('plugins.flutter.io/autologin');

  static AutoLoginPlatform? _platform;

  static AutoLoginPlatform get platform {
    if (_platform == null) {
      _platform = AutoLoginPlatform.instance;
    }
    return _platform!;
  }

  Future<void> attemptAutoLogin() async {
    try {
      bool success = await platform.attemptAutoLogin();
      if (success) {
        print("Auto login successful!");
        // 执行登录成功后的逻辑
      } else {
        print("Auto login failed, prompting user to login manually.");
        // 执行登录失败后的逻辑,例如显示登录界面
      }
    } on PlatformException catch (e) {
      print("Failed to perform auto login: '${e.message}'.");
      // 处理平台异常
    }
  }
}

在这个示例中,我们定义了一个AutoLoginService类,它包含一个静态的platform属性,用于获取AutoLoginPlatform的实例。AutoLoginPlatformautologin_platform_interface库中定义的接口类。我们通过AutoLoginPlatform.instance来获取具体的平台实现实例。

attemptAutoLogin方法调用平台特定的attemptAutoLogin函数,该函数返回一个布尔值,表示自动登录是否成功。根据返回值,我们可以执行相应的逻辑。

注意,这里的MethodChannel名称'plugins.flutter.io/autologin'是一个占位符,你应该使用实际插件定义的方法通道名称。

最后,在你的应用入口点(例如main.dart)中调用这个服务:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Auto Login Demo'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              await AutoLoginService().attemptAutoLogin();
            },
            child: Text('Attempt Auto Login'),
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮,点击按钮时会调用AutoLoginServiceattemptAutoLogin方法尝试自动登录。

请注意,这个示例假设你已经有了对应的平台实现(iOS和Android),并且这些实现已经正确注册了方法通道并实现了attemptAutoLogin方法。如果没有这些平台实现,你需要创建它们,并确保它们与这个接口兼容。

由于autologin_platform_interface通常是一个抽象层,具体的实现细节和平台特定的代码将在这个接口的实现库中定义。你可能需要查阅该库的文档或源代码以了解如何创建这些平台特定的实现。

回到顶部