如何在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
相关产品推荐
相关产品推荐

