Flutter日志记录插件logto_dart_sdk的使用

Flutter日志记录插件logto_dart_sdk的使用


Logto 帮助您快速专注于登录后的所有事情。

Logto Flutter SDK

Build Status

该项目是Logto的官方Flutter SDK。它提供了一种简单的方法来将Logto集成到您的Flutter项目中。

在后台,此SDK使用flutter_web_auth_2包处理OAuth2流程。

安装

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

dependencies:
  logto_dart_sdk: ^3.0.0

然后运行flutter pub get以安装该包。

或者直接通过运行以下命令安装包:

flutter pub add logto_dart_sdk

可以在pub.dev上查看该包。

设置

了解更多关于flutter_web_auth_2的设置

使用方法

初始化Logto SDK

final logtoConfig = const LogtoConfig(
  endpoint: "<your-logto-endpoint>",
  appId: "<your-app-id>"
);

void _init() {
  logtoClient = LogtoClient(
    config: logtoConfig,
    httpClient: http.Client(), // 可选的http客户端
  );
  render();
}

登录和登出

// 登录
await logtoClient.signIn(redirectUri);

// 登出
await logtoClient.signOut(redirectUri);

完整SDK文档

检查Flutter SDK指南以获取更多详细信息。

支持的平台

  • iOS
  • Android
  • Web

迁移指南

:::note 对于版本3.0.0之前的SDK,该SDK使用flutter_web_auth包。 :::

  1. 升级到最新版本
dependencies:
  logto_dart_sdk: ^3.0.0
  1. 更新manifest文件(仅限Android平台)

将AndroidManifest.xml文件中的flutter_web_auth回调活动替换为新的flutter_web_auth_2

  • FlutterWebAuth -> FlutterWebAuth2
  • flutter_web_auth -> flutter_web_auth_2
  1. redirectUri参数现在在signOut方法中是必需的。
await logtoClient.signOut(redirectUri);

示例代码

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:logto_dart_sdk/logto_client.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

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

  // 此小部件是您的应用程序的根节点。
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter SDK Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        textButtonTheme: TextButtonThemeData(
          style: TextButton.styleFrom(
            foregroundColor: Colors.white,
          ),
        ),
      ),
      home: const MyHomePage(title: 'Logto SDK Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

ButtonStyle secondaryButtonStyle = TextButton.styleFrom(
  foregroundColor: Colors.black,
  padding: const EdgeInsets.all(16.0),
  textStyle: const TextStyle(fontSize: 20),
);

ButtonStyle primaryButtonStyle = TextButton.styleFrom(
  foregroundColor: Colors.white,
  backgroundColor: Colors.deepPurpleAccent,
  padding: const EdgeInsets.all(16.0),
  textStyle: const TextStyle(fontSize: 20),
);

class _MyHomePageState extends State<MyHomePage> {
  static String welcome = 'Logto SDK Demo Home Page';
  String? content;
  bool isAuthenticated = false;

  final redirectUri = 'io.logto://callback';

  final config = LogtoConfig(
      appId: '<your app id>',
      endpoint: '<your logto endpoint>',
      // resources: ['<your api resources>'], // 解除注释以请求资源范围
      scopes: [
        LogtoUserScope.phone.value,
        LogtoUserScope.email.value,
        // LogtoUserScope.organizations.value, // 解除注释以请求组织范围
        // 添加其他资源范围
      ]);

  late LogtoClient logtoClient;

  [@override](/user/override)
  void initState() {
    super.initState();
    _init();
  }

  void render() async {
    if (await logtoClient.isAuthenticated) {
      var claims = await logtoClient.idTokenClaims;
      setState(() {
        content = claims!.toJson().toString().replaceAll(',', ',\n');
        isAuthenticated = true;
      });
      return;
    }
    setState(() {
      content = '';
      isAuthenticated = false;
    });
  }

  void _init() {
    logtoClient = LogtoClient(
      config: config,
      httpClient: http.Client(),
    );
    render();
  }

  Future<void> _showMyDialog(String title, String content) async {
    return showDialog<void>(
      context: context,
      barrierDismissible: false, // 用户必须点击按钮!
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text(title),
          content: Text(content),
          actions: <Widget>[
            TextButton(
              style: secondaryButtonStyle,
              child: const Text('Got it'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    Widget signInButton = TextButton(
      style: primaryButtonStyle,
      onPressed: () async {
        await logtoClient.signIn(redirectUri);
        render();
      },
      child: const Text('Sign In'),
    );

    Widget signOutButton = TextButton(
      style: secondaryButtonStyle,
      onPressed: () async {
        await logtoClient.signOut(redirectUri);
        render();
      },
      child: const Text('Sign Out'),
    );

    Widget getUserInfoButton = TextButton(
      style: secondaryButtonStyle,
      onPressed: () async {
        var userInfo = await logtoClient.getUserInfo();
        _showMyDialog(
            'User Info', userInfo.toJson().toString().replaceAll(',', ',\n'));
      },
      child: const Text('Get User Info'),
    );

    Widget getOrganizationTokenButton = TextButton(
      style: secondaryButtonStyle,
      onPressed: () async {
        var token = await logtoClient
            .getOrganizationToken('<organization id returned in id_token>');
        _showMyDialog('Organization Token', token!.toJson().toString());
      },
      child: const Text('Get Organization Token'),
    );

    Widget getResourceTokenButton = TextButton(
      style: secondaryButtonStyle,
      onPressed: () async {
        var token = await logtoClient.getAccessToken(
            resource: '<your resource indicator>');
        _showMyDialog('Resource Token', token!.toJson().toString());
      },
      child: const Text('Get Resource Token'),
    );

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            SelectableText(welcome,
                style:
                    const TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
            Container(
              padding: const EdgeInsets.all(64),
              child: SelectableText(
                content ?? '',
              ),
            ),
            isAuthenticated == true ? signOutButton : signInButton,
            isAuthenticated == true
                ? getUserInfoButton
                : const SizedBox.shrink(),
            isAuthenticated == true &&
                    (config.scopes
                            ?.contains(LogtoUserScope.organizations.value) ??
                        false)
                ? getOrganizationTokenButton
                : const SizedBox.shrink(),
            isAuthenticated == true && config.resources != null
                ? getResourceTokenButton
                : const SizedBox.shrink(),
          ],
        ),
      ),
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何在Flutter项目中使用logto_dart_sdk插件进行日志记录的示例代码。这个插件允许你将日志发送到指定的日志服务器或处理系统。

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  logto_dart_sdk: ^最新版本号  # 请替换为实际可用的最新版本号

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

2. 初始化日志记录器

在你的应用入口文件(通常是main.dart)中初始化日志记录器。这里假设你需要将日志发送到某个日志服务器。

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

void main() {
  // 初始化日志记录器
  Logto.init(
    serverUrl: 'https://your-log-server-url.com/api/logs', // 替换为你的日志服务器URL
    appName: 'MyFlutterApp',
    appVersion: '1.0.0',
    // 可以添加更多配置,如认证信息等
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  void _logExample() {
    // 记录信息日志
    Logto.info('This is an info log');

    // 记录警告日志
    Logto.warn('This is a warning log');

    // 记录错误日志
    Logto.error('This is an error log', error: Exception('Sample exception'));

    // 记录调试日志
    Logto.debug('This is a debug log');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Log Example'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _logExample,
          child: Text('Log Example'),
        ),
      ),
    );
  }
}

3. 配置日志输出(可选)

如果你希望将日志同时输出到控制台或其他目的地,你可以自定义日志输出格式和处理器。logto_dart_sdk通常允许你注册多个日志处理器。以下是一个简单的例子,展示如何将日志同时发送到服务器和控制台:

import 'package:logto_dart_sdk/logto_dart_sdk.dart';
import 'dart:developer' as developer;

void main() {
  // 自定义日志处理器,输出到控制台
  var consoleHandler = (LogRecord record) {
    String logMessage = '${record.level.name}: ${record.message}';
    if (record.error != null) {
      logMessage += '\n${record.error.toString()}';
    }
    if (record.stackTrace != null) {
      logMessage += '\n${record.stackTrace.toString()}';
    }
    developer.log(logMessage, level: record.level.toDeveloperLogLevel());
  };

  // 注册自定义处理器
  Logto.addHandler(consoleHandler);

  // 初始化日志记录器(包括服务器配置)
  Logto.init(
    serverUrl: 'https://your-log-server-url.com/api/logs', // 替换为你的日志服务器URL
    appName: 'MyFlutterApp',
    appVersion: '1.0.0',
    // 可以添加更多配置,如认证信息等
  );

  runApp(MyApp());
}

请注意,logto_dart_sdk的具体API和使用方式可能会根据版本有所不同,因此请参考其官方文档和源代码以获取最新和最准确的信息。如果插件提供了额外的配置选项或功能,请确保在初始化时正确设置。

回到顶部