Flutter SDK 接入指南

在 Flutter 应用中集成 xxinstall_flutter 归因 SDK,支持 iOS 和 Android。

概述

xxinstall_flutter 是 XXinstall 的 Flutter 归因 SDK,通过 Platform Plugin 桥接原生编译代码(AAR + XCFramework),核心逻辑在原生层运行。

SDK 核心逻辑(签名算法、指纹采集、HTTP 请求)以编译后的二进制分发(Android AAR + iOS XCFramework),Dart 层仅为薄壳调用。

安装

方式一:下载托管包(推荐)

下载 SDK 包并放到项目中:

# 下载
curl -O https://www.xxinstall.org/sdk/xxinstall_flutter-1.0.0.tar.gz

# 解压到项目同级目录(或 packages/ 等任意位置)
tar xzf xxinstall_flutter-1.0.0.tar.gz

pubspec.yaml 中引用本地路径:

dependencies:
  xxinstall_flutter:
    path: ../xxinstall_flutter  # 根据实际路径调整

方式二:Git 引用

dependencies:
  xxinstall_flutter:
    git:
      url: https://github.com/your-org/weiwei-guiyin.git
      path: packages/xxinstall_flutter

安装依赖:

flutter pub get

快速开始

import 'package:xxinstall_flutter/xxinstall_flutter.dart';

// 1. 设置 API 地址(全局,只需调用一次)
await XXinstall.setHost('https://your-api-domain.com');

// 2. 初始化并获取归因结果
final result = await XXinstall.init(
  appKey: 'YOUR_APP_KEY',
  appSecret: 'YOUR_APP_SECRET',
);

print('归因结果: ${result.matchType}');
print('邀请码: ${result.inviteCode}');
print('渠道: ${result.channel}');

完整示例

import 'package:flutter/material.dart';
import 'package:xxinstall_flutter/xxinstall_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await XXinstall.setHost('https://your-api-domain.com');
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  AttributionResult? _result;
  String _status = '初始化中...';

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

  Future<void> _initAttribution() async {
    try {
      final result = await XXinstall.init(
        appKey: 'YOUR_APP_KEY',
        appSecret: 'YOUR_APP_SECRET',
        debug: true,
      );
      setState(() {
        _result = result;
        _status = '归因完成: ${result.matchType}';
      });
    } catch (e) {
      setState(() => _status = '归因失败: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('XXinstall Demo')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(_status),
              if (_result != null) ...[
                Text('邀请码: ${_result!.inviteCode ?? "无"}'),
                Text('渠道: ${_result!.channel}'),
                Text('置信度: ${_result!.confidence}'),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

API

XXinstall.setHost(url)

设置 API 服务器地址。必须在 init() 之前调用。

await XXinstall.setHost('https://your-api-domain.com');

XXinstall.setDebug(enabled)

开启或关闭调试日志输出。

await XXinstall.setDebug(true);

XXinstall.init(...)

初始化 SDK 并执行归因匹配。返回 Future<AttributionResult>

final result = await XXinstall.init(
  appKey: 'YOUR_APP_KEY',
  appSecret: 'YOUR_APP_SECRET',
);
参数类型必填说明
appKeyString应用 Key,在管理后台创建
appSecretString应用 Secret,用于签名
baseUrlString?API 地址(优先于 setHost)
deviceIdString?自定义设备 ID
debugbool是否输出调试日志(默认 false)
skipCachebool跳过缓存,强制重新归因(默认 false)
skipClipboardbool跳过剪贴板读取(默认 false)
skipWebViewbool跳过内置 WebView 指纹采集(默认 false)

XXinstall.getAttribution()

获取缓存的归因结果(不发起网络请求)。

final result = await XXinstall.getAttribution();
if (result != null) {
  print('缓存的归因结果: ${result.matchType}');
}

XXinstall.clearCache()

清除本地缓存的归因结果。下次调用 init() 会重新发起归因请求。

await XXinstall.clearCache();

XXinstall.trackEvent(...)

上报自定义事件。

await XXinstall.trackEvent(
  appKey: 'YOUR_APP_KEY',
  appSecret: 'YOUR_APP_SECRET',
  eventName: 'register',
  eventType: 4,           // 4=注册, 6=付费, 7=自定义
  userId: 'user_123',
  channel: 'wechat',
);
参数类型必填说明
appKeyString应用 Key
appSecretString应用 Secret
eventNameString事件名称
eventTypeint事件类型,默认 7(1=下载 2=安装 3=打开 4=注册 5=自定义 6=付费)
deviceIdString?设备 ID
userIdString?用户 ID
inviteCodeString?邀请码
channelString?渠道标识
eventParamsMap?自定义参数

类型定义

class AttributionResult {
  final String? inviteCode;  // 邀请码
  final String channel;      // 渠道
  final String matchType;    // clipboard | fingerprint | ipua | direct | none
  final double confidence;   // 置信度 (0-1)
  final String scene;        // 场景标识
}