Flutter Twitch API集成插件twitch_api的使用
Flutter Twitch API集成插件twitch_api的使用
1. 简介
twitch_api
是一个纯 Dart 的包装库,用于通过 OAuth 隐式认证连接到 Twitch.tv。它实现了 Twitch API 参考中定义的所有端点。
2. 入门指南
2.1 注册应用
要使用此插件,您需要在 Twitch 开发者控制台 注册一个应用以获取 客户端 ID。
2.2 初始化 TwitchClient
注册应用后,您需要使用 clientId
和 redirectUri
实例化 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
更多关于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
插件:
- 初始化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),
);
}
}
- 获取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所必需的。