一、引言

在开发 Android 应用时,推送通知是一个非常重要的功能。它能让应用及时向用户传递信息,像新闻更新、订单状态变化等等。但推送通知的可靠性和到达率常常让人头疼,很多开发者都遇到过用户收不到通知的情况。今天咱们就来聊聊怎么解决这个问题,主要说说 FCM 集成和自定义推送通道优化。

二、Android 推送通知概述

1. 什么是推送通知

推送通知就是应用在后台给用户发送消息,不管用户有没有打开应用,消息都会显示在手机的通知栏里。比如你在电商应用上下了个订单,订单发货了,应用就会给你推送一条通知,告诉你订单的状态。

2. 推送通知的重要性

推送通知能提高用户的活跃度和留存率。想象一下,你经常用的新闻应用,每天定时给你推送最新的新闻,你就会更频繁地打开这个应用,看看有什么新消息。而且,推送通知还能让用户及时了解应用的重要信息,提升用户体验。

3. 可靠性和到达率的问题

可靠性指的是推送通知能不能准确地发送到用户的设备上,到达率就是成功发送到用户设备的通知数量占总发送数量的比例。这两个指标很重要,如果可靠性和到达率不高,用户就可能错过重要的消息,对应用的满意度也会降低。

三、FCM 集成

1. 什么是 FCM

FCM 全名叫 Firebase Cloud Messaging,是 Google 提供的一个跨平台的消息传递解决方案。它能让开发者轻松地向 Android、iOS 和 Web 应用发送通知和数据消息。

2. FCM 集成步骤

步骤 1:创建 Firebase 项目

首先,你得去 Firebase 控制台创建一个项目。打开 https://console.firebase.google.com/ ,点击“添加项目”,按照提示填好项目名称、国家等信息,然后点击“创建项目”。

步骤 2:添加 Android 应用到项目

在 Firebase 控制台里,点击“添加应用”,选择 Android。然后填写应用的包名,这个包名要和你 Android 项目里的包名一致。接着下载 google-services.json 文件,把它放到你 Android 项目的 app 目录下。

步骤 3:配置项目

在项目的 build.gradle 文件里添加 Firebase 插件:

// 技术栈:Android Gradle
// 在项目根目录的 build.gradle 文件中添加
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        // 添加 Firebase 插件
        classpath 'com.google.gms:google-services:4.3.10'
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

app 模块的 build.gradle 文件里添加 FCM 依赖:

// 技术栈:Android Gradle
// 在 app 模块的 build.gradle 文件中添加
apply plugin: 'com.google.gms.google-services'

dependencies {
    // 添加 FCM 依赖
    implementation 'com.google.firebase:firebase-messaging:23.0.6'
}

步骤 4:实现 FirebaseMessagingService

创建一个类继承自 FirebaseMessagingService,重写 onMessageReceivedonNewToken 方法:

// 技术栈:Java
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        // 处理接收到的消息
        if (remoteMessage.getNotification() != null) {
            String title = remoteMessage.getNotification().getTitle();
            String body = remoteMessage.getNotification().getBody();
            // 显示通知
            showNotification(title, body);
        }
    }

    @Override
    public void onNewToken(String token) {
        // 处理新的设备令牌
        sendRegistrationToServer(token);
    }

    private void showNotification(String title, String body) {
        // 显示通知的代码
    }

    private void sendRegistrationToServer(String token) {
        // 将设备令牌发送到服务器的代码
    }
}

AndroidManifest.xml 里注册这个服务:

<!-- 技术栈:Android XML -->
<service
    android:name=".MyFirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

3. FCM 的优缺点

优点

  • 跨平台支持:可以同时向 Android、iOS 和 Web 应用发送消息,方便开发者统一管理。
  • 可靠性高:Google 的服务器有很好的稳定性和可靠性,能保证消息的准确送达。
  • 功能丰富:支持通知消息、数据消息,还能进行消息的定时发送、分组发送等。

缺点

  • 依赖 Google 服务:在一些没有 Google 服务的地区,可能无法正常使用 FCM。
  • 配置相对复杂:需要在 Firebase 控制台进行一系列的配置,对于新手来说可能有一定难度。

4. 注意事项

  • 确保 google-services.json 文件的配置正确,包名要和项目里的一致。
  • 处理好设备令牌的更新,及时将新的令牌发送到服务器。
  • 遵守 Firebase 的使用规则,不要发送违规的消息。

四、自定义推送通道优化

1. 什么是推送通道

推送通道就是消息从服务器发送到用户设备的路径。在 Android 8.0 及以上版本,系统引入了通知渠道的概念,开发者可以自定义不同的推送通道,为不同类型的通知设置不同的优先级、声音、震动等。

2. 自定义推送通道的步骤

步骤 1:创建通知通道

在 Android 8.0 及以上版本,使用 NotificationChannel 类创建通知通道:

// 技术栈:Java
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;

public class NotificationUtils {

    public static final String CHANNEL_ID_IMPORTANT = "important_channel";
    public static final String CHANNEL_ID_NORMAL = "normal_channel";

    public static void createNotificationChannels(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 创建重要通知通道
            NotificationChannel importantChannel = new NotificationChannel(
                    CHANNEL_ID_IMPORTANT,
                    "重要通知",
                    NotificationManager.IMPORTANCE_HIGH
            );
            importantChannel.setDescription("重要通知,会有声音和震动");

            // 创建普通通知通道
            NotificationChannel normalChannel = new NotificationChannel(
                    CHANNEL_ID_NORMAL,
                    "普通通知",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            normalChannel.setDescription("普通通知,无声音和震动");

            // 获取通知管理器
            NotificationManager manager = context.getSystemService(NotificationManager.class);
            // 创建通知通道
            manager.createNotificationChannel(importantChannel);
            manager.createNotificationChannel(normalChannel);
        }
    }
}

在应用启动时调用 createNotificationChannels 方法:

// 技术栈:Java
import android.app.Application;

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        NotificationUtils.createNotificationChannels(this);
    }
}

AndroidManifest.xml 里注册 MyApplication

<!-- 技术栈:Android XML -->
<application
    android:name=".MyApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    ...
</application>

步骤 2:使用通知通道发送通知

// 技术栈:Java
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;

public class NotificationSender {

    public static void sendNotification(Context context, String channelId, String title, String body) {
        NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        Notification.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder = new Notification.Builder(context, channelId);
        } else {
            builder = new Notification.Builder(context);
        }

        builder.setContentTitle(title)
               .setContentText(body)
               .setSmallIcon(R.drawable.ic_notification);

        Notification notification = builder.build();
        manager.notify(1, notification);
    }
}

调用 sendNotification 方法发送通知:

// 技术栈:Java
NotificationSender.sendNotification(this, NotificationUtils.CHANNEL_ID_IMPORTANT, "重要消息", "这是一条重要的通知");

3. 自定义推送通道的优点

  • 提高用户体验:用户可以根据自己的需求选择是否接收某些类型的通知,避免被过多的通知打扰。
  • 提高到达率:对于重要的通知,可以设置高优先级,确保用户能及时收到。

4. 注意事项

  • 不同的通知通道要设置合理的优先级和提示方式,避免给用户造成困扰。
  • 在创建通知通道时,要注意通道的 ID 和名称不能重复。

五、应用场景

1. 新闻类应用

新闻类应用可以使用 FCM 集成和自定义推送通道优化,将最新的新闻推送给用户。对于重要的新闻,可以使用高优先级的通知通道,确保用户能及时看到。

2. 电商类应用

电商类应用可以推送订单状态变化、促销活动等信息。对于订单发货、支付成功等重要信息,使用重要通知通道;对于普通的促销活动,可以使用普通通知通道。

3. 社交类应用

社交类应用可以推送新消息、好友请求等通知。对于新消息,可以设置高优先级,让用户及时回复;对于好友请求,可以设置普通优先级。

六、文章总结

通过 FCM 集成和自定义推送通道优化,我们可以有效解决 Android 推送通知的可靠性和到达率问题。FCM 提供了强大的消息传递功能,能保证消息的准确送达;自定义推送通道可以根据不同的通知类型设置不同的优先级和提示方式,提高用户体验和到达率。在实际开发中,我们要根据应用的特点和用户的需求,合理使用 FCM 和自定义推送通道,为用户提供更好的服务。