Flutter 应用场景

最近更新时间:2025-01-24 14:07:52

我的收藏
说明:
目前 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的Task
preBuild.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() {
// 初始化QAPM
QAPMBuilder 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.com
builder.host = "https://app.rumt-zh.com"; // 设置上报域名
builder.needLog = true; // 是否需要开启日志,release下建议关闭
builder.userId = "11223344"; // 设置用户ID
builder.funcSwitch = QAPM.MODE_CRASH; // 需要开启跨端的功能,这里目前仅支持crash
// 确保去掉原有的WidgetsFlutterBinding.ensureInitialized() ,以免出现重复初始化绑定的异常造成无法正常初始化,SDK内部已通过initFlutterBinding入参带入继承的WidgetsFlutterBinding实现初始化操作
builder.initFlutterBinding = MyApmWidgetsFlutterBinding.ensureInitialized;
// 启动SDK
QAPM.init(builder, () {
runApp(MyApp());
});
}

class MyApmWidgetsFlutterBinding extends QapmWidgetsFlutterBinding {
@override
void 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 {
@override
void 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 {

@override
void initState() {
super.initState();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('APM Example'),
),
body: Center(
child: MyHome(),
),
),
// 添加 QapmNavigatorObserver
navigatorObservers: [
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 的方式让上层模块可以直接调用。