Flutter安卓包管理插件android_package_manager的使用
Flutter安卓包管理插件android_package_manager的使用
简介
android_package_manager
插件为 Flutter 应用提供了访问 Android 原生 PackageManager
API 的能力,可以获取各种信息,如已安装的应用程序、包、权限等。
关于此插件
该插件仅适用于 Android。它提供了对 Android PackageManager
API 最常用方法的更简单访问。部分方法改编自现有的 package_manager
插件,但该插件似乎最近没有维护。
开始使用
导入插件
import 'package:android_package_manager/android_package_manager.dart';
单例访问示例
final pm = AndroidPackageManager();
可用方法
请参阅官方文档 PackageManager API。
免责声明: 我尝试适应大多数可用的方法,并进行了一些简单的仪器测试。测试过的方法可以在 example/integration_test
目录下找到。
示例 Flutter 应用演示了 getInstalledPackages
方法的使用。
注意事项
请注意某些方法中的 flags
可选参数。这些参数会影响请求 API 的输出。例如,如果未指定 GET_PERMISSIONS
标志,则 PackageInfo
不会显示任何权限信息。
可选权限
默认情况下,从 Android 11(API 级别 30)开始,已安装应用列表是有限的。更多详细信息请参阅 这里。要访问设备上安装的所有应用的完整列表,请在 AndroidManifest.xml
文件中添加以下权限:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
待办事项
- 完善文档
- 添加 DartDocs
- 调整一些方法以兼容 Android Tiramisu(弃用一些方法)
- 文档化位掩码值
- 将接口分离到单独的包中(可能)
问题
如果您有任何问题或建议,请在此处提交 issues
示例代码
以下是一个完整的示例代码,展示了如何使用 android_package_manager
插件获取已安装的包信息并显示在 Flutter 应用中。
main.dart
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:android_package_manager/android_package_manager.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MainPage(),
);
}
}
class MainPage extends StatefulWidget {
const MainPage({Key? key}) : super(key: key);
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
List<PackageInfo>? _applicationInfoList;
@override
void initState() {
super.initState();
final flags = PackageInfoFlags({
PMFlag.getMetaData,
PMFlag.getPermissions,
PMFlag.getReceivers,
PMFlag.getServices,
PMFlag.getProviders,
});
_pm.getInstalledPackages(flags: flags).then(
(value) => setState(() => _applicationInfoList = value),
);
}
@override
Widget build(BuildContext context) {
final appInfo = _applicationInfoList;
return Scaffold(
appBar: AppBar(
title: const Text("Android Package Manager Demo"),
),
body: ListView.builder(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 32.0),
itemBuilder: (_, index) {
final info = appInfo![index];
return Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0),
child: _PackageEntry(info: info),
);
},
itemCount: appInfo?.length ?? 0,
),
);
}
AndroidPackageManager get _pm => AndroidPackageManager();
}
class _Permissions extends StatelessWidget {
const _Permissions({required this.permissions});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(child: Text('Permissions (${permissions.length})')),
TextButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (_) => BottomSheet(
onClosing: () {},
builder: (_) {
return SizedBox(
height: MediaQuery.sizeOf(context).height * 0.5,
child: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 16),
itemBuilder: (_, i) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text('[${i + 1}] ${permissions[i]}'),
);
},
separatorBuilder: (_, __) => const Divider(height: 16),
itemCount: permissions.length,
),
);
},
),
);
},
child: const Text(
'Show',
style: TextStyle(decoration: TextDecoration.underline),
),
),
],
);
}
final List<String> permissions;
}
class _Receivers extends StatelessWidget {
const _Receivers({required this.receivers});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(child: Text('Receivers (${receivers.length})')),
TextButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (_) => BottomSheet(
onClosing: () {},
builder: (_) {
return SizedBox(
height: MediaQuery.sizeOf(context).height * 0.5,
child: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 16),
itemBuilder: (_, i) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text('[${i + 1}] ${receivers[i].name}'),
);
},
separatorBuilder: (_, __) => const Divider(height: 16),
itemCount: receivers.length,
),
);
},
),
);
},
child: const Text(
'Show',
style: TextStyle(decoration: TextDecoration.underline),
),
),
],
);
}
final List<ActivityInfo> receivers;
}
class _Services extends StatelessWidget {
const _Services({required this.services});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(child: Text('Services (${services.length})')),
TextButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (_) => BottomSheet(
onClosing: () {},
builder: (_) {
return SizedBox(
height: MediaQuery.sizeOf(context).height * 0.5,
child: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 16),
itemBuilder: (_, i) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text('[${i + 1}] ${services[i].name}'),
);
},
separatorBuilder: (_, __) => const Divider(height: 16),
itemCount: services.length,
),
);
},
),
);
},
child: const Text(
'Show',
style: TextStyle(decoration: TextDecoration.underline),
),
),
],
);
}
final List<ServiceInfo> services;
}
class _Providers extends StatelessWidget {
const _Providers({required this.providers});
@override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(child: Text('Providers (${providers.length})')),
TextButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (_) => BottomSheet(
onClosing: () {},
builder: (_) {
return SizedBox(
height: MediaQuery.sizeOf(context).height * 0.5,
child: ListView.separated(
padding: const EdgeInsets.symmetric(vertical: 16),
itemBuilder: (_, i) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text('[${i + 1}] ${providers[i].name}'),
);
},
separatorBuilder: (_, __) => const Divider(height: 16),
itemCount: providers.length,
),
);
},
),
);
},
child: const Text(
'Show',
style: TextStyle(decoration: TextDecoration.underline),
),
),
],
);
}
final List<ProviderInfo> providers;
}
class _AppIcon extends StatelessWidget {
const _AppIcon({required this.info});
@override
Widget build(BuildContext context) {
return FutureBuilder<Uint8List?>(
future: info.applicationInfo?.getAppIcon(),
builder: (context, snapshot) {
if (snapshot.hasData) {
final iconBytes = snapshot.data!;
return Image.memory(iconBytes, fit: BoxFit.fill);
}
if (snapshot.hasError) {
return const Icon(Icons.error, color: Colors.red);
}
return const SizedBox.shrink();
},
);
}
final PackageInfo info;
}
class _AppLabel extends StatelessWidget {
const _AppLabel({required this.info});
@override
Widget build(BuildContext context) {
return FutureBuilder<String?>(
future: AndroidPackageManager().getApplicationLabel(packageName: info.packageName!),
builder: (context, snapshot) => Text(snapshot.data ?? "No Name"),
);
}
final PackageInfo info;
}
class _PackageEntry extends StatelessWidget {
const _PackageEntry({required this.info});
@override
Widget build(BuildContext context) {
return Card(
child: ListTile(
leading: SizedBox.square(dimension: 48.0, child: _AppIcon(info: info)),
title: _AppLabel(info: info),
subtitle: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('${info.packageName} (${info.longVersionCode ?? info.versionCode})'),
Builder(
builder: (_) {
final permissions = info.requestedPermissions;
if (permissions == null || permissions.isEmpty) {
return const SizedBox.shrink();
}
return _Permissions(permissions: permissions);
},
),
Builder(
builder: (_) {
final receivers = info.receivers;
if (receivers == null || receivers.isEmpty) {
return const SizedBox.shrink();
}
return _Receivers(receivers: receivers);
},
),
Builder(
builder: (_) {
final services = info.services;
if (services == null || services.isEmpty) {
return const SizedBox.shrink();
}
return _Services(services: services);
},
),
Builder(
builder: (_) {
final providers = info.providers;
if (providers == null || providers.isEmpty) {
return const SizedBox.shrink();
}
return _Providers(providers: providers);
},
),
],
),
),
),
);
}
final PackageInfo info;
}
以上代码展示了如何使用 android_package_manager
插件获取已安装的包信息,并在 Flutter 应用中显示这些信息。希望这对您有所帮助!
更多关于Flutter安卓包管理插件android_package_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter安卓包管理插件android_package_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用android_package_manager
插件的示例代码案例。android_package_manager
插件允许你在Flutter应用中管理和查询已安装的Android应用包信息。
首先,确保你已经在pubspec.yaml
文件中添加了android_package_manager
依赖:
dependencies:
flutter:
sdk: flutter
android_package_manager: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
接下来,你需要处理Android平台的特定权限配置。在你的android/app/src/main/AndroidManifest.xml
文件中,添加以下权限(如果需要访问敏感信息):
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
<!-- 其他配置 -->
</manifest>
注意:PACKAGE_USAGE_STATS
权限需要用户手动授予,因此你可能需要在应用中引导用户前往设置页面授予权限。
现在,你可以在你的Flutter代码中使用android_package_manager
插件。以下是一个简单的示例,展示如何获取已安装应用列表:
import 'package:flutter/material.dart';
import 'package:android_package_manager/android_package_manager.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<PackageInfo> _installedPackages = [];
@override
void initState() {
super.initState();
_getInstalledPackages();
}
Future<void> _getInstalledPackages() async {
try {
final packageManager = AndroidPackageManager();
List<PackageInfo> packages = await packageManager.getAllPackages();
setState(() {
_installedPackages = packages;
});
} catch (e) {
print("Error getting installed packages: $e");
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Installed Packages'),
),
body: ListView.builder(
itemCount: _installedPackages.length,
itemBuilder: (context, index) {
final package = _installedPackages[index];
return ListTile(
title: Text(package.packageName),
subtitle: Text(package.label),
);
},
),
),
);
}
}
在这个示例中,我们创建了一个Flutter应用,该应用在启动时获取所有已安装的应用包信息,并将它们显示在一个列表中。每个列表项显示应用的包名和标签(即应用的显示名称)。
请注意,AndroidPackageManager
类的具体方法和属性可能会随着插件版本的更新而变化,因此请参考最新的插件文档以获取准确的信息。
此外,由于PACKAGE_USAGE_STATS
权限的敏感性,在实际应用中处理权限请求时,应遵循最佳实践,确保用户体验和隐私安全。