集成基础:SDK集成方式与环境配置要点
咱们聊到Crash治理,第一步肯定是把SDK塞进项目里。这事儿看着简单,但我在实际项目中踩过的坑能绕办公室一圈。这章我就把Android、iOS、Web三端的集成套路给你捋一遍,外加那些环境配置里容易翻车的地方。
一、整体集成框架
先看一张图,帮你建立整体认识。SDK集成不是简单拷贝文件,它涉及引入依赖、初始化配置、权限申请、符号文件上传等环节。不同平台有各自的坑,但核心逻辑是通的。
二、Android SDK 集成实战
2.1 依赖引入方式
现在的Android项目多用Gradle。我习惯将SDK版本号统一写在项目级的ext块里,方便管理。直接在app/build.gradle中加入依赖:
dependencies {
implementation 'com.example.crashtracker:crash-sdk:2.1.0'
// 如果你需要NDK崩溃捕捉,加这个
implementation 'com.example.crashtracker:crash-sdk-native:2.1.0'
}
implementation 而非 compile,因为 Android Gradle Plugin 3.0+ 已经移除了 compile 关键字。我在老旧项目里亲眼见过 compile 导致依赖冲突的情况。
2.2 混淆配置与权限
ProGuard/R8 会把SDK的类名混淆掉,crash堆栈就完全看不懂了。你得在proguard-rules.pro里保留SDK相关类:
-keep class com.example.crashtracker.** { *; }
-keep class * implements com.example.crashtracker.CrashHandler { *; }
-dontwarn com.example.crashtracker.**
权限方面,Android 6.0以上需要动态申请读写存储权限(如果你要写本地日志的话)。但说实话,我更建议直接用SDK默认的内存日志方案,避免和用户隐私政策冲突。我曾经有个项目为了写本地日志,被用户暗地里投诉了三次。
2.3 初始化时机
SDK初始化必须在Application.onCreate()里尽早执行,越早越好。你想想看,如果主线程上有个空指针崩溃发生在初始化之前,那就抓不到了。我一般把它放在 super.onCreate() 之后第一行:
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
CrashSdk.init(this, new CrashConfig.Builder()
.setAppId("your_app_id")
.setDebug(BuildConfig.DEBUG)
.build());
}
}
ContentProvider 的 onCreate 里初始化。Android 多进程初始化顺序你猜不透,我见过有人在那里面初始化导致空指针——讽刺的是,自己的初始化代码反而产生了crash。
三、iOS SDK 集成要点
3.1 CocoaPods vs SPM
iOS现在主流是用CocoaPods或Swift Package Manager。我个人偏向SPM,因为Xcode原生支持,不需要额外装 Ruby 工具链。但如果你用的是ObjC混编项目,CocoaPods 可能更稳定。
用CocoaPods的话,Podfile里加一行:
pod 'CrashSDK', '~> 3.2.0'
用SPM的话,在Xcode里 File → Add Packages,输入仓库地址就行。注意选对版本规则,别用 "main" 分支,否则哪天SDK更新了你的编译就炸了。
3.2 初始化与符号化
iOS的初始化通常在AppDelegate的didFinishLaunchingWithOptions中:
import CrashSDK
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let config = CrashConfig(appId: "your_app_id")
CrashSDK.start(with: config)
return true
}
}
符号化是个大坑。iOS崩溃堆栈里全是地址,必须上传dSYM文件才能还原成函数名。我建议用脚本自动上传:在 Build Phases 里加一个 Run Script,每次Archive后自动执行。
四、Web SDK 集成方式
4.1 npm 安装 vs CDN
Web端最灵活。如果你的项目是React/Vue/Vite等现代框架,用npm安装:
npm install @crash-tracker/web-sdk --save
然后用导入方式初始化:
import { init } from '@crash-tracker/web-sdk';
init({
appId: 'your_web_app_id',
environment: process.env.NODE_ENV,
// 是否监控白屏和资源加载错误
monitorWhiteScreen: true
});
如果项目是传统JSP/ASP页面,直接用CDN script标签。但注意要放在页面顶部靠近head的位置,确保最早捕获错误。
4.2 跨域与SourceMap
Web端最头疼的是跨域脚本错误,堆栈显示 'Script error.' 什么信息都没有。解决方法是给script标签加 crossorigin 属性,并且CDN返回正确的 Access-Control-Allow-Origin 头。
另外,生产环境要上传SourceMap给SDK后台,这样压缩后的代码报错才能映射回原始源码。我通常用webpack插件自动上传:
new CrashSourceMapPlugin({
url: 'https://crash.yourdomain.com/upload',
appId: 'your_web_app_id'
})
五、环境配置通用要点
不管哪个平台,有几个配置逃不掉。我整理了一张表,方便你对照检查。
| 配置项 | 说明 | 常见错误 |
|---|---|---|
| AppKey / AppId | SDK用于标识你的应用,从后台获取 | 复制粘贴多了空格,调试半天看不出 |
| Debug模式开关 | 开发时设为true,能看到SDK日志;线上必须false | 有人忘了关,导致用户端也在打印敏感日志 |
| 渠道标识 | 区分不同发布渠道(应用宝、华为、App Store) | 渠道名用了中文,导致后台统计乱码 |
| 上报策略 | 实时/间隔/仅WiFi上传等 | 默认实时可能导致用户流量暴增 |
| 符号文件上传 | Android的mapping.txt / iOS的dSYM / Web的SourceMap | 忘记上传,crash堆栈全是地址 |
嗯,有一点需要特别提醒:测试环境不要和线上用同一个AppId。你会把开发阶段的试错crash和线上真实crash混在一起,根本没法分析。我一般建三个项目:Dev、Staging、Production,各配不同的AppId。
六、验证集成是否成功
集成完了,怎么确认SDK真的工作了?不能等到用户出问题才发现没上报吧。
- Android:写一个按钮,点击后执行
Integer.parseInt(null)或throw new RuntimeException("test")。看后台有没有收到这条crash。 - iOS:用
NSArray *arr = @[]; arr[1]触发越界。记得只在Debug包做测试,别带到Release里。 - Web:直接在控制台执行
undefined.xxx触发TypeError,等几秒看后台日志。
最后说一句:集成本身不复杂,复杂的是那些你意想不到的边界情况——比如用户手机空间不足、网络被屏蔽、权限被系统强杀。这些我们后面章节会细讲。先把基础集成跑通,才算真正迈出Crash治理第一步。