Flutter应用列表检测插件applist_detector_flutter的使用
Flutter应用列表检测插件applist_detector_flutter的使用
A Flutter端口库用于检测可疑应用,如Magisk管理器、Xposed框架、异常环境、运行模拟器等。该库用Kotlin和Dart编写。
这并不是一个由Google官方支持的产品
截图
![]() |
![]() |
![]() |
![]() |
---|
| | 您可以使用我们的应用 Security Tester,它是一个直接UI实现/示例库。 |
平台支持
Android | iOS | MacOS | Web | Linux | Windows |
---|---|---|---|---|---|
✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
特性
-
检查系统文件中的可疑文件。
-
检查可疑设置属性,如调试属性、VPN使用情况等。
-
检查运行可疑应用的异常环境,如Magisk、Riru或Zygisk。
-
检查应用是否在模拟器上运行,例如Genymotion、Bluestacks、Windows子系统等。
注意: 这个功能不是100%准确的。但比其他库如
device_info_plus
或safe_device
更准确。 -
检查Xposed框架是否已安装。
-
使用Play Integrity API检查,帮助保护您的应用和游戏免受潜在的风险和欺诈性交互,如作弊和未经授权的访问,并允许您采取适当的措施来防止攻击和减少滥用。
贡献
欢迎通过创建问题或拉取请求来贡献此项目。任何帮助都将被感激❤️。更多信息请查看 CONTRIBUTING.md 文件。
TODO
这些是我们计划在未来添加的功能。
- 完成 CONTRIBUTING.md 指南。
- 添加更多针对Xposed框架的检查。
- 添加对iOS的支持。
- 添加100%文档覆盖率。
- 添加100%测试覆盖率。
信用
- 1nikolas/play-integrity-checker-app
- 1nikolas/play-integrity-checker-server
- Dr-TSNG/ApplistDetector
- byxiaorun/Ruru
- scottyab/rootbeer
- fluttercommunity/plus_plugins/tree/main/packages/device_info_plus/device_info_plus
- ufukhawk/safe_device
免责声明
该工具旨在帮助用户轻松保护其应用,并且 不是100%无懈可击的。如果您正在寻找100%安全的解决方案,那么这不是正确的工具。该工具不应用于任何非法或恶意活动。仅将其用于良好用途。对于因使用此工具而造成的任何损害,我概不负责。
许可证
该库根据Apache 2.0许可证分发。更多详情请参阅 LICENSE DETAILS。
示例代码
import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:applist_detector_flutter/applist_detector_flutter.dart';
import './utils.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Applist Detector Flutter',
theme: ThemeData(
useMaterial3: true,
colorScheme: lightColorScheme,
),
darkTheme: ThemeData.dark(useMaterial3: true).copyWith(
colorScheme: darkColorScheme,
),
home: const HomeScreen(),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
[@override](/user/override)
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final _plugin = ApplistDetectorFlutter();
bool isLoading = false;
List<ResultWrapper> results = [];
Set<ResultWrapper> selected = {};
[@override](/user/override)
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
_startTests();
});
}
void _startTests() async {
try {
final tests = [
buildWrapper("Abnormal Environment", process: () {
return _plugin.abnormalEnvironment();
}),
buildWrapper("Libc File Detection", process: () {
return _plugin.fileDetection();
}),
buildWrapper("Syscall File Detection", process: () {
return _plugin.fileDetection(useSysCall: true);
}),
buildWrapper("Xposed Framework", process: () {
return _plugin.xposedFramework();
}),
buildWrapper("Xposed Modules", process: () {
return _plugin.xposedModules();
}),
buildWrapper("LS Patch Xposed Modules", process: () {
return _plugin.xposedModules(lspatch: true);
}),
buildWrapper("Magisk App", process: () {
return _plugin.magiskApp();
}),
buildWrapper("PM Command", process: () {
return _plugin.pmCommand();
}),
buildWrapper("PM Conventional APIs", process: () {
return _plugin.pmConventionalAPIs();
}),
buildWrapper("PM Sundry APIs", process: () {
return _plugin.pmSundryAPIs();
}),
buildWrapper("PM QueryIntentActivities", process: () {
return _plugin.pmQueryIntentActivities();
}),
buildWrapper("Settings Props", process: () {
return _plugin.settingsProps();
}),
buildWrapper("Running Emulator", process: () {
return _plugin.emulatorCheck();
}),
buildWrapper("RootBear Checks", process: () {
return _plugin.checkRootBeer();
}),
];
results = await Future.wait(tests);
} catch (e, t) {
log("ERROR Init", error: e, stackTrace: t);
} finally {
if (mounted) {
setState(() {
isLoading = false;
});
}
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Applist Detector Flutter'),
elevation: 0,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() => isLoading = true);
_startTests();
},
child: const Icon(Icons.refresh),
),
body: SafeArea(
child: Builder(
builder: (context) {
if (isLoading) {
return const SizedBox(
width: double.infinity,
height: 50,
child: Center(
child: CircularProgressIndicator(),
),
);
}
return ListView(
children: [
Wrap(
runSpacing: 10,
spacing: 5,
children: DetectorResultType.values.map((type) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(width: 10),
icons[type] ?? const SizedBox.shrink(),
const SizedBox(width: 5),
Text(labels[type] ?? "-"),
],
);
}).toList(),
),
const SizedBox(height: 10),
if (results.isEmpty) ...[
const SizedBox.square(
dimension: 50,
child: Center(
child: CircularProgressIndicator(),
),
)
],
ExpansionPanelList(
dividerColor: Colors.transparent,
expansionCallback: (index, isExpanded) {
final item = results[index];
if (isExpanded) {
selected.remove(item);
} else {
selected.add(item);
}
if (mounted) {
setState(() {});
}
},
children: results.map((e) {
final isExpanded = selected.contains(e);
return buildExpPanel(
e,
testName: e.testName,
isExpanded: isExpanded,
);
}).toList(),
),
const SizedBox(height: 80)
],
);
},
),
),
);
}
static const Map<DetectorResultType, Widget> icons = {
DetectorResultType.notFound: Icon(Icons.done),
DetectorResultType.found: Icon(Icons.coronavirus, color: Colors.red),
DetectorResultType.suspicious: Icon(Icons.visibility),
DetectorResultType.methodUnavailable: Icon(Icons.code_off),
};
static const Map<DetectorResultType, String> labels = {
DetectorResultType.notFound: "Not Found",
DetectorResultType.found: "Found",
DetectorResultType.suspicious: "Suspicious",
DetectorResultType.methodUnavailable: "Method Unavailable",
};
ExpansionPanel buildExpPanel(
ResultWrapper wrapper, {
required String testName,
bool isExpanded = false,
}) {
final details = wrapper.result.details;
final type = wrapper.result.type;
final error = wrapper.error;
return ExpansionPanel(
isExpanded: isExpanded,
headerBuilder: (context, isExpanded) {
return ListTile(
leading: error != null
? const Icon(Icons.error, color: Colors.red)
: icons[type],
title: Text(testName),
trailing: Text(error != null ? "ERROR" : ""),
subtitle: Text(labels[type] ?? "Unknown"),
);
},
body: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 10,
).add(const EdgeInsets.only(bottom: 15)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: details.entries.map((e) {
return Row(
children: [
icons[e.value]!,
const SizedBox(width: 10),
Expanded(child: Text(e.key)),
],
);
}).toList(),
),
if (error != null) ...[
const SizedBox(height: 10),
Text(error.toString()),
],
],
),
),
);
}
}
更多关于Flutter应用列表检测插件applist_detector_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter应用列表检测插件applist_detector_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
applist_detector_flutter
是一个用于检测设备上已安装应用程序列表的 Flutter 插件。它可以帮助开发者获取设备上安装的应用程序信息,并根据需要进行处理。以下是如何使用 applist_detector_flutter
插件的基本步骤:
1. 添加依赖
首先,在你的 pubspec.yaml
文件中添加 applist_detector_flutter
插件的依赖:
dependencies:
flutter:
sdk: flutter
applist_detector_flutter: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来获取依赖。
2. 导入插件
在你的 Dart 文件中导入插件:
import 'package:applist_detector_flutter/applist_detector_flutter.dart';
3. 获取已安装应用程序列表
使用 AppListDetectorFlutter
类来获取设备上已安装的应用程序列表。以下是一个简单的示例:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('AppList Detector Example'),
),
body: Center(
child: FutureBuilder<List<AppInfo>>(
future: AppListDetectorFlutter.getInstalledApps(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return Text('No apps found');
} else {
List<AppInfo> apps = snapshot.data!;
return ListView.builder(
itemCount: apps.length,
itemBuilder: (context, index) {
AppInfo app = apps[index];
return ListTile(
title: Text(app.appName),
subtitle: Text(app.packageName),
leading: Icon(Icons.apps),
);
},
);
}
},
),
),
),
);
}
}
4. 处理权限
在某些设备上,获取已安装应用程序列表可能需要特定的权限。请确保在 Android 的 AndroidManifest.xml
文件中添加以下权限:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>