说明:
目前 Flutter 强绑定终端运行,如果已经有了 Android 或 iOS 的应用,请直接使用对应的 AppKey,如没有请创建时选择 Android 或 iOS 应用。
自动集成
1. 安装。
在项目的
pubspec.yaml
文件中添加 qapm_flutter
的依赖。# 在pubspec.yaml中加入dependencies:qapm_flutter: ^0.1.0
运行
flutter pub get
更新依赖。flutter pub get
2. 导入。
import 'package:qapm_flutter/qapm_flutter.dart';
配置原生支持
Android 平台
配置 Gradle
1. 在工程级的
build.gradle
文件下,增加maven 依赖
和qapm-plugin 插件
。buildscript {repositories {...// 添加maven源maven { url 'https://qapm-maven.pkg.coding.net/repository/qapm_sdk/android_release/' }...}dependencies {// 添加qapm-plugin插件classpath 'com.tencent.qapmplugin:qapm-plugin:3.4'}}allprojects {repositories {...// 添加maven源maven { url 'https://qapm-maven.pkg.coding.net/repository/qapm_sdk/android_release/' }...}}
说明:
如果您的 gradle 版本小于7.4,则将 qapm-plugin 插件版本改为2.39。
2. 在 app 的
build.gradle
文件下,增加 qapm-plugin
的引用。...// 引用插件apply plugin: "qapm-plugin"...// 添加自动生成UUID的TaskpreBuild.dependsOn(UUIDGenerator)
配置权限
在
AndroidMainfest.xml
文件中增加以下权限。<!--上报信息所需--><uses-permission android:name="android.permission.INTERNET" /><!--采集信息所需--><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
配置混淆
在
proguard
混淆配置文件中增加以下内容,避免打包报错或 SDK 不可用。-dontwarn com.tencent.cos.xml.** { *; }-dontwarn com.tencent.qcloud.** { *; }-dontwarn com.squareup.okhttp.** { *; }-dontwarn okhttp3.** { *; }-keep class com.tencent.qapmsdk.** { *; }-dontwarn com.tencent.qapmsdk.** { *; }
iOS 平台
在 iOS 的工程路径下,执行
pod install
更新依赖。pod
install
初始化 QAPM SDK
1. 为保证能够捕获全局的异常,建议您将应用的
void main() => runApp(MyApp());
替换成以下代码。如果您的工程是纯 flutter 开发,或者原生(Android 和 iOS)并没有接入 QAPM,则参考以下方式初始化 QAPM。
void main() {// 初始化QAPMQAPMBuilder builder = QAPMBuilder();// 目前AppKey还是沿用原生层的,所以这里需要在控制台创建对应平台的应用,并且分别设置if (Platform.isAndroid) {builder.appKey = "2b6f3f82-11907";} else if (Platform.isIOS) {builder.appKey = "26388a8d-3649";}builder.model = "HUAWEI"; // 设置手机型号builder.appVersion = "1.0"; // 设置原生应用版本,这里纯flutter开发可以和crossVersion填一样值,如是混合开发建议和原生侧协商builder.crossVersion = "1.0"; // 跨端的应用版本builder.deviceId = "uuid"; // 设置设备ID//目前上报的域名分为了三个不同的地址,分别是国内站、新加坡站、法兰克福站,根据实际需求选择一个环境上报即可//国内站:https://app.rumt-zh.com//新加坡站:https://app.rumt-sg.com//法兰克福站:https://eu-frankfurt.rumapp.tencentcs.combuilder.host = "https://app.rumt-zh.com"; // 设置上报域名builder.needLog = true; // 是否需要开启日志,release下建议关闭builder.userId = "11223344"; // 设置用户IDbuilder.funcSwitch = QAPM.MODE_CRASH; // 需要开启跨端的功能,这里目前仅支持crash// 确保去掉原有的WidgetsFlutterBinding.ensureInitialized() ,以免出现重复初始化绑定的异常造成无法正常初始化,SDK内部已通过initFlutterBinding入参带入继承的WidgetsFlutterBinding实现初始化操作builder.initFlutterBinding = MyApmWidgetsFlutterBinding.ensureInitialized;// 启动SDKQAPM.init(builder, () {runApp(MyApp());});}class MyApmWidgetsFlutterBinding extends QapmWidgetsFlutterBinding {@overridevoid handleAppLifecycleStateChanged(AppLifecycleState state) {// 添加自己的实现逻辑print('AppLifecycleState changed to $state');super.handleAppLifecycleStateChanged(state);}static WidgetsBinding? ensureInitialized() {MyApmWidgetsFlutterBinding();return WidgetsBinding.instance;}}
如果您的工程是原生 + Flutter 都需要使用 QAPM 的混合开发场景,则参考以下方式初始化 QAPM。
// 设置与原生通信的桥const channel = MethodChannel("com.example.flutter/qapm");void main() async {QAPMBuilder builder = QAPMBuilder();builder.needLog = true; // 是否需要开启日志,release下建议关闭builder.crossVersion = "1.0"; // 跨端的应用版本builder.funcSwitch = QAPM.MODE_CRASH; // 需要开启跨端的功能,这里目前仅支持crash// 确保去掉原有的WidgetsFlutterBinding.ensureInitialized() ,以免出现重复初始化绑定的异常造成无法正常初始化,SDK内部已通过initFlutterBinding入参带入继承的WidgetsFlutterBinding实现初始化操作builder.initFlutterBinding = MyApmWidgetsFlutterBinding.ensureInitialized;QAPM.init(builder, () {runApp(MyApp());}, beforeInitRunner: (builder) async {// 原生层通过channel,实现对应逻辑,并将对应值传递给flutter,需要确保原生和flutter初始化的参数一致!!!builder.appKey = await channel.invokeMethod("getAppKey") as String; // 目前AppKey还是沿用原生层的,所以这里需要在控制台创建对应平台的应用,并且分别设置builder.model = await channel.invokeMethod("getModel") as String; // 设置手机型号,需要跨端开发和原生开发协商,设置一致的值builder.appVersion = await channel.invokeMethod("getAppVersion") as String; // 设置原生应用版本,需要跨端开发和原生开发协商,设置一致的值builder.deviceId = await channel.invokeMethod("getDeviceId") as String; // 设置设备ID,需要跨端开发和原生开发协商,设置一致的值builder.host = await channel.invokeMethod("getHost") as String; // 设置上报域名,需要跨端开发和原生开发协商,设置一致的值builder.userId = await channel.invokeMethod("getUserId") as String; // 设置用户ID,需要跨端开发和原生开发协商,设置一致的值});}class MyApmWidgetsFlutterBinding extends QapmWidgetsFlutterBinding {@overridevoid handleAppLifecycleStateChanged(AppLifecycleState state) {// 添加自己的实现逻辑print('AppLifecycleState changed to $state');super.handleAppLifecycleStateChanged(state);}static WidgetsBinding? ensureInitialized() {MyApmWidgetsFlutterBinding();return WidgetsBinding.instance;}}
2. 在 App 中设置路由监听。
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {@overridevoid initState() {super.initState();}@overrideWidget build(BuildContext context) {return MaterialApp(home: Scaffold(appBar: AppBar(title: const Text('APM Example'),),body: Center(child: MyHome(),),),// 添加 QapmNavigatorObservernavigatorObservers: [QapmNavigatorObserver()],routes: {'MainPage': (context) => MainPage(),'FirstPage': (context) => FirstPage(),'SecondPage': (context) => SecondPage(),},);}}
如果是接入了
TRouter
等混合栈的路由框架,由于其接管了原生的 Navigator
,需要将 QapmNavigatorObserver
设置到混合栈框架中,代码如下:runApp(MaterialApp(home: TRouteContainer(navigatorObservers: QapmNavigatorObserver(),),));
注意:
TRouter 需要使用2.5.7+ 版本,否则部分生命周期会丢失。
验证接入是否成功
关键词搜索
QAPM_flutter
,如出现以下日志(Android 为例)
,说明初始化成功了。2025-01-06 21:29:35.330 20883-21019 flutter com....qapmsdk.qapm_flutter_example I [QAPM_flutter_CrashMonitor] [DEBUG] init FlutterExceptionHandler success
注意:
确保去掉原有的
WidgetsFlutterBinding.ensureInitialized()
,以免出现重复初始化绑定的异常造成无法正常初始化,SDK 内部已通过 initFlutterBinding 入参带入继承的 WidgetsFlutterBinding 实现初始化操作。请
正确设置路由监听
,否则可能采集不到页面,影响指标计算。请尽可能确保页面路由使用可读性强的名称,如 'MainPage': (context) => MainPage()。
如果您启用了 Dart 混淆,请保管好对应的符号表(Android 为 symbols,iOS 为 App.Framework.dSYM)文件,并在详情页面上根据指引将符号表上传。开启混淆后部分类、属性也会相应混淆,请将
--extra-gen-snapshot-options=--save-obfuscation-map
指令生产的符号文件一起上传。Android 上传符号表请参见 符号表配置。
iOS 上传符号表请参见 符号表配置。
如果原生也使用了QAPM,不需要再引入 QAPM 依赖,SDK 会直接使用 API 的方式让上层模块可以直接调用。