You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native Android中结合OneSignal实现类WhatsApp通话的锁屏全屏通知

在React Native Android中基于OneSignal实现全屏锁屏通话通知方案

要实现类似WhatsApp的全屏通话通知(含锁屏显示),核心是通过自定义Android原生通知服务扩展OneSignal的默认行为,结合高优先级通知渠道与全屏Activity来达成。以下是可稳定运行的实现步骤:

1. 基础环境准备

确保已完成react-native-onesignal的集成与初始化,项目能正常接收普通OneSignal通知。

2. 自定义OneSignal通知服务

创建原生Java类接管通话类型通知的构建逻辑,替代OneSignal默认通知:

// android/app/src/main/java/[你的包名]/CustomNotificationService.java
import com.onesignal.OSNotificationReceivedEvent;
import com.onesignal.OneSignalNotificationService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.app.PendingIntent;
import android.content.Intent;
import androidx.core.app.NotificationCompat;

public class CustomNotificationService extends OneSignalNotificationService {
    @Override
    void notificationReceived(OSNotificationReceivedEvent event) {
        // 仅处理标记为通话类型的通知
        if ("call".equals(event.getNotification().getAdditionalData().optString("type"))) {
            Context context = getApplicationContext();
            NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

            // 创建高优先级通话通知渠道(Android O+ 必填)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationChannel callChannel = new NotificationChannel(
                    "call_channel", 
                    "通话通知", 
                    NotificationManager.IMPORTANCE_HIGH
                );
                callChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
                callChannel.setSound(null, null); // 可自定义通话铃声
                notificationManager.createNotificationChannel(callChannel);
            }

            // 构建全屏Activity的跳转意图
            Intent fullScreenIntent = new Intent(context, CallFullScreenActivity.class);
            fullScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(
                context, 
                0, 
                fullScreenIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            // 构建通话通知
            NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "call_channel")
                    .setSmallIcon(R.drawable.ic_call) // 替换为你的通话图标
                    .setContentTitle(event.getNotification().getTitle())
                    .setContentText(event.getNotification().getBody())
                    .setPriority(NotificationCompat.PRIORITY_MAX)
                    .setCategory(NotificationCompat.CATEGORY_CALL)
                    .setFullScreenIntent(fullScreenPendingIntent, true)
                    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC);

            // 添加接听/挂断操作按钮
            Intent answerIntent = new Intent(context, CallActionReceiver.class);
            answerIntent.setAction("ANSWER_CALL");
            PendingIntent answerPendingIntent = PendingIntent.getBroadcast(
                context, 
                1, 
                answerIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            Intent declineIntent = new Intent(context, CallActionReceiver.class);
            declineIntent.setAction("DECLINE_CALL");
            PendingIntent declinePendingIntent = PendingIntent.getBroadcast(
                context, 
                2, 
                declineIntent, 
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            builder.addAction(R.drawable.ic_answer, "接听", answerPendingIntent)
                    .addAction(R.drawable.ic_decline, "挂断", declinePendingIntent);

            // 发送自定义通知并取消OneSignal默认通知
            notificationManager.notify(1001, builder.build());
            event.complete(null);
        } else {
            // 非通话通知沿用OneSignal默认逻辑
            event.complete(event.getNotification());
        }
    }
}

3. 实现全屏通话Activity

创建锁屏时可唤醒并显示的全屏通话界面:

配置全屏主题

在res/values/styles.xml中添加主题:

<style name="CallFullScreenTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowShowWallpaper">true</item>
    <item name="android:windowAllowLockScreenDecorations">true</item>
    <item name="android:windowIsTranslucent">false</item>
</style>

创建全屏Activity类

// android/app/src/main/java/[你的包名]/CallFullScreenActivity.java
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.WindowManager;

public class CallFullScreenActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 允许锁屏时显示、唤醒屏幕、解锁键盘
        getWindow().addFlags(
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
        );
        setContentView(R.layout.activity_call_fullscreen); // 替换为你的通话界面布局
    }
}

设计通话界面布局

创建res/layout/activity_call_fullscreen.xml,添加来电人信息、接听/挂断按钮等UI元素,示例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:background="@android:color/black">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="张三正在呼叫你"
        android:textColor="@android:color/white"
        android:textSize="24sp"/>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="80dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_answer"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/ic_answer"
            android:layout_marginRight="40dp"/>

        <Button
            android:id="@+id/btn_decline"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="@drawable/ic_decline"/>
    </LinearLayout>
</LinearLayout>

4. 实现通话操作广播接收器

处理通知栏和全屏界面的接听/挂断操作:

// android/app/src/main/java/[你的包名]/CallActionReceiver.java
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.app.NotificationManager;

public class CallActionReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        // 取消通话通知
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancel(1001);

        switch (intent.getAction()) {
            case "ANSWER_CALL":
                // 跳转至通话页面或处理接听逻辑
                Intent answerIntent = new Intent(context, CallActivity.class);
                answerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(answerIntent);
                break;
            case "DECLINE_CALL":
                // 处理挂断逻辑(如通知服务器、结束通话进程)
                break;
        }
    }
}

5. 注册组件到AndroidManifest.xml

在AndroidManifest.xml中添加以下配置:

<!-- 注册自定义通知服务 -->
<service
    android:name=".CustomNotificationService"
    android:permission="android.permission.BIND_JOB_SERVICE">
    <intent-filter>
        <action android:name="com.onesignal.NotificationExtender" />
    </intent-filter>
</service>

<!-- 注册全屏通话Activity -->
<activity
    android:name=".CallFullScreenActivity"
    android:theme="@style/CallFullScreenTheme"
    android:launchMode="singleTask"
    android:excludeFromRecents="true" />

<!-- 注册通话操作广播接收器 -->
<receiver android:name=".CallActionReceiver">
    <intent-filter>
        <action android:name="ANSWER_CALL" />
        <action android:name="DECLINE_CALL" />
    </intent-filter>
</receiver>

<!-- 添加必要权限 -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />

6. React Native端触发通话通知

调用OneSignal接口发送标记为call类型的通知:

import OneSignal from 'react-native-onesignal';

// 发送通话通知给指定用户
const sendCallNotification = (targetPlayerId, callerName) => {
    OneSignal.postNotification({
        contents: { en: `${callerName}正在呼叫你` },
        headings: { en: '来电通知' },
        include_player_ids: [targetPlayerId],
        data: { type: 'call', callerId: '你的通话ID' },
        android_channel_id: 'call_channel'
    });
};

关键注意事项

  • 权限引导:需引导用户开启应用的「锁屏显示通知」权限,部分Android版本需手动授权。
  • Android版本适配:Android 12+ 的PendingIntent必须添加FLAG_IMMUTABLE或FLAG_MUTABLE,上述代码已适配。
  • 通知渠道优先级:必须设置为IMPORTANCE_HIGH,否则无法触发全屏唤醒效果。
  • 真机测试:模拟器无法完全模拟锁屏状态下的通知行为,务必在真机上验证。

内容的提问来源于stack exchange,提问作者Shafaq Shaikh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:44:51