Flutter Twitch API集成插件twitch_api的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter Twitch API集成插件twitch_api的使用

1. 简介

twitch_api 是一个纯 Dart 的包装库,用于通过 OAuth 隐式认证连接到 Twitch.tv。它实现了 Twitch API 参考中定义的所有端点。

2. 入门指南

2.1 注册应用

要使用此插件,您需要在 Twitch 开发者控制台 注册一个应用以获取 客户端 ID

2.2 初始化 TwitchClient

注册应用后,您需要使用 clientIdredirectUri 实例化 TwitchClient 类。

import 'package:twitch_api/twitch_api.dart';

final _twitchClient = TwitchClient(
  clientId: clientId,
  redirectUri: redirectUri,
);
2.3 进行首次认证

在使用任何方法之前,您需要管理与 Twitch 账户的首次连接并初始化收到的令牌。以下是一个完整的示例,使用 flutter_webview_plugin 进行认证。

const clientId = "<YOUR_CLIENT_ID>";
const redirectUri = "<YOUR_REDIRECT_URL>"; // 例如: "http://localhost/"

final _twitchClient = TwitchClient(
  clientId: clientId,
  redirectUri: redirectUri,
);

final _flutterWebviewPlugin = FlutterWebviewPlugin();

// 第一次通过 WebView 进行认证
Future<TwitchToken> _openConnectionPage({
  List<TwitchApiScope> scopes = const [],
}) {
  // 监听 URL 变化以检测重定向到我们的 redirectUri
  _flutterWebviewPlugin.onUrlChanged.listen((url) {
    if (url.startsWith(_twitchClient.redirectUri)) {
      // 到达 redirectUri 后初始化令牌
      _twitchClient.initializeToken(TwitchToken.fromUrl(url));

      // 关闭 WebView
      _flutterWebviewPlugin.close();
    }
  });

  // 当 WebView 关闭时弹出当前路由
  _flutterWebviewPlugin.onDestroy.listen((_) => Navigator.pop(context));

  // 获取授权 URL 以通过 WebView 进行连接
  final _url = _twitchClient.authorizeUri(scopes);

  return Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => WebViewPage(_url.toString()),
    ),
  ).then((_) => _twitchClient.twitchHttpClient.validateToken());
}

3. 支持的端点

以下是 twitch_api 插件目前支持的 Twitch API 端点:

  • 广告
    • ✅ 开始广告
  • 分析
    • ✅ 获取扩展分析
    • ✅ 获取游戏分析(文档正在编写中)
  • Bits
    • ✅ 获取 Bits 排行榜
    • ✅ 获取 Cheermotes
    • ✅ 获取扩展交易
  • 频道
    • ✅ 获取频道信息
    • ✅ 修改频道信息
    • ✅ 获取频道编辑者
  • 频道积分
    • ✅ 创建自定义奖励
    • ✅ 删除自定义奖励
    • ✅ 获取自定义奖励
    • ✅ 获取自定义奖励兑换
    • ✅ 更新自定义奖励
    • ✅ 更新兑换状态
  • 聊天
    • ✅ 获取频道表情
    • ✅ 获取全局表情
    • ✅ 获取表情集
    • ✅ 获取频道聊天徽章
    • ✅ 获取全局聊天徽章
    • ✅ 获取聊天设置
    • ❌ 更新聊天设置
  • 游戏
    • ✅ 获取热门游戏
    • ✅ 获取游戏
  • 搜索
    • ✅ 搜索分类
    • ✅ 搜索频道
    • ❌ 获取流密钥
    • ✅ 获取流
    • ❌ 创建流标记
    • ❌ 获取流标记
  • 订阅
    • ✅ 获取主播订阅
  • 用户
    • ✅ 获取用户
    • ❌ 更新用户
    • ✅ 获取用户关注
    • ❌ 创建用户关注
    • ❌ 删除用户关注
    • ❌ 获取用户屏蔽列表
    • ❌ 屏蔽用户
    • ❌ 解除屏蔽用户
    • ❌ 获取用户扩展
    • ❌ 获取用户激活的扩展
    • ❌ 更新用户扩展

4. 完整示例 Demo

以下是一个完整的示例应用程序,展示了如何使用 twitch_api 插件进行认证并调用各种 Twitch API 方法。

import 'package:example/webview_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:twitch_api/twitch_api.dart';

const clientId = 'MY_CLIENT_ID';
const redirectUri = 'http://localhost:8080/static.html';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  final _twitchClient = TwitchClient(clientId: clientId, redirectUri: redirectUri);
  final _flutterWebviewPlugin = FlutterWebviewPlugin();

  void _urlListener(String url) {
    if (url.startsWith(redirectUri)) {
      _twitchClient.initializeToken(TwitchToken.fromUrl(url));
      _flutterWebviewPlugin.close();
    }
  }

  // 第一次通过 WebView 进行认证
  Future<TwitchToken> _openConnectionPage({List<TwitchApiScope> scopes = const []}) {
    _flutterWebviewPlugin.onUrlChanged.listen(_urlListener);
    _flutterWebviewPlugin.onDestroy.listen((_) => Navigator.pop(context));

    // 获取授权 URL 以通过 WebView 进行连接
    final url = _twitchClient.authorizeUri(scopes);

    return Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => WebViewPage(url.toString()),
      ),
    ).then((_) => _twitchClient.twitchHttpClient.validateToken());
  }

  [@override](/user/override)
  void initState() {
    super.initState();
    WidgetsBinding.instance.scheduleFrameCallback((_) {
      _openConnectionPage(scopes: TwitchApiScope.values).then((value) => setState(() {}));
    });
  }

  void _displayDataAlert({
    String? method,
    String? data,
    bool isImg = false,
    bool? isOnline,
  }) {
    showDialog(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text(method ?? ''),
          content: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              if (isOnline != null)
                Text(
                  isOnline ? '在线' : '离线',
                  style: TextStyle(
                    color: isOnline ? Colors.green : Colors.red,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              if (!isImg && data != null) Text(data),
              if (isImg && data != null)
                Image.network(
                  data,
                  loadingBuilder: (_, __, ___) => const CircularProgressIndicator(),
                ),
            ],
          ),
        );
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView(
        children: <Widget>[
          Text(
            '欢迎用户: ${_twitchClient.twitchHttpClient.twitchToken?.userId}',
          ),
          Text(
            '您的 Twitch 令牌是: ${_twitchClient.twitchHttpClient.twitchToken?.token}',
          ),
          ElevatedButton(
            onPressed: () => _twitchClient
                .startCommercial(
              broadcasterId: _twitchClient.twitchHttpClient.twitchToken!.userId!,
              length: 60,
            )
                .catchError((error) {
              _displayDataAlert(
                method: 'startCommercial',
                data: error.toString(),
              );
              return error;
            }),
            child: const Text('开始广告'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient
                .getExtensionAnalytics(first: 1)
                .catchError((error) {
              _displayDataAlert(
                method: 'getExtensionAnalytics',
                data: error.toString(),
              );
              return error;
            }),
            child: const Text('获取扩展分析'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient
                .getGameAnalytics(gameId: '493057')
                .catchError((error) {
              _displayDataAlert(
                method: 'getGameAnalytics',
                data: error.toString(),
              );
              return error;
            }),
            child: const Text('获取游戏分析'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getUsersFollows(toId: '23161357').then(
                  (value) => _displayDataAlert(
                    method: 'getUsersFollows',
                    data: '总粉丝数: ${value.total}',
                  ),
                ),
            child: const Text('获取用户 23161357 的粉丝'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getUsers(ids: ['44322889']).then(
              (value) => _displayDataAlert(
                method: value.data.first.displayName,
                data: value.data.first.description,
              ),
            ),
            child: const Text('获取用户 Dallas 的信息'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getTopGames().then(
                  (value) => _displayDataAlert(
                    method: '热门游戏',
                    data: value.data.map<String>((e) => e.name).toList().join('\n'),
                  ),
                ),
            child: const Text('获取热门游戏'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getGames(names: ['Fortnite']).then(
              (value) => _displayDataAlert(
                method: value.data.first.name,
                data: value.data.first.getBoxArtUrl(),
                isImg: true,
              ),
            ),
            child: const Text('获取 Fortnite 游戏信息'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getChannelInformations('44445592').then(
                  (value) => _displayDataAlert(
                    method: value.data.first.broadcasterName,
                    data: value.data.first.title,
                  ),
                ),
            child: const Text('获取 Pokimane 频道信息'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getStreams(userLogins: ['auronplay']).then(
              (value) => _displayDataAlert(
                method: (value.data.isNotEmpty) ? value.data.first.userLogin : 'getStreams',
                data: '观众数: ${(value.data.isNotEmpty) ? value.data.first.viewerCount : "无数据"}',
                isOnline: (value.data.isNotEmpty) ? value.data.first.type == TwitchStreamType.live : false,
              ),
            ),
            child: const Text('获取 auronplay 的直播信息'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.searchChannels(query: 'loserfruit').then(
              (value) {
                _displayDataAlert(
                  method: value.data.first.displayName,
                  data: value.data.first.thumbnailUrl,
                  isImg: true,
                  isOnline: value.data.first.isLive,
                );
              },
            ),
            child: const Text('搜索 loserfruit 频道'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.searchCategories(query: 'fort').then(
                  (value) => _displayDataAlert(
                    method: value.data.first.name,
                    data: value.data.first.getBoxArtUrl(),
                    isImg: true,
                  ),
                ),
            child: const Text('搜索 "fort" 分类'),
          ),
          ElevatedButton(
            onPressed: () {
              final id = _twitchClient.twitchHttpClient.twitchToken?.userId;
              if (id != null) {
                _twitchClient
                    .getBroadcasterSubscriptions(broadcasterId: id)
                    .then(
                      (value) => _displayDataAlert(
                        method: value.data.first.userName,
                        data: value.data.first.tier,
                      ),
                    );
              }
            },
            child: const Text('获取主播订阅'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getBitsLeaderboard().then(
                  (value) => _displayDataAlert(
                    method: value.data.first.userName,
                    data: value.data.first.score.toString(),
                  ),
                ),
            child: const Text('获取 Bits 排行榜'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.getCheermotes().then(
                  (value) => _displayDataAlert(
                    method: value.data.first.prefix,
                    data: value.data.first.tiers.map((e) => e.id).toList().toString(),
                  ),
                ),
            child: const Text('获取 Cheermotes'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient.modifyChannelinformation(
              broadcasterId: _twitchClient.twitchHttpClient.twitchToken!.userId!,
              title: '测试',
            ),
            child: const Text('将频道标题修改为: 测试'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient
                .getChannelEditors(
                  broadcasterId: _twitchClient.twitchHttpClient.twitchToken!.userId!,
                )
                .then(
                  (value) => _displayDataAlert(
                    method: '您有 ${value.data.length} 位编辑者',
                    data: value.data.map<String>((e) => e.userName).join(', '),
                  ),
                ),
            child: const Text('获取您的频道编辑者'),
          ),
          ElevatedButton(
            onPressed: () => _twitchClient
                .getCustomRewards(
                  broadcasterId: _twitchClient.twitchHttpClient.twitchToken?.userId ?? '',
                )
                .then(
                  (value) => _displayDataAlert(
                    method: '获取自定义奖励',
                    data: value.data.map<String>((e) => e.title).join(', '),
                  ),
                ),
            child: const Text('获取自定义奖励'),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter Twitch API集成插件twitch_api的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Twitch API集成插件twitch_api的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter应用中使用twitch_api插件来集成Twitch API的代码案例。这个示例将展示如何初始化插件、获取Twitch用户信息以及处理可能的异常。

首先,确保你已经在pubspec.yaml文件中添加了twitch_api依赖:

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

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

接下来,你可以按照以下步骤在你的Flutter应用中使用twitch_api插件:

  1. 初始化Twitch API客户端

在你的主文件(通常是main.dart)中,你需要初始化TwitchApi客户端。这通常涉及到设置你的Twitch客户端ID和客户端密钥。

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

void main() {
  // 初始化TwitchApi客户端
  TwitchApi _twitchApi = TwitchApi(
    clientId: '你的Twitch客户端ID',
    clientSecret: '你的Twitch客户端密钥',
  );

  runApp(MyApp(_twitchApi));
}

class MyApp extends StatelessWidget {
  final TwitchApi twitchApi;

  MyApp(this.twitchApi);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Twitch API Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(twitchApi: twitchApi),
    );
  }
}
  1. 获取Twitch用户信息

在你的主页面(例如MyHomePage.dart)中,你可以使用TwitchApi客户端来获取用户信息。下面是一个简单的示例,展示如何获取一个特定用户的信息。

import 'package:flutter/material.dart';
import 'package:twitch_api/models/user.dart';
import 'package:twitch_api/twitch_api.dart';

class MyHomePage extends StatefulWidget {
  final TwitchApi twitchApi;

  MyHomePage({required this.twitchApi});

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late User? user;
  String? errorMessage;

  @override
  void initState() {
    super.initState();
    _getUserInfo('twitch用户名'); // 替换为你想查询的Twitch用户名
  }

  Future<void> _getUserInfo(String username) async {
    try {
      user = await widget.twitchApi.getUsers(usernames: [username]).first;
    } catch (e) {
      print(e);
      setState(() {
        errorMessage = '无法获取用户信息: ${e.message ?? '未知错误'}';
      });
    }

    if (mounted) {
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Twitch用户信息'),
      ),
      body: Center(
        child: user != null
            ? Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text('用户名: ${user!.displayName!}'),
                  Text('ID: ${user!.id!}'),
                  // 可以添加更多用户信息字段
                ],
              )
            : Text(errorMessage ?? '加载中...'),
      ),
    );
  }
}

在这个示例中,我们创建了一个MyHomePage类,它在initState方法中调用_getUserInfo函数来获取指定用户名的用户信息。获取到的用户信息被存储在user变量中,并在UI中显示。如果发生错误,错误消息将被存储在errorMessage变量中并显示。

请注意,上述代码中的getUsers方法返回的是一个List<User>,所以我们使用.first来获取列表中的第一个用户(假设我们只查询了一个用户名)。在实际应用中,你可能需要处理多个用户的情况或添加更多的错误处理逻辑。

此外,确保你已经在Twitch开发者门户中注册了你的应用,并获得了有效的客户端ID和客户端密钥。这些信息是访问Twitch API所必需的。

回到顶部