Flutter Strava API集成插件strava_client的使用
Flutter Strava API集成插件strava_client的使用
概述
strava_flutter
是一个用于在Dart/Flutter项目中调用Strava API v3的包。它遵循最新的认证流程,允许开发者轻松地与Strava的各种API进行交互。
警告: 该包正在经历大规模重构,未来更新可能会引入破坏性变更。
支持的API
认证相关API
authorize
deauthorize
运动员相关API
getLoggedInAthlete
updateLoggedInAthlete
(需要profile:write
权限)getLoggedInAthleteActivities
getLoggedInAthleteZones
getGearById
getStats
俱乐部相关API
getClubById
getClubActivitiesById
getClubMembersById
赛事相关API
getRunningRaces
getRunningRaceById
活动相关API
createActivity
uploadActivity
(包括getUploadById
)测试了TCX和GPX格式的支持
为了生成TCX文件,可以使用 rw_tcx 包。
段落相关API
getSegmentById
getLoggedInAthleteStarredSegments
getLeaderboardBySegmentId
starSegment
安装方法
请参考 pub.dev 上提供的安装指南。
Android Pie (9.0, API level 28) 额外步骤
如果遇到net::ERR_CLEARTEXT_NOT_PERMITTED
错误,请在AndroidManifest.xml
中添加如下配置:
<application
...
android:usesCleartextTraffic="true"
...>
使用说明
-
在Strava设置页面获取客户端密钥,并将“Authorization Callback Domain”设为
redirect
。 -
设置URL Scheme以便处理来自Strava认证的重定向URL:
- 对于Android,在
AndroidManifest.xml
中添加以下代码:
同时修改<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="stravaflutter" android:host="redirect" /> </intent-filter>
launchMode
为singleInstance
以确保Firefox下的正常工作。 - 对于iOS,在
info.plist
中添加以下内容:
如果需要启动本地Strava应用进行认证,还需添加:<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>stravaflutter</string> <key>CFBundleURLSchemes</key> <array> <string>stravaflutter</string> </array> </dict> </array>
<key>LSApplicationQueriesSchemes</key> <array> <string>strava</string> </array>
- 对于Android,在
-
创建
secret.dart
文件并保存您的client secret
和appID
:final String secret = "[Your client secret]"; final String clientId = "[Your appID]";
-
在需要使用这些值的地方导入
secret.dart
。 -
若要查看调试信息,可以在初始化
StravaClient
时将isInDebug
设为true
。 -
参考示例代码了解具体用法。
示例代码
下面是一个简单的Flutter应用程序示例,演示了如何使用strava_flutter
进行用户登录、登出以及显示访问令牌:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:strava_client/strava_client.dart';
import 'secret.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Strava Flutter',
theme: ThemeData(primarySwatch: Colors.blue),
home: StravaFlutterPage(),
);
}
}
class StravaFlutterPage extends StatefulWidget {
@override
_StravaFlutterPageState createState() => _StravaFlutterPageState();
}
class _StravaFlutterPageState extends State<StravaFlutterPage> {
final TextEditingController _textEditingController = TextEditingController();
final DateFormat dateFormatter = DateFormat("HH:mm:ss");
late final StravaClient stravaClient;
bool isLoggedIn = false;
TokenResponse? token;
@override
void initState() {
super.initState();
stravaClient = StravaClient(secret: secret, clientId: clientId);
}
FutureOr<void> showErrorMessage(dynamic error, dynamic stackTrace) async {
if (error is Fault) {
await showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text("Did Receive Fault"),
content: Text(
"Message: ${error.message}\n-----------------\nErrors:\n${(error.errors ?? []).map((e) => "Code: ${e.code}\nResource: ${e.resource}\nField: ${e.field}\n").join("\n----------\n")}",
),
),
);
}
}
void testAuthentication() {
ExampleAuthentication(stravaClient).testAuthentication(
[
AuthenticationScope.profile_read_all,
AuthenticationScope.read_all,
AuthenticationScope.activity_read_all
],
"stravaflutter://redirect",
).then((token) {
setState(() {
isLoggedIn = true;
this.token = token;
});
_textEditingController.text = token.accessToken;
}).catchError(showErrorMessage);
}
void testDeauth() {
ExampleAuthentication(stravaClient).testDeauthorize().then((value) {
setState(() {
isLoggedIn = false;
this.token = null;
_textEditingController.clear();
});
}).catchError(showErrorMessage);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter Strava Plugin"),
actions: [
Icon(
Icons.radio_button_checked_outlined,
color: isLoggedIn ? Colors.white : Colors.red,
),
SizedBox(width: 8,)
],
),
body: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [_login(), _apiGroups()],
),
),
);
}
Widget _login() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
child: Text("Login With Strava"),
onPressed: testAuthentication,
),
ElevatedButton(
child: Text("De Authorize"),
onPressed: testDeauth,
)
],
),
SizedBox(height: 8,),
TextField(
minLines: 1,
maxLines: 3,
controller: _textEditingController,
decoration: InputDecoration(
border: OutlineInputBorder(),
label: Text("Access Token"),
suffixIcon: TextButton(
child: Text("Copy"),
onPressed: () {
Clipboard.setData(ClipboardData(text: _textEditingController.text))
.then((value) => ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Copied!"))));
},
),
),
),
Divider()
],
);
}
Widget _apiGroups() {
return IgnorePointer(
ignoring: !isLoggedIn,
child: AnimatedOpacity(
opacity: isLoggedIn ? 1.0 : 0.4,
duration: Duration(milliseconds: 200),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(title: Text("Athletes"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Clubs"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Gears"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Routes"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Running Races"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Segment Efforts"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Segments"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Streams"), trailing: Icon(Icons.chevron_right),),
ListTile(title: Text("Uploads"), trailing: Icon(Icons.chevron_right),)
],
),
),
);
}
}
以上就是关于strava_flutter
插件的基本介绍及其在Flutter项目中的使用方法。希望这对您有所帮助!如果您有任何问题或需要实现其他API功能,请随时提出新问题。
更多关于Flutter Strava API集成插件strava_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter Strava API集成插件strava_client的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中集成并使用strava_client
插件来与Strava API进行交互的代码示例。这个示例将展示如何初始化插件、获取用户授权以及调用Strava API获取活动列表。
首先,确保你已经在pubspec.yaml
文件中添加了strava_client
依赖:
dependencies:
flutter:
sdk: flutter
strava_client: ^最新版本号 # 替换为实际可用的最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目中,你需要进行以下步骤:
- 配置Strava API客户端:
在你的android/app/src/main/AndroidManifest.xml
文件中,确保你有必要的互联网权限:
<uses-permission android:name="android.permission.INTERNET" />
在你的ios/Runner/Info.plist
文件中,你可能需要配置一些额外的权限或设置,具体取决于你的应用需求。
- 初始化Strava客户端:
在你的Flutter项目的lib
目录下,创建一个新的Dart文件(例如strava_service.dart
),并在其中初始化Strava客户端:
import 'package:flutter/material.dart';
import 'package:strava_client/strava_client.dart';
class StravaService {
late StravaClient _stravaClient;
StravaService(String clientId, String clientSecret, String redirectUri) {
_stravaClient = StravaClient(
clientId: clientId,
clientSecret: clientSecret,
redirectUri: redirectUri,
);
}
// 获取用户授权URL
Future<String> getAuthorizationUrl() async {
return _stravaClient.getAuthorizationUrl();
}
// 使用授权码获取访问令牌
Future<AccessToken> getAccessToken(String code) async {
return await _stravaClient.getAccessToken(code);
}
// 获取用户活动列表
Future<List<Activity>> getActivities(AccessToken accessToken) async {
return await accessToken.activities.getAthleteActivities();
}
}
- 在UI中使用Strava服务:
在你的主Dart文件(例如main.dart
)中,使用StravaService
来管理Strava API的交互:
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart'; // 用于打开浏览器
import 'strava_service.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late StravaService _stravaService;
String? _authorizationUrl;
List<Activity>? _activities;
@override
void initState() {
super.initState();
_stravaService = StravaService(
clientId: '你的Strava客户端ID',
clientSecret: '你的Strava客户端密钥',
redirectUri: '你的重定向URI',
);
// 获取授权URL
_getAuthorizationUrl();
}
Future<void> _getAuthorizationUrl() async {
setState(() {
_authorizationUrl = await _stravaService.getAuthorizationUrl();
});
}
Future<void> _handleAuthorizationResponse(String code) async {
try {
AccessToken accessToken = await _stravaService.getAccessToken(code);
_activities = await accessToken.activities.getAthleteActivities();
} catch (e) {
print('Error fetching access token: $e');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Strava API Integration'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (_authorizationUrl != null)
ElevatedButton(
onPressed: () async {
// 打开授权URL
if (await canLaunch(_authorizationUrl!)) {
await launch(_authorizationUrl!,
forceWebView: true,
webViewConfiguration: WebViewConfiguration(
javascriptMode: JavaScriptMode.unrestricted,
)
);
// 假设授权后重定向回你的应用,并附带授权码
// 在这里你需要处理重定向,并调用_handleAuthorizationResponse
// 这通常涉及设置一个URI监听器或深度链接处理
// 由于这是一个示例,我们直接模拟一个授权码
String fakeAuthorizationCode = '假设的授权码';
_handleAuthorizationResponse(fakeAuthorizationCode);
}
},
child: Text('获取授权'),
),
if (_activities != null)
ListView.builder(
shrinkWrap: true,
itemCount: _activities!.length,
itemBuilder: (context, index) {
Activity activity = _activities![index];
return ListTile(
title: Text('活动名称: ${activity.name}'),
subtitle: Text('活动日期: ${activity.startDateLocal}'),
);
},
),
],
),
),
),
);
}
}
注意:
- 在真实应用中,处理重定向和提取授权码的过程会更复杂。你可能需要设置URI监听器或使用深度链接来捕获重定向后的URL,并从中提取授权码。
- 在这个示例中,我们直接使用了一个“假设的授权码”,这在实际应用中是不可行的。
- 你需要确保在Strava开发者门户中正确配置了你的重定向URI,并且你的应用有权限访问所需的数据。
- 由于
url_launcher
插件用于打开浏览器,你可能需要在pubspec.yaml
文件中添加该依赖:url_launcher: ^最新版本号
。
希望这个示例能帮助你在Flutter项目中集成Strava API。