21、通知的点击统计:通过PendingIntent传递统计参数、BroadcastReceiver统计点击、Firebase Analytics集成
通知发出去,用户点没点?点了哪个?这是每个做推送的工程师都绕不开的问题。说实话,我见过太多团队把通知发得满天飞,结果一问点击率,全凭感觉猜。这不行。
今天我们就来聊聊通知点击统计这件事。我会把三种主流方案都讲透:通过PendingIntent传参、BroadcastReceiver拦截统计、以及接入Firebase Analytics。这三种方案各有适用场景,我建议你根据项目实际情况灵活组合。
核心观点:通知点击统计不是可选项,而是推送系统的标配。没有统计,你根本不知道推送效果如何,更别提优化了。
方案一:通过PendingIntent传递统计参数
这是最基础、也是最直接的方式。说白了,就是在构建通知的时候,把统计需要的参数塞进Intent里,用户点击通知后,在目标Activity里取出来上报。
我个人习惯用campaign_id来标识每次推送活动。你想想看,如果没有这个ID,你根本不知道用户点的是哪一次推送。
// 构建通知时传入统计参数
Intent intent = new Intent(context, NotificationClickActivity.class);
intent.putExtra("campaign_id", "campaign_2024_001");
intent.putExtra("push_type", "promotion");
intent.putExtra("timestamp", System.currentTimeMillis());
PendingIntent pendingIntent = PendingIntent.getActivity(
context,
requestCode,
intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("限时优惠")
.setContentText("今日全场8折,点击查看")
.setContentIntent(pendingIntent)
.setAutoCancel(true);
小提示:Android 12 以上要求显式声明 FLAG_IMMUTABLE 或 FLAG_MUTABLE。我建议大部分场景用 FLAG_IMMUTABLE,除非你需要修改Intent里的数据。
然后在目标Activity里解析参数并上报:
public class NotificationClickActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 解析统计参数
Intent intent = getIntent();
if (intent != null) {
String campaignId = intent.getStringExtra("campaign_id");
String pushType = intent.getStringExtra("push_type");
long timestamp = intent.getLongExtra("timestamp", 0L);
// 上报点击事件
reportNotificationClick(campaignId, pushType, timestamp);
}
// 跳转到真正的目标页面
navigateToTargetPage();
finish();
}
private void reportNotificationClick(String campaignId, String pushType, long timestamp) {
// 这里可以调用自己的统计SDK,或者埋点到本地日志
Log.d("NotificationStats", "点击统计: campaign=" + campaignId
+ ", type=" + pushType + ", time=" + timestamp);
// 实际项目中通常会调用统计SDK
// AnalyticsTracker.trackEvent("notification_click", params);
}
}
注意:如果用户从最近任务列表重启Activity,getIntent()返回的还是启动时的Intent。这时候你需要判断一下,避免重复上报。我一般会在SharedPreferences里记录已上报的campaign_id+timestamp组合。
方案二:BroadcastReceiver统计点击
这个方案我特别喜欢,因为它不依赖Activity。什么意思呢?就是即使用户点击通知时App被杀死了,BroadcastReceiver也能被唤醒,完成统计后再决定要不要启动Activity。
我曾经在一个日活千万级的项目里用过这个方案。当时遇到一个坑:通知点击后Activity启动太慢,统计上报延迟严重。换成BroadcastReceiver后,统计几乎实时完成。
// 1. 定义 BroadcastReceiver
public class NotificationClickReceiver extends BroadcastReceiver {
private static final String ACTION_NOTIFICATION_CLICK =
"com.example.action.NOTIFICATION_CLICK";
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_NOTIFICATION_CLICK.equals(intent.getAction())) {
String campaignId = intent.getStringExtra("campaign_id");
String pushType = intent.getStringExtra("push_type");
// 立即统计点击
Log.d("NotificationStats", "BroadcastReceiver 统计: " + campaignId);
// 上报到统计服务
reportClick(campaignId, pushType);
// 然后启动真正的目标Activity
Intent targetIntent = new Intent(context, TargetActivity.class);
targetIntent.putExtras(intent.getExtras());
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(targetIntent);
}
}
private void reportClick(String campaignId, String pushType) {
// 这里可以调用OkHttp直接上报,或者用WorkManager延迟上报
// 我建议用WorkManager,保证上报成功
}
}
// 2. 动态注册(推荐在Application中注册)
public class MyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
NotificationClickReceiver receiver = new NotificationClickReceiver();
IntentFilter filter = new IntentFilter(NotificationClickReceiver.ACTION_NOTIFICATION_CLICK);
registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED);
}
}
// 3. 构建通知时使用 Broadcast PendingIntent
Intent clickIntent = new Intent(NotificationClickReceiver.ACTION_NOTIFICATION_CLICK);
clickIntent.setPackage(context.getPackageName());
clickIntent.putExtra("campaign_id", "campaign_2024_002");
clickIntent.putExtra("push_type", "reminder");
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
requestCode,
clickIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
);
关键区别:PendingIntent.getActivity 启动Activity,而 PendingIntent.getBroadcast 发送广播。广播接收器在onReceive里可以立即执行统计逻辑,不受Activity生命周期影响。
方案三:Firebase Analytics集成
如果你的项目已经接入了Firebase,那直接用Firebase Analytics做通知点击统计是最省事的。它自带自动归因功能,能帮你把点击和转化关联起来。
我记得第一次用Firebase做推送统计时,发现它连用户从点击到下单的完整路径都能追踪。说实话,这比自己埋点省了太多事。
// 1. 在build.gradle中添加依赖
// implementation 'com.google.firebase:firebase-analytics:21.5.0'
// implementation 'com.google.firebase:firebase-messaging:23.4.0'
// 2. 在通知点击时记录事件
public class NotificationClickActivity extends AppCompatActivity {
private FirebaseAnalytics firebaseAnalytics;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
firebaseAnalytics = FirebaseAnalytics.getInstance(this);
Intent intent = getIntent();
if (intent != null) {
String campaignId = intent.getStringExtra("campaign_id");
// Firebase 自动归因参数
Bundle params = new Bundle();
params.putString(FirebaseAnalytics.Param.CAMPAIGN, campaignId);
params.putString(FirebaseAnalytics.Param.MEDIUM, "push_notification");
params.putString(FirebaseAnalytics.Param.SOURCE, "firebase");
// 记录通知打开事件
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.NOTIFICATION_OPEN, params);
// 也可以记录自定义事件
// firebaseAnalytics.logEvent("custom_notification_click", params);
}
}
}
// 3. 在Firebase控制台查看报表
// 路径: Analytics -> 事件 -> notification_open
// 可以看到点击次数、点击率、以及后续的转化数据
技巧:Firebase Analytics 的 notification_open 事件是系统预定义的,会自动关联推送归因。但如果你需要更细粒度的统计,建议用自定义事件,比如 "promotion_notification_click" 带上商品ID。
三种方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| PendingIntent传参 | 实现简单,无需额外组件 | 依赖Activity生命周期,App被杀可能丢失 | 小型项目、快速验证 |
| BroadcastReceiver | 独立于Activity,统计及时 | 需要动态注册,Android 8+限制隐式广播 | 中大型项目、对统计实时性要求高 |
| Firebase Analytics | 自动归因,报表完善,无需自建后端 | 依赖Google服务,国内需要特殊处理 | 海外项目、已接入Firebase的项目 |
我的实战建议
嗯,这里我想分享一些踩坑后的经验:
- 不要只用一种方案。我建议用BroadcastReceiver做核心统计,同时把参数传给Activity做二次校验。这样即使广播没收到,Activity还能补报。
- 注意去重。用户可能多次点击同一条通知。我习惯在统计时加一个
click_id(UUID),服务端根据这个ID去重。 - 国内环境要备选方案。Firebase在国内不稳定。我一般在海外版用Firebase,国内版用自建统计+友盟/极光。
- 测试要覆盖极端情况。我曾经遇到过通知点击后App被系统杀死,统计还没上报就丢了。后来用WorkManager加了一个兜底上报任务,才彻底解决。
一句话总结:通知点击统计的核心就两件事——把参数传到位、把事件报上去。至于用哪种方式,取决于你的项目规模和网络环境。但不管用哪种,一定要做。
公众号:蓝海资料掘金营,微信deep3321