如何在Flutter中实现Android原生风格的Bubble Conversation?
在Flutter中实现Android官方对话气泡(Bubble)方案
目前Flutter框架本身没有提供直接调用Android系统气泡通知的API,要实现Android官方文档定义的对话气泡效果,必须通过**平台通道(MethodChannel)**调用原生Android代码完成,以下是具体实现步骤:
一、Android端配置与代码实现
1. 配置AndroidManifest.xml
先在清单文件中声明气泡相关权限,并设置用于显示对话的Activity属性:
<!-- 声明通知权限(Android 13+必需) --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- 对话页面Activity配置 --> <activity android:name=".ConversationActivity" android:allowEmbedded="true" android:documentLaunchMode="always" android:resizeableActivity="true"> </activity>
2. 编写原生气泡通知工具类
创建NotificationHelper类,负责构建并发送气泡通知(以Kotlin为例):
import android.app.NotificationManager import android.app.PendingIntent import android.content.Context import android.content.Intent import android.os.Build import androidx.core.app.NotificationCompat class NotificationHelper(private val context: Context) { private val notificationManager = context.getSystemService(NotificationManager::class.java) init { // 创建通知渠道(Android O及以上必需) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( "BUBBLE_CHANNEL", "对话气泡频道", NotificationManager.IMPORTANCE_HIGH ).apply { description = "用于显示对话气泡通知" setAllowBubbles(true) } notificationManager.createNotificationChannel(channel) } } fun showBubbleNotification(conversationId: String, title: String, content: String) { // 跳转对话页面的Intent val intent = Intent(context, ConversationActivity::class.java).apply { putExtra("CONVERSATION_ID", conversationId) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK } val pendingIntent = PendingIntent.getActivity( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 构建气泡元数据 val bubbleMetadata = NotificationCompat.BubbleMetadata.Builder( pendingIntent, NotificationCompat.BubbleMetadata.PERSISTENT_ACTION_NONE ).apply { setDesiredHeight(600) // 设置气泡高度 setAutoExpandBubble(true) setSuppressNotification(true) // 隐藏通知栏的普通通知 }.build() // 构建并发送通知 val notification = NotificationCompat.Builder(context, "BUBBLE_CHANNEL") .setSmallIcon(R.drawable.ic_notification) .setContentTitle(title) .setContentText(content) .setPriority(NotificationCompat.PRIORITY_HIGH) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setBubbleMetadata(bubbleMetadata) .build() notificationManager.notify(conversationId.hashCode(), notification) } }
3. 实现对话Activity
ConversationActivity需要支持嵌入气泡并显示对话内容,示例代码:
import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_conversation.* class ConversationActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_conversation) val conversationId = intent.getStringExtra("CONVERSATION_ID") tv_conversation_title.text = "与用户$conversationId 的对话" // 此处可根据conversationId加载对应对话内容 } }
二、Flutter端调用原生方法
通过MethodChannel触发原生的气泡通知逻辑:
import 'package:flutter/services.dart'; class BubbleNotificationService { static const MethodChannel _channel = MethodChannel('bubble_notification'); // 调用原生显示气泡通知 static Future<void> showBubbleNotification({ required String conversationId, required String title, required String content, }) async { try { await _channel.invokeMethod('showBubble', { 'conversationId': conversationId, 'title': title, 'content': content, }); } on PlatformException catch (e) { print('显示气泡失败: ${e.message}'); } } }
在MainActivity中注册MethodChannel(Kotlin):
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "bubble_notification" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "showBubble") { val conversationId = call.argument<String>("conversationId") val title = call.argument<String>("title") val content = call.argument<String>("content") if (conversationId != null && title != null && content != null) { NotificationHelper(this).showBubbleNotification(conversationId, title, content) result.success(null) } else { result.error("INVALID_ARGUMENTS", "参数不能为空", null) } } else { result.notImplemented() } } } }
注意事项
- 气泡功能仅支持Android 10(API 29)及以上系统
- Android 13及以上需动态申请POST_NOTIFICATIONS权限
- 部分厂商对气泡功能有自定义限制,需测试适配
内容的提问来源于stack exchange,提问作者Nguyễn Minh Khoa
相关产品推荐
相关产品推荐

