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

如何从Android原生Broadcast Receiver向Flutter传输数据流?

Android原生向Flutter同步短信发送报告的两种方案

方案一:通过EventChannel实时传输数据(推荐)

这种方案借助Flutter提供的EventChannel实现原生与Flutter的数据流通信,实时将短信发送状态传递到Flutter端,再由Flutter完成本地数据库更新。

原生端改造步骤

  1. 在MainActivity中注册EventChannel并保存事件接收器
public class MainActivity extends FlutterActivity {
    private static final String RECEIVE_REPORT = "com.esnanosoft/sms_sent_report";
    private EventChannel.EventSink smsSentEventSink;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 注册EventChannel,监听Flutter的订阅请求
        new EventChannel(getFlutterEngine().getDartExecutor().getBinaryMessenger(), RECEIVE_REPORT)
                .setStreamHandler(new EventChannel.StreamHandler() {
                    @Override
                    public void onListen(Object arguments, EventChannel.EventSink sink) {
                        smsSentEventSink = sink; // 保存接收器,用于后续发送事件
                    }

                    @Override
                    public void onCancel(Object arguments) {
                        smsSentEventSink = null; // 取消订阅时清空接收器
                    }
                });
        
        // 将MainActivity实例存入Application,方便BroadcastReceiver调用
        ((MyApplication) getApplication()).setMainActivity(this);
    }

    // 对外提供发送短信报告的方法
    public void sendSmsSentReport(String messageId) {
        if (smsSentEventSink != null) {
            smsSentEventSink.success(messageId); // 向Flutter发送事件数据
        }
    }
}
  1. 自定义Application类存储MainActivity实例
public class MyApplication extends FlutterApplication {
    private MainActivity mainActivity;

    public MainActivity getMainActivity() {
        return mainActivity;
    }

    public void setMainActivity(MainActivity mainActivity) {
        this.mainActivity = mainActivity;
    }
}
  1. 修改SentReceiver,触发事件发送
public class SentReceiver extends BroadcastReceiver {
    private static final String TAG = "SentReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: " + intent.getAction());
        int resultCode = getResultCode();
        boolean successfullySent = resultCode == Activity.RESULT_OK;

        if (successfullySent) {
            String messageId = intent.getStringExtra("messageId");
            Log.e(TAG, "run: " + messageId);
            
            // 从Application获取MainActivity实例,发送事件到Flutter
            MainActivity mainActivity = ((MyApplication) context.getApplicationContext()).getMainActivity();
            if (mainActivity != null) {
                mainActivity.sendSmsSentReport(messageId);
            }
        }
    }
}

Flutter端完善代码

import 'package:flutter/services.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class SmsReportManager {
  static const String RECEIVE_REPORT = "com.esnanosoft/sms_sent_report";
  static const sentSMSChannel = EventChannel(RECEIVE_REPORT);
  StreamSubscription? _streamSubscription;
  Database? _database;

  // 初始化数据库(复用你已有的逻辑)
  Future<void> initDB() async {
    final dbPath = await getDatabasesPath();
    final path = join(dbPath, "ESNanoSoft.db");
    _database = await openDatabase(path, version: 1, onCreate: _createDB, onUpgrade: _onUpgrade);
  }

  // 开始监听原生发送的事件
  void startListening() {
    _streamSubscription = sentSMSChannel.receiveBroadcastStream().listen((event) {
      print("收到短信发送报告:messageId = $event");
      // 更新本地数据库状态
      _updateSmsStatus(event as String, true);
    }, onError: (error) {
      print("接收发送报告出错:$error");
    });
  }

  // 停止监听,避免内存泄漏
  void stopListening() {
    _streamSubscription?.cancel();
    _streamSubscription = null;
  }

  // 更新数据库中短信的发送状态
  Future<void> _updateSmsStatus(String messageId, bool isSent) async {
    if (_database == null) return;
    await _database!.update(
      'sms_table', // 替换为你的实际表名
      {'is_sent': isSent ? 1 : 0}, // 替换为你的状态字段名
      where: 'id = ?', // 替换为你的主键字段
      whereArgs: [messageId],
    );
  }

  // 数据库创建和升级逻辑(复用你已有的代码)
  void _createDB(Database db, int version) {
    // 你的表创建语句
  }

  void _onUpgrade(Database db, int oldVersion, int newVersion) {
    // 你的表升级逻辑
  }
}

方案二:原生直接访问Flutter的SQLite数据库

如果不需要实时通知,也可以让原生直接定位到Flutter的SQLite数据库文件,直接执行更新操作。

原生端修改SentReceiver

public class SentReceiver extends BroadcastReceiver {
    private static final String TAG = "SentReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: " + intent.getAction());
        int resultCode = getResultCode();
        boolean successfullySent = resultCode == Activity.RESULT_OK;

        if (successfullySent) {
            String messageId = intent.getStringExtra("messageId");
            Log.e(TAG, "run: " + messageId);
            
            // 将数据库操作放到子线程,避免主线程ANR
            new Thread(() -> {
                // 获取Flutter SQLite数据库的路径
                String dbDir = context.getFilesDir().getParentFile().getPath() + "/databases";
                String dbPath = dbDir + "/ESNanoSoft.db";
                
                // 打开数据库并更新状态
                SQLiteDatabase db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READWRITE);
                ContentValues values = new ContentValues();
                values.put("is_sent", 1); // 替换为你的状态字段名,1表示发送成功
                db.update("sms_table", values, "id = ?", new String[]{messageId}); // 替换为你的表名和主键
                
                db.close();
            }).start();
        }
    }
}

注意事项

  • 原生端的表结构、字段名必须与Flutter端完全一致,否则会触发数据库异常
  • 数据库版本升级时,原生端的升级逻辑需要和Flutter端保持同步
  • 必须在子线程中执行数据库操作,避免BroadcastReceiver在主线程执行耗时操作导致ANR

内容的提问来源于stack exchange,提问作者SALMAN ABOHOLIQAH

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:45:39