Flutter应用发布管理插件appcenter_release_manager的使用
Flutter应用发布管理插件appcenter_release_manager的使用
appcenter_release_manager
是一个用于从您的 iOS 或 Android 应用中直接下载 AppCenter 更新的 Flutter 插件。以下是如何使用该插件的详细说明。
使用预定义的UI
您可以使用 AppcenterReleaseManagerLatestReleases
小部件来显示最新的应用更新信息。API Token 应该具有只读权限。
AppcenterReleaseManagerLatestReleases(
apiToken: 'your-api-token',
ownerName: 'your-owner-name',
appName: 'your-app-name',
)
创建自定义UI
如果您想创建自定义的UI,可以使用 AppCenterReleaseManager
类作为仓库或服务。API Token 应该具有只读权限。
AppCenterReleaseManager(
apiToken: 'your-api-token',
)
通过URL或发布详情安装
通过发布详情安装
final details = await AppCenterReleaseManager(apiToken: 'your-api-token').getLatestReleaseDetails('owner_name', 'app_name');
AppCenterReleaseManager(apiToken: 'your-api-token').installRelease(details, openAndroidInstallScreen: true, keepAndroidNotification: false);
通过URL安装
final details = await AppCenterReleaseManager(apiToken: 'your-api-token').getLatestReleaseDetails('owner_name', 'app_name');
AppCenterReleaseManager(apiToken: 'your-api-token').installReleaseByUrl(details.installUrl, appName: 'your-app-name', appVersion: 'your-version', openAndroidInstallScreen: true, keepAndroidNotification: false);
安装选项
openAndroidInstallScreen
:在 Android 上,这将在下载完成后打开安装屏幕。在 iOS 上此选项无效。keepAndroidNotification
:在 Android 上,这将在下载完成后保留通知。在 iOS 上此选项无效。如果openAndroidInstallScreen
设置为false
,则keepAndroidNotification
会自动设置为true
。
全权限访问
如果您希望按所有者拆分所有内容,需要提供一个全权限 API Token。
其他可用方法
API Token 应该具有只读权限。
AppCenterReleaseManager(apiToken: 'your-api-token').getUserDetails(); //全局 API Token 仅限
AppCenterReleaseManager(apiToken: 'your-api-token').getAllOrganizations(); //全局 API Token 仅限
AppCenterReleaseManager(apiToken: 'your-api-token').getAllApps(); //全局 API Token 仅限
AppCenterReleaseManager(apiToken: 'your-api-token').getAllApps(ownerName: 'owner_name'); //全局 API Token 仅限
AppCenterReleaseManager(apiToken: 'your-api-token').getReleases('owner_name', 'app_name'); //全局/应用 API Token 仅限
AppCenterReleaseManager(apiToken: 'your-api-token').getReleaseDetails('owner_name', 'app_name', 'id'); //全局/应用 API Token 仅限
AppCenterReleaseManager(apiToken: 'your-api-token').getLatestReleaseDetails('owner_name', 'app_name'); //全局/应用 API Token 仅限
Android 生产环境
此包自动为 Android 8 及以上版本添加了一个额外的权限来安装应用程序。
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
对于大多数情况,您不希望在生产环境中使用此权限。要移除此权限,请在 AndroidManifest.xml
中添加以下行:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your-package-name">
<uses-permission
android:name="android.permission.REQUEST_INSTALL_PACKAGES"
tools:node="remove" />
</manifest>
通常情况下,您会将此代码放在:
/android/app/src/release/AndroidManifest.xml
但如果您使用了 prod
、alpha
、beta
等构建变体,可能需要将其放在:
/android/app/src/prod/AndroidManifest.xml
这样可以确保在 prod
构建变体中移除该权限,而在 beta
和 alpha
构建变体中仍然可以安装更新。
示例代码
以下是一个完整的示例代码,展示了如何使用 appcenter_release_manager
插件。
import 'package:appcenter_release_manager/appcenter_release_manager.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var _index = 0;
late AppCenterReleaseManager _appCenterReleaseManager;
@override
void initState() {
super.initState();
_appCenterReleaseManager = AppCenterReleaseManager(apiToken: 'your-api-token');
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle.light,
title: const Text('AppCenter App'),
),
body: IndexedStack(
index: _index,
children: [
OwnerList(appCenterReleaseManager: _appCenterReleaseManager),
AppList(appCenterReleaseManager: _appCenterReleaseManager),
AppCenterReleaseManagerLatestReleases(
apiToken: _appCenterReleaseManager.apiToken,
ownerName: 'your-owner-name',
appName: 'your-app-name',
),
UserDetails(appCenterReleaseManager: _appCenterReleaseManager),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _index,
onTap: (value) => setState(() => _index = value),
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
showSelectedLabels: true,
showUnselectedLabels: true,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.group),
label: 'Owners',
),
BottomNavigationBarItem(
icon: Icon(Icons.list),
label: 'Apps',
),
BottomNavigationBarItem(
icon: Icon(Icons.description),
label: 'Latest Releases',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'User Details',
),
],
),
),
);
}
}
class UserDetails extends StatefulWidget {
final AppCenterReleaseManager appCenterReleaseManager;
const UserDetails({
required this.appCenterReleaseManager,
super.key,
});
@override
State<UserDetails> createState() => _UserDetailsState();
}
class _UserDetailsState extends State<UserDetails> {
User? _user;
@override
void initState() {
super.initState();
_getUserDetails();
}
@override
Widget build(BuildContext context) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
Text('Name: ${_user?.name}'),
Text('displayName: ${_user?.displayName}'),
Text('origin: ${_user?.origin}'),
Text('avatarUrl: ${_user?.avatarUrl}'),
Text('createdAt: ${_user?.createdAt}'),
Text('canChangePassword: ${_user?.canChangePassword}'),
],
);
}
Future<void> _getUserDetails() async {
_user = await widget.appCenterReleaseManager.getUserDetails();
setState(() {});
}
}
class OwnerList extends StatefulWidget {
final AppCenterReleaseManager appCenterReleaseManager;
const OwnerList({
required this.appCenterReleaseManager,
super.key,
});
@override
State<OwnerList> createState() => _OwnerListState();
}
class _OwnerListState extends State<OwnerList> {
var _list = <Owner>[];
@override
void initState() {
super.initState();
_getApps();
}
Future<void> _getApps() async {
_list = await widget.appCenterReleaseManager.getAllOrganizations();
setState(() {});
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _list.length,
itemBuilder: (context, index) {
final item = _list[index];
return ListTile(
leading: Container(
width: 64,
height: 64,
padding: const EdgeInsets.all(4),
child: item.avatarUrl == null
? const Placeholder()
: Image.network(item.avatarUrl!),
),
title: Text(item.name),
onTap: () => Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => OwnerAppList(
appCenterReleaseManager: widget.appCenterReleaseManager,
owner: item,
),
),
),
);
},
);
}
}
class OwnerAppList extends StatefulWidget {
final AppCenterReleaseManager appCenterReleaseManager;
final Owner owner;
const OwnerAppList({
required this.appCenterReleaseManager,
required this.owner,
super.key,
});
@override
State<OwnerAppList> createState() => _OwnerAppListState();
}
class _OwnerAppListState extends State<OwnerAppList> {
var _list = <App>[];
@override
void initState() {
super.initState();
_getApps();
}
Future<void> _getApps() async {
_list = await widget.appCenterReleaseManager.getAllApps(ownerName: widget.owner.name);
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle.light,
title: Text(widget.owner.name),
),
body: ListView.builder(
itemCount: _list.length,
itemBuilder: (context, index) {
final item = _list[index];
return ListTile(
leading: Container(
width: 64,
height: 64,
padding: const EdgeInsets.all(4),
child: item.iconUrl == null
? const Placeholder()
: Image.network(item.iconUrl!),
),
title: Text(item.name),
onTap: () => Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => AppDetail(
appCenterReleaseManager: widget.appCenterReleaseManager,
app: item,
),
),
),
);
},
),
);
}
}
class AppList extends StatefulWidget {
final AppCenterReleaseManager appCenterReleaseManager;
const AppList({
required this.appCenterReleaseManager,
super.key,
});
@override
State<AppList> createState() => _AppListState();
}
class _AppListState extends State<AppList> {
var _list = <App>[];
@override
void initState() {
super.initState();
_getApps();
}
Future<void> _getApps() async {
_list = await widget.appCenterReleaseManager.getAllApps();
setState(() {});
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _list.length,
itemBuilder: (context, index) {
final item = _list[index];
return ListTile(
leading: Container(
width: 64,
height: 64,
padding: const EdgeInsets.all(4),
child: item.iconUrl == null
? const Placeholder()
: Image.network(item.iconUrl!),
),
title: Text(item.name),
onTap: () => Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => AppDetail(
appCenterReleaseManager: widget.appCenterReleaseManager,
app: item,
),
),
),
);
},
);
}
}
class AppDetail extends StatefulWidget {
final AppCenterReleaseManager appCenterReleaseManager;
final App app;
const AppDetail({
required this.appCenterReleaseManager,
required this.app,
super.key,
});
@override
State<AppDetail> createState() => _AppDetailState();
}
class _AppDetailState extends State<AppDetail> {
var _list = <Release>[];
@override
void initState() {
super.initState();
_getApps();
}
Future<void> _getApps() async {
final name = widget.app.owner?.name;
if (name == null) return;
_list = await widget.appCenterReleaseManager.getReleases(name, widget.app.name);
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle.light,
title: Text(widget.app.name),
),
body: ListView.builder(
itemCount: _list.length,
itemBuilder: (context, index) {
final item = _list[index];
return ListTile(
title: Text('${item.shortVersion} (${item.version})'),
subtitle: Text(item.uploadedAt?.toIso8601String() ?? ''),
onTap: () => Navigator.of(context).push<void>(
MaterialPageRoute(
builder: (context) => ReleaseDetailScreen(
appCenterReleaseManager: widget.appCenterReleaseManager,
app: widget.app,
release: item,
),
),
),
);
},
),
);
}
}
class ReleaseDetailScreen extends StatefulWidget {
final AppCenterReleaseManager appCenterReleaseManager;
final App app;
final Release release;
const ReleaseDetailScreen({
required this.appCenterReleaseManager,
required this.app,
required this.release,
super.key,
});
@override
State<ReleaseDetailScreen> createState() => _ReleaseDetailScreenState();
}
class _ReleaseDetailScreenState extends State<ReleaseDetailScreen> {
ReleaseDetail? _details;
@override
void initState() {
super.initState();
_getApps();
}
Future<void> _getApps() async {
final name = widget.app.owner?.name;
if (name == null) return;
_details = await widget.appCenterReleaseManager.getReleaseDetails(name, widget.app.name, widget.release.id);
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle.light,
title: Text(widget.app.name),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: _details == null
? []
: [
Text(_details!.uploadedAt?.toIso8601String() ?? ''),
Text('${_details!.shortVersion} (${_details!.version})'),
MaterialButton(
color: Colors.blue,
onPressed: () => widget.appCenterReleaseManager.installRelease(
_details!,
openAndroidInstallScreen: true,
keepAndroidNotification: true,
),
child: const Text(
'Install',
style: TextStyle(color: Colors.white),
),
),
],
),
);
}
}
以上代码展示了如何使用 appcenter_release_manager
插件来管理应用的发布和更新。希望对您有所帮助!
更多关于Flutter应用发布管理插件appcenter_release_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter应用发布管理插件appcenter_release_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 appcenter_release_manager
插件在 Flutter 应用中进行发布管理的代码示例。这个插件允许你通过 Microsoft App Center 管理应用的发布。
首先,确保你已经在 pubspec.yaml
文件中添加了 appcenter_release_manager
依赖项:
dependencies:
flutter:
sdk: flutter
appcenter_release_manager: ^最新版本号 # 请替换为实际的最新版本号
然后,运行 flutter pub get
以获取依赖项。
初始化 App Center
在你的 Flutter 应用中,你需要初始化 App Center。这通常在 main.dart
或一个初始化文件中完成。
import 'package:flutter/material.dart';
import 'package:appcenter_release_manager/appcenter_release_manager.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 App Center
await AppCenterReleaseManager.install(
appId: '你的AppCenter应用ID',
secret: '你的AppCenter应用密钥',
debug: false, // 生产环境中设置为false
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter AppCenter Release Manager Example'),
),
body: Center(
child: Text('Check the console for release updates!'),
),
),
);
}
}
监听版本更新
你可以使用 AppCenterReleaseManager.addListener
方法来监听版本更新事件。
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 初始化 App Center
await AppCenterReleaseManager.install(
appId: '你的AppCenter应用ID',
secret: '你的AppCenter应用密钥',
debug: false, // 生产环境中设置为false
);
// 添加监听器
AppCenterReleaseManager.addListener((event) {
if (event is ReleaseUpdateAvailableEvent) {
// 处理版本更新可用事件
print('A new release is available: ${event.releaseNotes}');
// 显示对话框或导航到更新页面
} else if (event is ReleaseDownloadProgressEvent) {
// 处理下载进度事件
print('Download progress: ${event.progress}%');
} else if (event is ReleaseInstalledEvent) {
// 处理版本安装完成事件
print('New release installed successfully.');
// 可以重新启动应用
} else if (event is ReleaseErrorEvent) {
// 处理错误事件
print('Error occurred: ${event.error.message}');
}
});
runApp(MyApp());
}
强制检查更新
你可以在需要的时候调用 AppCenterReleaseManager.checkForUpdates()
方法来强制检查更新。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter AppCenter Release Manager Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Check the console for release updates!'),
ElevatedButton(
onPressed: () async {
// 强制检查更新
await AppCenterReleaseManager.checkForUpdates();
},
child: Text('Check for Updates'),
),
],
),
),
),
);
}
}
注意事项
- 安全性:确保你的
appId
和secret
不要硬编码在客户端代码中,最好通过安全的后端服务获取。 - 用户体验:在提示用户更新时,确保有良好的用户体验,比如提供取消选项,或者在下载和安装过程中提供明确的进度反馈。
- 测试:在发布到生产环境之前,务必在测试环境中充分测试发布管理功能。
通过上述代码示例,你应该能够在 Flutter 应用中成功集成和使用 appcenter_release_manager
插件进行发布管理。