Files
push_server/Android高优先级通知渠道配置指南.md
2025-12-31 10:42:38 +08:00

14 KiB
Raw Permalink Blame History

Android 高优先级通知渠道配置指南

概述

在 Android 应用中配置高优先级通知渠道,可以实现强提醒效果,包括:

  • ✓ 灭屏状态下的声音和振动提醒
  • ✓ 锁屏界面显示通知
  • ✓ 通知栏显示消息
  • ✓ 绕过免打扰模式(部分情况下)

实现步骤

1. 创建高优先级通知渠道

在应用启动时Application 或 MainActivity 的 onCreate 中)创建通知渠道:

import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Build;

public class MyApplication extends Application {
    
    public static final String CHANNEL_ID_IMPORTANT = "important_messages";
    public static final String CHANNEL_NAME_IMPORTANT = "重要消息";
    
    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannels();
    }
    
    private void createNotificationChannels() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager = 
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            
            // 创建高优先级通知渠道
            NotificationChannel importantChannel = new NotificationChannel(
                CHANNEL_ID_IMPORTANT,
                CHANNEL_NAME_IMPORTANT,
                NotificationManager.IMPORTANCE_HIGH  // 高优先级
            );
            
            // 设置渠道描述
            importantChannel.setDescription("重要消息通知,包括即时聊天、语音通话等");
            
            // 启用指示灯
            importantChannel.enableLights(true);
            importantChannel.setLightColor(android.graphics.Color.BLUE);
            
            // 启用振动
            importantChannel.enableVibration(true);
            // 设置振动模式等待0ms振动1000ms暂停500ms再振动1000ms
            importantChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
            
            // 设置通知声音(使用系统默认通知声音)
            importantChannel.setSound(
                android.provider.Settings.System.DEFAULT_NOTIFICATION_URI,
                new AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                    .build()
            );
            
            // 设置绕过免打扰模式(需要用户授权)
            // importantChannel.setBypassDnd(true);
            
            // 在锁屏上显示
            importantChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
            
            // 创建渠道
            notificationManager.createNotificationChannel(importantChannel);
        }
    }
}

2. 在 AndroidManifest.xml 中注册 Application

<application
    android:name=".MyApplication"
    ...>
    ...
</application>

3. 处理 OPPO 推送消息时使用该渠道

当收到 OPPO 推送消息时,在显示通知时指定使用该渠道:

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Build;

public class PushMessageHandler {
    
    private Context context;
    private NotificationManager notificationManager;
    
    public PushMessageHandler(Context context) {
        this.context = context;
        this.notificationManager = 
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    }
    
    /**
     * 显示推送通知
     * @param title 通知标题
     * @param content 通知内容
     * @param data 推送数据(可选)
     */
    public void showNotification(String title, String content, Map<String, String> data) {
        // 创建点击意图
        Intent intent = new Intent(context, MainActivity.class);
        if (data != null) {
            for (Map.Entry<String, String> entry : data.entrySet()) {
                intent.putExtra(entry.getKey(), entry.getValue());
            }
        }
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        
        PendingIntent pendingIntent = PendingIntent.getActivity(
            context,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
        );
        
        // 构建通知
        Notification.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Android 8.0 及以上使用渠道
            builder = new Notification.Builder(context, MyApplication.CHANNEL_ID_IMPORTANT);
        } else {
            // Android 8.0 以下
            builder = new Notification.Builder(context);
        }
        
        builder.setContentTitle(title)
               .setContentText(content)
               .setSmallIcon(R.drawable.ic_notification)  // 小图标
               .setLargeIcon(BitmapFactory.decodeResource(
                   context.getResources(), 
                   R.drawable.ic_launcher
               ))  // 大图标
               .setContentIntent(pendingIntent)
               .setAutoCancel(true)  // 点击后自动取消
               .setPriority(Notification.PRIORITY_HIGH)  // 高优先级Android 7.1及以下)
               .setDefaults(Notification.DEFAULT_ALL)  // 使用默认声音、振动、灯光
               .setWhen(System.currentTimeMillis())
               .setShowWhen(true);
        
        // 设置通知样式(可选)
        Notification.BigTextStyle bigTextStyle = new Notification.BigTextStyle();
        bigTextStyle.bigText(content);
        builder.setStyle(bigTextStyle);
        
        // 显示通知
        int notificationId = (int) System.currentTimeMillis();
        notificationManager.notify(notificationId, builder.build());
    }
}

4. 在 OPPO 推送接收处理中使用

import com.heytap.msp.push.mode.DataMessage;
import com.heytap.msp.push.service.DataMessageCallbackService;

public class OppoPushMessageService extends DataMessageCallbackService {
    
    @Override
    public void processMessage(Context context, DataMessage dataMessage) {
        super.processMessage(context, dataMessage);
        
        // 获取推送消息内容
        String title = dataMessage.getTitle();
        String content = dataMessage.getContent();
        Map<String, String> extra = dataMessage.getExtra();
        
        // 使用高优先级通知渠道显示通知
        PushMessageHandler handler = new PushMessageHandler(context);
        handler.showNotification(title, content, extra);
    }
}

5. 在 AndroidManifest.xml 中注册推送服务

<application>
    ...
    
    <!-- OPPO 推送服务 -->
    <service
        android:name=".OppoPushMessageService"
        android:permission="com.heytap.mcs.permission.SEND_PUSH_MESSAGE"
        android:exported="true">
        <intent-filter>
            <action android:name="com.heytap.mcs.action.RECEIVE_MCS_MESSAGE" />
        </intent-filter>
    </service>
    
    ...
</application>

完整示例代码

Application.java

package com.xunpaisoft.social;

import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.media.AudioAttributes;
import android.os.Build;

public class MyApplication extends Application {
    
    public static final String CHANNEL_ID_IMPORTANT = "important_messages";
    public static final String CHANNEL_NAME_IMPORTANT = "重要消息";
    
    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannels();
    }
    
    private void createNotificationChannels() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationManager notificationManager = 
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
            
            // 检查渠道是否已存在
            if (notificationManager.getNotificationChannel(CHANNEL_ID_IMPORTANT) == null) {
                NotificationChannel importantChannel = new NotificationChannel(
                    CHANNEL_ID_IMPORTANT,
                    CHANNEL_NAME_IMPORTANT,
                    NotificationManager.IMPORTANCE_HIGH
                );
                
                importantChannel.setDescription("重要消息通知");
                importantChannel.enableLights(true);
                importantChannel.enableVibration(true);
                importantChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
                importantChannel.setSound(
                    android.provider.Settings.System.DEFAULT_NOTIFICATION_URI,
                    new AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                        .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                        .build()
                );
                
                notificationManager.createNotificationChannel(importantChannel);
            }
        }
    }
}

PushNotificationHelper.java

package com.xunpaisoft.social;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;

public class PushNotificationHelper {
    
    private static final String CHANNEL_ID = MyApplication.CHANNEL_ID_IMPORTANT;
    
    public static void showNotification(Context context, String title, String content) {
        NotificationManager notificationManager = 
            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        
        Intent intent = new Intent(context, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        
        PendingIntent pendingIntent = PendingIntent.getActivity(
            context,
            0,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT | 
            (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_IMMUTABLE : 0)
        );
        
        Notification.Builder builder;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder = new Notification.Builder(context, CHANNEL_ID);
        } else {
            builder = new Notification.Builder(context);
            builder.setPriority(Notification.PRIORITY_HIGH);
        }
        
        builder.setContentTitle(title)
               .setContentText(content)
               .setSmallIcon(R.drawable.ic_notification)
               .setContentIntent(pendingIntent)
               .setAutoCancel(true)
               .setDefaults(Notification.DEFAULT_ALL);
        
        int notificationId = (int) System.currentTimeMillis();
        notificationManager.notify(notificationId, builder.build());
    }
}

权限配置

AndroidManifest.xml 中添加必要权限:

<manifest>
    <!-- 通知权限 -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
    
    <!-- 振动权限 -->
    <uses-permission android:name="android.permission.VIBRATE" />
    
    <!-- 唤醒锁(可选,用于确保通知及时送达) -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    
    <application>
        ...
    </application>
</manifest>

Android 13+ (API 33+) 权限处理

Android 13 及以上版本需要动态申请通知权限:

import android.Manifest;
import android.content.pm.PackageManager;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {
    
    private static final int REQUEST_NOTIFICATION_PERMISSION = 1001;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // Android 13+ 需要动态申请通知权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) 
                != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(
                    this,
                    new String[]{Manifest.permission.POST_NOTIFICATIONS},
                    REQUEST_NOTIFICATION_PERMISSION
                );
            }
        }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_NOTIFICATION_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限已授予
            }
        }
    }
}

测试验证

  1. 安装应用:在 OPPO 手机上安装配置好的应用
  2. 发送推送:使用之前的测试脚本发送推送消息
  3. 验证效果
    • ✓ 灭屏状态下应该有声音和振动
    • ✓ 锁屏界面应该显示通知
    • ✓ 通知栏应该显示消息
    • ✓ 通知应该使用"重要消息"渠道

注意事项

  1. 渠道创建时机:通知渠道应该在应用启动时创建,且只需创建一次
  2. 渠道优先级IMPORTANCE_HIGH 表示高优先级,会显示在通知栏顶部并发出声音
  3. 用户设置:用户可以在系统设置中修改渠道的提醒方式,但高优先级渠道默认会启用声音和振动
  4. 兼容性Android 8.0 (API 26) 及以上版本才支持通知渠道,低版本会自动使用传统通知方式

与 OPPO 推送集成

当收到 OPPO 推送消息时,在消息处理回调中使用配置好的通知渠道显示通知即可。这样即使不使用通讯与服务类消息权限,也能实现强提醒效果。